1 /*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef ANDROID_INCLUDE_HARDWARE_QEMUD_H
18 #define ANDROID_INCLUDE_HARDWARE_QEMUD_H
19
20 #include <cutils/sockets.h>
21 #include "qemu_pipe.h"
22
23 /* the following is helper code that is used by the QEMU-specific
24 * hardware HAL modules to communicate with the emulator program
25 * through the 'qemud' multiplexing daemon, or through the qemud
26 * pipe.
27 *
28 * see the documentation comments for details in
29 * development/emulator/qemud/qemud.c
30 *
31 * all definitions here are built into the HAL module to avoid
32 * having to write a tiny shared library for this.
33 */
34
35 /* we expect the D macro to be defined to a function macro
36 * that sends its formatted string argument(s) to the log.
37 * If not, ignore the traces.
38 */
39 # define D(...) ((void)0)
40
41 static __inline__ int
qemud_channel_open(const char * name)42 qemud_channel_open(const char* name)
43 {
44 int fd;
45 int namelen = strlen(name);
46 char answer[2];
47 char pipe_name[256];
48
49 /* First, try to connect to the pipe. */
50 snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name);
51 fd = qemu_pipe_open(pipe_name);
52 D("%s: pipe name %s (name %s) fd %d", __FUNCTION__, pipe_name, name, fd);
53 if (fd < 0) {
54 D("QEMUD pipe is not available for %s: %s", name, strerror(errno));
55 /* If pipe is not available, connect to qemud control socket */
56 fd = socket_local_client( "qemud",
57 ANDROID_SOCKET_NAMESPACE_RESERVED,
58 SOCK_STREAM );
59 if (fd < 0) {
60 D("no qemud control socket: %s", strerror(errno));
61 return -1;
62 }
63
64 /* send service name to connect */
65 if (!WriteFully(fd, name, namelen)) {
66 D("can't send service name to qemud: %s",
67 strerror(errno));
68 close(fd);
69 return -1;
70 }
71
72 /* read answer from daemon */
73 if (!ReadFully(fd, answer, 2) ||
74 answer[0] != 'O' || answer[1] != 'K') {
75 D("cant' connect to %s service through qemud", name);
76 close(fd);
77 return -1;
78 }
79 }
80 return fd;
81 }
82
83 static __inline__ int
qemud_channel_send(int fd,const void * msg,int msglen)84 qemud_channel_send(int fd, const void* msg, int msglen)
85 {
86 char header[5];
87
88 if (msglen < 0)
89 msglen = strlen((const char*)msg);
90
91 if (msglen == 0)
92 return 0;
93
94 snprintf(header, sizeof header, "%04x", msglen);
95 if (!WriteFully(fd, header, 4)) {
96 D("can't write qemud frame header: %s", strerror(errno));
97 return -1;
98 }
99
100 if (!WriteFully(fd, msg, msglen)) {
101 D("can4t write qemud frame payload: %s", strerror(errno));
102 return -1;
103 }
104 return 0;
105 }
106
107 static __inline__ int
qemud_channel_recv(int fd,void * msg,int msgsize)108 qemud_channel_recv(int fd, void* msg, int msgsize)
109 {
110 char header[5];
111 int size, avail;
112
113 if (!ReadFully(fd, header, 4)) {
114 D("can't read qemud frame header: %s", strerror(errno));
115 return -1;
116 }
117 header[4] = 0;
118 if (sscanf(header, "%04x", &size) != 1) {
119 D("malformed qemud frame header: '%.*s'", 4, header);
120 return -1;
121 }
122 if (size > msgsize)
123 return -1;
124
125 if (!ReadFully(fd, msg, size)) {
126 D("can't read qemud frame payload: %s", strerror(errno));
127 return -1;
128 }
129 return size;
130 }
131
132 #endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_H */
133