1cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/*
2cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
4cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * you may not use this file except in compliance with the License.
6cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * You may obtain a copy of the License at
7cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
8cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
10cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * See the License for the specific language governing permissions and
14cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * limitations under the License.
15cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project */
16cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
17cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/* this file contains various functions used by all libhardware modules
18cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * that support QEMU emulation
19cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project */
20cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "qemu.h"
21cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define  LOG_TAG  "hardware-qemu"
22cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <cutils/log.h>
23cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <cutils/properties.h>
24cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <cutils/sockets.h>
25cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <errno.h>
26cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <fcntl.h>
27cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <termios.h>
28cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <stdio.h>
29cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <stdarg.h>
30cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
31cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define  QEMU_DEBUG  0
32cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
33cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#if QEMU_DEBUG
34b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block#  define  D(...)   ALOGD(__VA_ARGS__)
35cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#else
36cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#  define  D(...)   ((void)0)
37cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#endif
38cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
392dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine#include "hardware/qemu_pipe.h"
40cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
41cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint
42cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectqemu_check(void)
43cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
44cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    static int  in_qemu = -1;
45cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
46cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (__builtin_expect(in_qemu < 0,0)) {
47cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        char  propBuf[PROPERTY_VALUE_MAX];
48cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        property_get("ro.kernel.qemu", propBuf, "");
49cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        in_qemu = (propBuf[0] == '1');
50cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
51cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return in_qemu;
52cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
53cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
54e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectstatic int
55e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectqemu_fd_write( int  fd, const char*  cmd, int  len )
56e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project{
57e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    int  len2;
58e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    do {
59e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        len2 = write(fd, cmd, len);
60e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    } while (len2 < 0 && errno == EINTR);
61e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    return len2;
62e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project}
63e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
64e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectstatic int
65e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectqemu_fd_read( int  fd, char*  buff, int  len )
66e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project{
67e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    int  len2;
68e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    do {
69e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        len2 = read(fd, buff, len);
70e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    } while (len2 < 0 && errno == EINTR);
71e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    return len2;
72e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project}
73e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
742dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkinestatic int
752dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkineqemu_channel_open_qemud_pipe( QemuChannel*  channel,
762dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine                              const char*   name )
772dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine{
782dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    int   fd;
792dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    char  pipe_name[512];
802dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine
812dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    snprintf(pipe_name, sizeof(pipe_name), "qemud:%s", name);
822dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    fd = qemu_pipe_open(pipe_name);
832dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    if (fd < 0) {
842dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine        D("no qemud pipe: %s", strerror(errno));
852dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine        return -1;
862dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    }
872dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine
882dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    channel->is_qemud = 1;
892dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    channel->fd       = fd;
902dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine    return 0;
912dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine}
92e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
93e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectstatic int
94e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectqemu_channel_open_qemud( QemuChannel*  channel,
95e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                         const char*   name )
96e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project{
97e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    int   fd, ret, namelen = strlen(name);
98e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    char  answer[2];
99e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
100e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    fd = socket_local_client( "qemud",
101e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                              ANDROID_SOCKET_NAMESPACE_RESERVED,
102e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                              SOCK_STREAM );
103e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (fd < 0) {
104e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("no qemud control socket: %s", strerror(errno));
105e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
106e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
107e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
108e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    /* send service name to connect */
109e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (qemu_fd_write(fd, name, namelen) != namelen) {
110e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("can't send service name to qemud: %s",
111e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project           strerror(errno));
112e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        close(fd);
113e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
114e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
115e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
116e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    /* read answer from daemon */
117e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (qemu_fd_read(fd, answer, 2) != 2 ||
118e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        answer[0] != 'O' || answer[1] != 'K') {
119e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("cant' connect to %s service through qemud", name);
120e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        close(fd);
121e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
122e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
123e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
124e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    channel->is_qemud = 1;
125e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    channel->fd       = fd;
126e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    return 0;
127e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project}
128e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
129e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
130e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectstatic int
131e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectqemu_channel_open_qemud_old( QemuChannel*  channel,
132e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                             const char*   name )
133e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project{
134e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    int  fd;
135e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
136e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    snprintf(channel->device, sizeof channel->device,
137e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                "qemud_%s", name);
138e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
139e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    fd = socket_local_client( channel->device,
140e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                              ANDROID_SOCKET_NAMESPACE_RESERVED,
141e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                              SOCK_STREAM );
142e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (fd < 0) {
143e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("no '%s' control socket available: %s",
144e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            channel->device, strerror(errno));
145e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
146e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
147e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
148e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    close(fd);
149e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    channel->is_qemud_old = 1;
150e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    return 0;
151e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project}
152e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
153e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
154e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectstatic int
155e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Projectqemu_channel_open_tty( QemuChannel*  channel,
156e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                       const char*   name,
157e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                       int           mode )
158e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project{
159e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    char   key[PROPERTY_KEY_MAX];
160e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    char   prop[PROPERTY_VALUE_MAX];
161e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    int    ret;
162e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
163e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    ret = snprintf(key, sizeof key, "ro.kernel.android.%s", name);
164e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (ret >= (int)sizeof key)
165e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
166e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
167e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (property_get(key, prop, "") == 0) {
168e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("no kernel-provided %s device name", name);
169e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
170e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
171e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
172e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    ret = snprintf(channel->device, sizeof channel->device,
173e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project                    "/dev/%s", prop);
174e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (ret >= (int)sizeof channel->device) {
175e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        D("%s device name too long: '%s'", name, prop);
176e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
177e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
178e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
179e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    channel->is_tty = !memcmp("/dev/tty", channel->device, 8);
180e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    return 0;
181e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project}
182cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
183cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint
184cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectqemu_channel_open( QemuChannel*  channel,
185cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                   const char*   name,
186cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                   int           mode )
187cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
188cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int  fd = -1;
189cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
190cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* initialize the channel is needed */
191cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!channel->is_inited)
192cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    {
193e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        channel->is_inited = 1;
194cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
195cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        do {
1962dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine            if (qemu_channel_open_qemud_pipe(channel, name) == 0)
1972dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine                break;
1982dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkine
199e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            if (qemu_channel_open_qemud(channel, name) == 0)
200cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                break;
201cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
202e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            if (qemu_channel_open_qemud_old(channel, name) == 0)
203cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                break;
204cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
205e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            if (qemu_channel_open_tty(channel, name, mode) == 0)
206cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                break;
207cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
208e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            channel->is_available = 0;
209e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project            return -1;
210cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        } while (0);
211cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
212e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        channel->is_available = 1;
213cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
214cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
215cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* try to open the file */
216cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!channel->is_available) {
217cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        errno = ENOENT;
218e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return -1;
219e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
220e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
221e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (channel->is_qemud) {
222e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project        return dup(channel->fd);
223e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
224e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project
225e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    if (channel->is_qemud_old) {
226cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        do {
227cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            fd = socket_local_client( channel->device,
228cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                                      ANDROID_SOCKET_NAMESPACE_RESERVED,
229cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                                      SOCK_STREAM );
230cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        } while (fd < 0 && errno == EINTR);
231e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    }
232e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    else /* /dev/ttySn ? */
233e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    {
234cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        do {
235cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            fd = open(channel->device, mode);
236cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        } while (fd < 0 && errno == EINTR);
237cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
238cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        /* disable ECHO on serial lines */
239cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (fd >= 0 && channel->is_tty) {
240cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            struct termios  ios;
241cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            tcgetattr( fd, &ios );
242cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
243cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            tcsetattr( fd, TCSANOW, &ios );
244cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
245cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
246cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return fd;
247cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
248cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
249cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
250cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int
2512dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkineqemu_command_vformat( char*        buffer,
252cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                      int          buffer_size,
253cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                      const char*  format,
254cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                      va_list      args )
255cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
256cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char     header[5];
257cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int      len;
258cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
259cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (buffer_size < 6)
260cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
261cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
262cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    len = vsnprintf(buffer+4, buffer_size-4, format, args);
263cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (len >= buffer_size-4)
264cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
265cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
266cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    snprintf(header, sizeof header, "%04x", len);
267cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    memcpy(buffer, header, 4);
268cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return len + 4;
269cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
270cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
271cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int
2722dbd8949b2ac0aaa98f89a467c14bff857505794Vladimir Chtchetkineqemu_command_format( char*        buffer,
273cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                     int          buffer_size,
274cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                     const char*  format,
275cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                     ... )
276cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
277cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_list  args;
278cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int      ret;
279cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
280cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_start(args, format);
281cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    ret = qemu_command_format(buffer, buffer_size, format, args);
282cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_end(args);
283cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return ret;
284cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
285cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
286cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
287cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int
288cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectqemu_control_fd(void)
289cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
290cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    static QemuChannel  channel[1];
291cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int                 fd;
292cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
293e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    fd = qemu_channel_open( channel, "hw-control", O_RDWR );
294cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (fd < 0) {
295cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not open control channel: %s", __FUNCTION__,
296cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          strerror(errno));
297cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
298cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return fd;
299cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
300cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
301cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int
302cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectqemu_control_send(const char*  cmd, int  len)
303cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
304cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int  fd, len2;
305cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
306cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (len < 0) {
307cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        errno = EINVAL;
308cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
309cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
310cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
311cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fd = qemu_control_fd();
312cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (fd < 0)
313cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
314cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
315e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    len2 = qemu_fd_write(fd, cmd, len);
316cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(fd);
317cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (len2 != len) {
318cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not send everything %d < %d",
319cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          __FUNCTION__, len2, len);
320cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
321cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
322cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
323cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
324cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
325cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
326cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint
327cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectqemu_control_command( const char*  fmt, ... )
328cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
329cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_list  args;
330cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char     command[256];
331cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int      len, fd;
332cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
333cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_start(args, fmt);
334cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    len = qemu_command_vformat( command, sizeof command, fmt, args );
335cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    va_end(args);
336cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
337cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (len < 0 || len >= (int)sizeof command) {
338cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (len < 0) {
339cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            D("%s: could not send: %s", __FUNCTION__, strerror(errno));
340cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        } else {
341cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            D("%s: too large %d > %d", __FUNCTION__, len, (int)(sizeof command));
342cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
343cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        errno = EINVAL;
344cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
345cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
346cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
347cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return qemu_control_send( command, len );
348cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
349cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
350cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int  qemu_control_query( const char*  question, int  questionlen,
351cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                                char*        answer,   int  answersize )
352cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
353cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int   ret, fd, len, result = -1;
354cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char  header[5], *end;
355cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
356cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (questionlen <= 0) {
357cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        errno = EINVAL;
358cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
359cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
360cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
361cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fd = qemu_control_fd();
362cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (fd < 0)
363cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
364cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
365e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    ret = qemu_fd_write( fd, question, questionlen );
366cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret != questionlen) {
367cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not write all: %d < %d", __FUNCTION__,
368cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          ret, questionlen);
369cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        goto Exit;
370cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
371cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
372cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* read a 4-byte header giving the length of the following content */
373e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    ret = qemu_fd_read( fd, header, 4 );
374cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret != 4) {
375cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not read header (%d != 4)",
376cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          __FUNCTION__, ret);
377cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        goto Exit;
378cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
379cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
380e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    header[4] = 0;
381cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    len = strtol( header, &end,  16 );
382cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if ( len < 0 || end == NULL || end != header+4 || len > answersize ) {
383cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not parse header: '%s'",
384cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          __FUNCTION__, header);
385cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        goto Exit;
386cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
387cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
388cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* read the answer */
389e18b7b21c2fe0788e6cf1a1a055a25c2e5bc2dd8The Android Open Source Project    ret = qemu_fd_read( fd, answer, len );
390cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret != len) {
391cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        D("%s: could not read all of answer %d < %d",
392cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project          __FUNCTION__, ret, len);
393cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        goto Exit;
394cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
395cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
396cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    result = len;
397cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
398cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source ProjectExit:
399cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(fd);
400cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return result;
401cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
402