2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 /* this file contains various functions used by all libhardware modules
18 * that support QEMU emulation
21 #define LOG_TAG "hardware-qemu"
22 #include <cutils/log.h>
23 #include <cutils/properties.h>
24 #include <cutils/sockets.h>
34 # define D(...) LOGD(__VA_ARGS__)
36 # define D(...) ((void)0)
43 static int in_qemu = -1;
45 if (__builtin_expect(in_qemu < 0,0)) {
46 char propBuf[PROPERTY_VALUE_MAX];
47 property_get("ro.kernel.qemu", propBuf, "");
48 in_qemu = (propBuf[0] == '1');
55 qemu_channel_open( QemuChannel* channel,
61 /* initialize the channel is needed */
62 if (!channel->is_inited)
66 // try to connect to qemud socket first
68 snprintf(channel->device, sizeof channel->device,
71 fd = socket_local_client( channel->device,
72 ANDROID_SOCKET_NAMESPACE_RESERVED,
75 D("no '%s' control socket available: %s",
76 channel->device, strerror(errno));
80 channel->is_qemud = 1;
84 // otherwise, look for a kernel-provided device name
86 char key[PROPERTY_KEY_MAX];
87 char prop[PROPERTY_VALUE_MAX];
90 ret = snprintf(key, sizeof key, "ro.kernel.android.%s", name);
91 if (ret >= (int)sizeof key)
94 if (property_get(key, prop, "") == 0) {
95 D("no kernel-provided %s device name", name);
99 ret = snprintf(channel->device, sizeof channel->device,
101 if (ret >= (int)sizeof channel->device) {
102 D("%s device name too long: '%s'", name, prop);
105 channel->is_tty = !memcmp("/dev/tty", channel->device, 8);
110 channel->is_available = done;
111 channel->is_inited = 1;
114 /* try to open the file */
115 if (!channel->is_available) {
118 } else if (channel->is_qemud) {
120 fd = socket_local_client( channel->device,
121 ANDROID_SOCKET_NAMESPACE_RESERVED,
123 } while (fd < 0 && errno == EINTR);
126 fd = open(channel->device, mode);
127 } while (fd < 0 && errno == EINTR);
129 /* disable ECHO on serial lines */
130 if (fd >= 0 && channel->is_tty) {
132 tcgetattr( fd, &ios );
133 ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */
134 tcsetattr( fd, TCSANOW, &ios );
142 qemu_command_vformat( char* buffer,
153 len = vsnprintf(buffer+4, buffer_size-4, format, args);
154 if (len >= buffer_size-4)
157 snprintf(header, sizeof header, "%04x", len);
158 memcpy(buffer, header, 4);
163 qemu_command_format( char* buffer,
171 va_start(args, format);
172 ret = qemu_command_format(buffer, buffer_size, format, args);
179 qemu_control_fd(void)
181 static QemuChannel channel[1];
184 fd = qemu_channel_open( channel, "control", O_RDWR );
186 D("%s: could not open control channel: %s", __FUNCTION__,
193 qemu_control_write( int fd, const char* cmd, int len )
197 len2 = write(fd, cmd, len);
198 } while (len2 < 0 && errno == EINTR);
203 qemu_control_read( int fd, char* buff, int len )
207 len2 = read(fd, buff, len);
208 } while (len2 < 0 && errno == EINTR);
213 qemu_control_send(const char* cmd, int len)
222 fd = qemu_control_fd();
226 len2 = qemu_control_write(fd, cmd, len);
229 D("%s: could not send everything %d < %d",
230 __FUNCTION__, len2, len);
238 qemu_control_command( const char* fmt, ... )
245 len = qemu_command_vformat( command, sizeof command, fmt, args );
248 if (len < 0 || len >= (int)sizeof command) {
250 D("%s: could not send: %s", __FUNCTION__, strerror(errno));
252 D("%s: too large %d > %d", __FUNCTION__, len, (int)(sizeof command));
258 return qemu_control_send( command, len );
261 extern int qemu_control_query( const char* question, int questionlen,
262 char* answer, int answersize )
264 int ret, fd, len, result = -1;
265 char header[5], *end;
267 if (questionlen <= 0) {
272 fd = qemu_control_fd();
276 ret = qemu_control_write( fd, question, questionlen );
277 if (ret != questionlen) {
278 D("%s: could not write all: %d < %d", __FUNCTION__,
283 /* read a 4-byte header giving the length of the following content */
284 ret = qemu_control_read( fd, header, 4 );
286 D("%s: could not read header (%d != 4)",
292 len = strtol( header, &end, 16 );
293 if ( len < 0 || end == NULL || end != header+4 || len > answersize ) {
294 D("%s: could not parse header: '%s'",
295 __FUNCTION__, header);
299 /* read the answer */
300 ret = qemu_control_read( fd, answer, len );
302 D("%s: could not read all of answer %d < %d",
303 __FUNCTION__, ret, len);