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
22/* the following is helper code that is used by the QEMU-specific
23 * hardware HAL modules to communicate with the emulator program
24 * through the 'qemud' multiplexing daemon.
25 *
26 * see the documentation comments for details in
27 * development/emulator/qemud/qemud.c
28 *
29 * all definitions here are built into the HAL module to avoid
30 * having to write a tiny shared library for this.
31 */
32
33/* we expect the D macro to be defined to a function macro
34 * that sends its formatted string argument(s) to the log.
35 * If not, ignore the traces.
36 */
37#ifndef D
38#  define  D(...)  ((void)0)
39#endif
40
41static __inline__ int
42qemud_fd_write(int  fd, const void*  buff, int  len)
43{
44    int  len2;
45    do {
46        len2 = write(fd, buff, len);
47    } while (len2 < 0 && errno == EINTR);
48    return len2;
49}
50
51static __inline__ int
52qemud_fd_read(int  fd, void*  buff, int  len)
53{
54    int  len2;
55    do {
56        len2 = read(fd, buff, len);
57    } while (len2 < 0 && errno == EINTR);
58    return len2;
59}
60
61static __inline__ int
62qemud_channel_open(const char*  name)
63{
64    int  fd;
65    int  namelen = strlen(name);
66    char answer[2];
67
68    /* connect to qemud control socket */
69    fd = socket_local_client( "qemud",
70                              ANDROID_SOCKET_NAMESPACE_RESERVED,
71                              SOCK_STREAM );
72    if (fd < 0) {
73        D("no qemud control socket: %s", strerror(errno));
74        return -1;
75    }
76
77    /* send service name to connect */
78    if (qemud_fd_write(fd, name, namelen) != namelen) {
79        D("can't send service name to qemud: %s",
80           strerror(errno));
81        close(fd);
82        return -1;
83    }
84
85    /* read answer from daemon */
86    if (qemud_fd_read(fd, answer, 2) != 2 ||
87        answer[0] != 'O' || answer[1] != 'K') {
88        D("cant' connect to %s service through qemud", name);
89        close(fd);
90        return -1;
91    }
92    return fd;
93}
94
95static __inline__ int
96qemud_channel_send(int  fd, const void*  msg, int  msglen)
97{
98    char  header[5];
99
100    if (msglen < 0)
101        msglen = strlen((const char*)msg);
102
103    if (msglen == 0)
104        return 0;
105
106    snprintf(header, sizeof header, "%04x", msglen);
107    if (qemud_fd_write(fd, header, 4) != 4) {
108        D("can't write qemud frame header: %s", strerror(errno));
109        return -1;
110    }
111
112    if (qemud_fd_write(fd, msg, msglen) != msglen) {
113        D("can4t write qemud frame payload: %s", strerror(errno));
114        return -1;
115    }
116    return 0;
117}
118
119static __inline__ int
120qemud_channel_recv(int  fd, void*  msg, int  msgsize)
121{
122    char  header[5];
123    int   size, avail;
124
125    if (qemud_fd_read(fd, header, 4) != 4) {
126        D("can't read qemud frame header: %s", strerror(errno));
127        return -1;
128    }
129    header[4] = 0;
130    if (sscanf(header, "%04x", &size) != 1) {
131        D("malformed qemud frame header: '%.*s'", 4, header);
132        return -1;
133    }
134    if (size > msgsize)
135        return -1;
136
137    if (qemud_fd_read(fd, msg, size) != size) {
138        D("can't read qemud frame payload: %s", strerror(errno));
139        return -1;
140    }
141    return size;
142}
143
144#endif /* ANDROID_INCLUDE_HARDWARE_QEMUD_H */
145