blob: 1d2498e7524aefa401c7eabd5fd65e6a705a5828 [file] [log] [blame]
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -08001/*
2 * Copyright (C) 2011 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#include "qemu-common.h"
18#include "android/globals.h" /* for android_hw */
19#include "android/hw-qemud.h"
20#include "android/utils/misc.h"
21#include "android/utils/system.h"
22#include "android/utils/debug.h"
23#include "android/adb-server.h"
24#include "android/adb-qemud.h"
25
26#define E(...) derror(__VA_ARGS__)
27#define W(...) dwarning(__VA_ARGS__)
28#define D(...) VERBOSE_PRINT(adbclient,__VA_ARGS__)
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -080029#define DD(...) VERBOSE_PRINT(adb,__VA_ARGS__)
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080030#define D_ACTIVE VERBOSE_CHECK(adbclient)
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -080031#define DD_ACTIVE VERBOSE_CHECK(adb)
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080032#define QB(b, s) quote_bytes((const char*)b, (s < 32) ? s : 32)
33
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -080034#define SERVICE_NAME "adb"
35#define DEBUG_SERVICE_NAME "adb-debug"
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080036
37/* Enumerates ADB client state values. */
38typedef enum AdbClientState {
39 /* Waiting on a connection from ADB host. */
40 ADBC_STATE_WAIT_ON_HOST,
41 /* ADB host is connected. Waiting on the transport initialization completion
42 * in the guest. */
43 ADBC_STATE_HOST_CONNECTED,
44 /* Connection between ADB host and ADB guest is fully established. */
45 ADBC_STATE_CONNECTED,
46 /* ADB host has been disconnected. */
47 ADBC_STATE_HOST_DISCONNECTED,
48 /* ADB guest has been disconnected. */
49 ADBC_STATE_GUEST_DISCONNECTED,
50} AdbClientState;
51
52/* ADB client descriptor. */
53typedef struct AdbClient AdbClient;
54struct AdbClient {
55 /* Opaque pointer returned from adb_server_register_guest API. */
56 void* opaque;
57 /* QEMUD client pipe for this client. */
58 QemudClient* qemud_client;
59 /* Connection state. */
60 AdbClientState state;
61};
62
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -080063/* ADB debugging client descriptor. */
64typedef struct AdbDbgClient AdbDbgClient;
65struct AdbDbgClient {
66 /* QEMUD client pipe for this client. */
67 QemudClient* qemud_client;
68};
69
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080070/********************************************************************************
71 * ADB host communication.
72 *******************************************************************************/
73
74/* A callback that is invoked when the host is connected.
75 * Param:
76 * opaque - AdbClient instance.
77 * connection - An opaque pointer that identifies connection with the ADB host.
78 */
79static void
80_adb_on_host_connected(void* opaque, void* connection)
81{
82 AdbClient* const adb_client = (AdbClient*)opaque;
83
84 if (adb_client->state == ADBC_STATE_WAIT_ON_HOST) {
85 D("ADB client %p(o=%p) is connected to the host %p",
86 adb_client, adb_client->opaque, connection);
87
88 /* Bump the state up. */
89 adb_client->state = ADBC_STATE_HOST_CONNECTED;
90
91 /* Notify the ADB guest that host has been connected.This will unblock
92 * the guest from a 'read', then guest will register the transport, and
93 * will send 'setart' request, indicating that it is ready to receive
94 * data from the host. */
95 qemud_client_send(adb_client->qemud_client, (const uint8_t*)"ok", 2);
96 } else {
97 D("Unexpected ADB host connection while state is %d", adb_client->state);
98 }
99}
100
101/* A callback that is invoked when the host gets disconnected.
102 * Param:
103 * opaque - AdbClient instance.
104 * connection - An opaque pointer that identifies connection with the ADB host.
105 */
106static void
107_adb_on_host_disconnect(void* opaque, void* connection)
108{
109 AdbClient* const adb_client = (AdbClient*)opaque;
110
111 D("ADB client %p(o=%p) is disconnected from the host %p",
112 adb_client, adb_client->opaque, connection);
113 adb_client->state = ADBC_STATE_HOST_DISCONNECTED;
114}
115
116/* A callback that is invoked when the host sends data.
117 * Param:
118 * opaque - AdbClient instance.
119 * connection - An opaque pointer that identifies connection with the ADB host.
120 * buff, size - Buffer containing the host data.
121 */
122static void
123_adb_on_host_data(void* opaque, void* connection, const void* buff, int size)
124{
125 AdbClient* const adb_client = (AdbClient*)opaque;
126 D("ADB client %p(o=%p) received from the host %p %d bytes in %s",
127 adb_client, adb_client->opaque, connection, size, QB(buff, size));
128
129 if (adb_client->state == ADBC_STATE_CONNECTED) {
130 /* Dispatch data down to the guest. */
131 qemud_client_send(adb_client->qemud_client, (const uint8_t*)buff, size);
132 } else {
133 D("Unexpected data from ADB host %p while client %p(o=%p) is in state %d",
134 connection, adb_client, adb_client->opaque, adb_client->state);
135 }
136}
137
138/* ADB guest API required for adb_server_register_guest */
139static AdbGuestRoutines _adb_client_routines = {
140 /* A callback that is invoked when the host is connected. */
141 _adb_on_host_connected,
142 /* A callback that is invoked when the host gets disconnected. */
143 _adb_on_host_disconnect,
144 /* A callback that is invoked when the host sends data. */
145 _adb_on_host_data,
146};
147
148/********************************************************************************
149 * ADB guest communication.
150 *******************************************************************************/
151
152/* Allocates AdbClient instance. */
153static AdbClient*
154_adb_client_new(void)
155{
156 AdbClient* adb_client;
157
158 ANEW0(adb_client);
159
160 return adb_client;
161}
162
163/* Frees AdbClient instance, allocated with _adb_client_new */
164static void
165_adb_client_free(AdbClient* adb_client)
166{
167 if (adb_client != NULL) {
168 free(adb_client);
169 }
170}
171
172/* A callback that is invoked when ADB guest sends data to the service.
173 * Param:
174 * opaque - AdbClient instance.
175 * msg, msglen - Message received from the ADB guest.
176 * client - adb QEMUD client.
177 */
178static void
179_adb_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
180{
181 AdbClient* const adb_client = (AdbClient*)opaque;
182
183 D("ADB client %p(o=%p) received from guest %d bytes in %s",
184 adb_client, adb_client->opaque, msglen, QB(msg, msglen));
185
186 /* Properly dispatch the message, depending on the client state. */
187 switch (adb_client->state) {
188 case ADBC_STATE_CONNECTED:
189 /* Connection is fully established. Dispatch the message to the
190 * host. */
191 adb_server_on_guest_message(adb_client->opaque, msg, msglen);
192 break;
193
194 case ADBC_STATE_WAIT_ON_HOST:
195 /* At this state the only message that is allowed is 'accept' */
196 if (msglen == 6 && !memcmp(msg, "accept", 6)) {
197 /* Register ADB guest connection with the ADB server. */
198 adb_client->opaque =
199 adb_server_register_guest(adb_client, &_adb_client_routines);
200 if (adb_client->opaque == NULL) {
201 D("Unable to register ADB guest with the ADB server.");
202 /* KO the guest. */
203 qemud_client_send(adb_client->qemud_client,
204 (const uint8_t*)"ko", 2);
205 }
206 } else {
207 D("Unexpected guest request while waiting on ADB host to connect.");
208 }
209 break;
210
211 case ADBC_STATE_HOST_CONNECTED:
212 /* At this state the only message that is allowed is 'start' */
213 if (msglen == 5 && !memcmp(msg, "start", 5)) {
214 adb_client->state = ADBC_STATE_CONNECTED;
215 adb_server_complete_connection(adb_client->opaque);
216 } else {
217 D("Unexpected request while waiting on connection to start.");
218 }
219 break;
220
221 default:
222 D("Unexpected ADB guest request '%s' while client state is %d.",
223 QB(msg, msglen), adb_client->state);
224 break;
225 }
226}
227
228/* A callback that is invoked when ADB guest disconnects from the service. */
229static void
230_adb_client_close(void* opaque)
231{
232 AdbClient* const adb_client = (AdbClient*)opaque;
233
234 D("ADB client %p(o=%p) is disconnected from the guest.",
235 adb_client, adb_client->opaque);
236 adb_client->state = ADBC_STATE_GUEST_DISCONNECTED;
237 if (adb_client->opaque != NULL) {
238 /* Close connection with the host. */
239 adb_server_on_guest_closed(adb_client->opaque);
240 }
241 _adb_client_free(adb_client);
242}
243
244/* A callback that is invoked when ADB daemon running inside the guest connects
245 * to the service.
246 * Client parameters are ignored here. Typically they contain the ADB port number
247 * which is always 5555 for the device / emulated system.
248 */
249static QemudClient*
250_adb_service_connect(void* opaque,
251 QemudService* serv,
252 int channel,
253 const char* client_param)
254{
255 /* Create new QEMUD client for the connection with ADB daemon. */
256 AdbClient* const adb_client = _adb_client_new();
257
258 D("Connecting ADB guest: '%s'", client_param ? client_param : "<null>");
259 adb_client->qemud_client =
260 qemud_client_new(serv, channel, client_param, adb_client,
261 _adb_client_recv, _adb_client_close, NULL, NULL);
262 if (adb_client->qemud_client == NULL) {
263 D("Unable to create QEMUD client for ADB guest.");
264 _adb_client_free(adb_client);
265 return NULL;
266 }
267
268 return adb_client->qemud_client;
269}
270
271/********************************************************************************
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800272 * Debugging ADB guest communication.
273 *******************************************************************************/
274
275/* Allocates AdbDbgClient instance. */
276static AdbDbgClient*
277_adb_dbg_client_new(void)
278{
279 AdbDbgClient* adb_dbg_client;
280
281 ANEW0(adb_dbg_client);
282
283 return adb_dbg_client;
284}
285
286/* Frees AdbDbgClient instance, allocated with _adb_dbg_client_new */
287static void
288_adb_dbg_client_free(AdbDbgClient* adb_dbg_client)
289{
290 if (adb_dbg_client != NULL) {
291 free(adb_dbg_client);
292 }
293}
294
295/* A callback that is invoked when ADB debugging guest sends data to the service.
296 * Param:
297 * opaque - AdbDbgClient instance.
298 * msg, msglen - Message received from the ADB guest.
299 * client - adb-debug QEMUD client.
300 */
301static void
302_adb_dbg_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
303{
304 if (DD_ACTIVE) {
305 fprintf(stderr, "ADB: %s", (const char*)msg);
306 }
307}
308
309/* A callback that is invoked when ADB debugging guest disconnects from the
310 * service. */
311static void
312_adb_dbg_client_close(void* opaque)
313{
314 AdbDbgClient* const adb_dbg_client = (AdbDbgClient*)opaque;
315
316 DD("ADB debugging client %p is disconnected from the guest.", adb_dbg_client);
317 _adb_dbg_client_free(adb_dbg_client);
318}
319
320/* A callback that is invoked when ADB daemon running inside the guest connects
321 * to the debugging service.
322 * Client parameters are ignored here.
323 */
324static QemudClient*
325_adb_debug_service_connect(void* opaque,
326 QemudService* serv,
327 int channel,
328 const char* client_param)
329{
330 /* Create new QEMUD client for the connection with ADB debugger. */
331 AdbDbgClient* const adb_dbg_client = _adb_dbg_client_new();
332
333 DD("Connecting ADB debugging guest: '%s'",
334 client_param ? client_param : "<null>");
335 adb_dbg_client->qemud_client =
336 qemud_client_new(serv, channel, client_param, adb_dbg_client,
337 _adb_dbg_client_recv, _adb_dbg_client_close, NULL, NULL);
338 if (adb_dbg_client->qemud_client == NULL) {
339 DD("Unable to create QEMUD client for ADB debugging guest.");
340 _adb_dbg_client_free(adb_dbg_client);
341 return NULL;
342 }
343
344 return adb_dbg_client->qemud_client;
345}
346
347/********************************************************************************
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800348 * ADB service API.
349 *******************************************************************************/
350
351void
352android_adb_service_init(void)
353{
354static int _inited = 0;
355
356 if (!adb_server_is_initialized()) {
357 return;
358 }
359
360 if (!_inited) {
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800361 /* Register main ADB service. */
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800362 QemudService* serv = qemud_service_register(SERVICE_NAME, 0, NULL,
363 _adb_service_connect,
364 NULL, NULL);
365 if (serv == NULL) {
366 derror("%s: Could not register '%s' service",
367 __FUNCTION__, SERVICE_NAME);
368 return;
369 }
370 D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME);
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800371
372 /* Register debugging ADB service. */
373 serv = qemud_service_register(DEBUG_SERVICE_NAME, 0, NULL,
374 _adb_debug_service_connect, NULL, NULL);
375 if (serv != NULL) {
376 DD("Registered '%s' qemud service", DEBUG_SERVICE_NAME);
377 } else {
378 dwarning("%s: Could not register '%s' service",
379 __FUNCTION__, DEBUG_SERVICE_NAME);
380 }
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800381 }
382}