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