blob: 9d82251cd18fabfafc22177df06b5ac7dc6e10e4 [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 Chtchetkine39a11582012-04-30 15:18:15 -070036/* Maximum length of the message that can be received from the guest. */
37#define ADB_MAX_MSG_LEN 8
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080038/* Enumerates ADB client state values. */
39typedef enum AdbClientState {
40 /* Waiting on a connection from ADB host. */
41 ADBC_STATE_WAIT_ON_HOST,
42 /* ADB host is connected. Waiting on the transport initialization completion
43 * in the guest. */
44 ADBC_STATE_HOST_CONNECTED,
45 /* Connection between ADB host and ADB guest is fully established. */
46 ADBC_STATE_CONNECTED,
47 /* ADB host has been disconnected. */
48 ADBC_STATE_HOST_DISCONNECTED,
49 /* ADB guest has been disconnected. */
50 ADBC_STATE_GUEST_DISCONNECTED,
51} AdbClientState;
52
53/* ADB client descriptor. */
54typedef struct AdbClient AdbClient;
55struct AdbClient {
56 /* Opaque pointer returned from adb_server_register_guest API. */
57 void* opaque;
58 /* QEMUD client pipe for this client. */
59 QemudClient* qemud_client;
60 /* Connection state. */
61 AdbClientState state;
Vladimir Chtchetkine39a11582012-04-30 15:18:15 -070062 /* Buffer, collecting accept / stop messages from client. */
63 char msg_buffer[ADB_MAX_MSG_LEN];
64 /* Current position in message buffer. */
65 int msg_cur;
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080066};
67
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -080068/* ADB debugging client descriptor. */
69typedef struct AdbDbgClient AdbDbgClient;
70struct AdbDbgClient {
71 /* QEMUD client pipe for this client. */
72 QemudClient* qemud_client;
73};
74
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -080075/********************************************************************************
76 * ADB host communication.
77 *******************************************************************************/
78
79/* A callback that is invoked when the host is connected.
80 * Param:
81 * opaque - AdbClient instance.
82 * connection - An opaque pointer that identifies connection with the ADB host.
83 */
84static void
85_adb_on_host_connected(void* opaque, void* connection)
86{
87 AdbClient* const adb_client = (AdbClient*)opaque;
88
89 if (adb_client->state == ADBC_STATE_WAIT_ON_HOST) {
90 D("ADB client %p(o=%p) is connected to the host %p",
91 adb_client, adb_client->opaque, connection);
92
93 /* Bump the state up. */
94 adb_client->state = ADBC_STATE_HOST_CONNECTED;
95
96 /* Notify the ADB guest that host has been connected.This will unblock
97 * the guest from a 'read', then guest will register the transport, and
98 * will send 'setart' request, indicating that it is ready to receive
99 * data from the host. */
100 qemud_client_send(adb_client->qemud_client, (const uint8_t*)"ok", 2);
101 } else {
102 D("Unexpected ADB host connection while state is %d", adb_client->state);
103 }
104}
105
106/* A callback that is invoked when the host gets disconnected.
107 * Param:
108 * opaque - AdbClient instance.
109 * connection - An opaque pointer that identifies connection with the ADB host.
110 */
111static void
112_adb_on_host_disconnect(void* opaque, void* connection)
113{
114 AdbClient* const adb_client = (AdbClient*)opaque;
115
116 D("ADB client %p(o=%p) is disconnected from the host %p",
117 adb_client, adb_client->opaque, connection);
118 adb_client->state = ADBC_STATE_HOST_DISCONNECTED;
119}
120
121/* A callback that is invoked when the host sends data.
122 * Param:
123 * opaque - AdbClient instance.
124 * connection - An opaque pointer that identifies connection with the ADB host.
125 * buff, size - Buffer containing the host data.
126 */
127static void
128_adb_on_host_data(void* opaque, void* connection, const void* buff, int size)
129{
130 AdbClient* const adb_client = (AdbClient*)opaque;
131 D("ADB client %p(o=%p) received from the host %p %d bytes in %s",
132 adb_client, adb_client->opaque, connection, size, QB(buff, size));
133
134 if (adb_client->state == ADBC_STATE_CONNECTED) {
135 /* Dispatch data down to the guest. */
136 qemud_client_send(adb_client->qemud_client, (const uint8_t*)buff, size);
137 } else {
138 D("Unexpected data from ADB host %p while client %p(o=%p) is in state %d",
139 connection, adb_client, adb_client->opaque, adb_client->state);
140 }
141}
142
143/* ADB guest API required for adb_server_register_guest */
144static AdbGuestRoutines _adb_client_routines = {
145 /* A callback that is invoked when the host is connected. */
146 _adb_on_host_connected,
147 /* A callback that is invoked when the host gets disconnected. */
148 _adb_on_host_disconnect,
149 /* A callback that is invoked when the host sends data. */
150 _adb_on_host_data,
151};
152
153/********************************************************************************
154 * ADB guest communication.
155 *******************************************************************************/
156
157/* Allocates AdbClient instance. */
158static AdbClient*
159_adb_client_new(void)
160{
161 AdbClient* adb_client;
162
163 ANEW0(adb_client);
164
165 return adb_client;
166}
167
168/* Frees AdbClient instance, allocated with _adb_client_new */
169static void
170_adb_client_free(AdbClient* adb_client)
171{
172 if (adb_client != NULL) {
173 free(adb_client);
174 }
175}
176
177/* A callback that is invoked when ADB guest sends data to the service.
178 * Param:
179 * opaque - AdbClient instance.
180 * msg, msglen - Message received from the ADB guest.
181 * client - adb QEMUD client.
182 */
183static void
184_adb_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
185{
186 AdbClient* const adb_client = (AdbClient*)opaque;
187
188 D("ADB client %p(o=%p) received from guest %d bytes in %s",
189 adb_client, adb_client->opaque, msglen, QB(msg, msglen));
190
Vladimir Chtchetkine39a11582012-04-30 15:18:15 -0700191 if (adb_client->state == ADBC_STATE_CONNECTED) {
192 /* Connection is fully established. Dispatch the message to the host. */
193 adb_server_on_guest_message(adb_client->opaque, msg, msglen);
194 return;
195 }
196
197 /*
198 * At this point we expect either "accept", or "start" messages. Depending
199 * on the state of the pipe (although small) these messages could be broken
200 * into pieces. So, simply checking msg for "accept", or "start" may not
201 * work. Lets collect them first in internal buffer, and then will see.
202 */
203
204 /* Make sure tha message doesn't overflow the buffer. */
205 if ((msglen + adb_client->msg_cur) > sizeof(adb_client->msg_buffer)) {
206 D("Unexpected message in ADB client.");
207 adb_client->msg_cur = 0;
208 return;
209 }
210 /* Append to current message. */
211 memcpy(adb_client->msg_buffer + adb_client->msg_cur, msg, msglen);
212 adb_client->msg_cur += msglen;
213
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800214 /* Properly dispatch the message, depending on the client state. */
215 switch (adb_client->state) {
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800216 case ADBC_STATE_WAIT_ON_HOST:
217 /* At this state the only message that is allowed is 'accept' */
Vladimir Chtchetkine39a11582012-04-30 15:18:15 -0700218 if (adb_client->msg_cur == 6 &&
219 !memcmp(adb_client->msg_buffer, "accept", 6)) {
220 adb_client->msg_cur = 0;
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800221 /* Register ADB guest connection with the ADB server. */
222 adb_client->opaque =
223 adb_server_register_guest(adb_client, &_adb_client_routines);
224 if (adb_client->opaque == NULL) {
225 D("Unable to register ADB guest with the ADB server.");
226 /* KO the guest. */
227 qemud_client_send(adb_client->qemud_client,
228 (const uint8_t*)"ko", 2);
229 }
230 } else {
231 D("Unexpected guest request while waiting on ADB host to connect.");
232 }
233 break;
234
235 case ADBC_STATE_HOST_CONNECTED:
236 /* At this state the only message that is allowed is 'start' */
Vladimir Chtchetkine39a11582012-04-30 15:18:15 -0700237 if (adb_client->msg_cur &&
238 !memcmp(adb_client->msg_buffer, "start", 5)) {
239 adb_client->msg_cur = 0;
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800240 adb_client->state = ADBC_STATE_CONNECTED;
241 adb_server_complete_connection(adb_client->opaque);
242 } else {
243 D("Unexpected request while waiting on connection to start.");
244 }
245 break;
246
247 default:
248 D("Unexpected ADB guest request '%s' while client state is %d.",
249 QB(msg, msglen), adb_client->state);
250 break;
251 }
252}
253
254/* A callback that is invoked when ADB guest disconnects from the service. */
255static void
256_adb_client_close(void* opaque)
257{
258 AdbClient* const adb_client = (AdbClient*)opaque;
259
260 D("ADB client %p(o=%p) is disconnected from the guest.",
261 adb_client, adb_client->opaque);
262 adb_client->state = ADBC_STATE_GUEST_DISCONNECTED;
263 if (adb_client->opaque != NULL) {
264 /* Close connection with the host. */
265 adb_server_on_guest_closed(adb_client->opaque);
266 }
267 _adb_client_free(adb_client);
268}
269
270/* A callback that is invoked when ADB daemon running inside the guest connects
271 * to the service.
272 * Client parameters are ignored here. Typically they contain the ADB port number
273 * which is always 5555 for the device / emulated system.
274 */
275static QemudClient*
276_adb_service_connect(void* opaque,
277 QemudService* serv,
278 int channel,
279 const char* client_param)
280{
281 /* Create new QEMUD client for the connection with ADB daemon. */
282 AdbClient* const adb_client = _adb_client_new();
283
284 D("Connecting ADB guest: '%s'", client_param ? client_param : "<null>");
285 adb_client->qemud_client =
286 qemud_client_new(serv, channel, client_param, adb_client,
287 _adb_client_recv, _adb_client_close, NULL, NULL);
288 if (adb_client->qemud_client == NULL) {
289 D("Unable to create QEMUD client for ADB guest.");
290 _adb_client_free(adb_client);
291 return NULL;
292 }
293
294 return adb_client->qemud_client;
295}
296
297/********************************************************************************
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800298 * Debugging ADB guest communication.
299 *******************************************************************************/
300
301/* Allocates AdbDbgClient instance. */
302static AdbDbgClient*
303_adb_dbg_client_new(void)
304{
305 AdbDbgClient* adb_dbg_client;
306
307 ANEW0(adb_dbg_client);
308
309 return adb_dbg_client;
310}
311
312/* Frees AdbDbgClient instance, allocated with _adb_dbg_client_new */
313static void
314_adb_dbg_client_free(AdbDbgClient* adb_dbg_client)
315{
316 if (adb_dbg_client != NULL) {
317 free(adb_dbg_client);
318 }
319}
320
321/* A callback that is invoked when ADB debugging guest sends data to the service.
322 * Param:
323 * opaque - AdbDbgClient instance.
324 * msg, msglen - Message received from the ADB guest.
325 * client - adb-debug QEMUD client.
326 */
327static void
328_adb_dbg_client_recv(void* opaque, uint8_t* msg, int msglen, QemudClient* client)
329{
330 if (DD_ACTIVE) {
331 fprintf(stderr, "ADB: %s", (const char*)msg);
332 }
333}
334
335/* A callback that is invoked when ADB debugging guest disconnects from the
336 * service. */
337static void
338_adb_dbg_client_close(void* opaque)
339{
340 AdbDbgClient* const adb_dbg_client = (AdbDbgClient*)opaque;
341
342 DD("ADB debugging client %p is disconnected from the guest.", adb_dbg_client);
343 _adb_dbg_client_free(adb_dbg_client);
344}
345
346/* A callback that is invoked when ADB daemon running inside the guest connects
347 * to the debugging service.
348 * Client parameters are ignored here.
349 */
350static QemudClient*
351_adb_debug_service_connect(void* opaque,
352 QemudService* serv,
353 int channel,
354 const char* client_param)
355{
356 /* Create new QEMUD client for the connection with ADB debugger. */
357 AdbDbgClient* const adb_dbg_client = _adb_dbg_client_new();
358
359 DD("Connecting ADB debugging guest: '%s'",
360 client_param ? client_param : "<null>");
361 adb_dbg_client->qemud_client =
362 qemud_client_new(serv, channel, client_param, adb_dbg_client,
363 _adb_dbg_client_recv, _adb_dbg_client_close, NULL, NULL);
364 if (adb_dbg_client->qemud_client == NULL) {
365 DD("Unable to create QEMUD client for ADB debugging guest.");
366 _adb_dbg_client_free(adb_dbg_client);
367 return NULL;
368 }
369
370 return adb_dbg_client->qemud_client;
371}
372
373/********************************************************************************
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800374 * ADB service API.
375 *******************************************************************************/
376
377void
378android_adb_service_init(void)
379{
380static int _inited = 0;
381
382 if (!adb_server_is_initialized()) {
383 return;
384 }
385
386 if (!_inited) {
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800387 /* Register main ADB service. */
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800388 QemudService* serv = qemud_service_register(SERVICE_NAME, 0, NULL,
389 _adb_service_connect,
390 NULL, NULL);
391 if (serv == NULL) {
392 derror("%s: Could not register '%s' service",
393 __FUNCTION__, SERVICE_NAME);
394 return;
395 }
396 D("%s: Registered '%s' qemud service", __FUNCTION__, SERVICE_NAME);
Vladimir Chtchetkinebf45fc22012-02-27 10:46:10 -0800397
398 /* Register debugging ADB service. */
399 serv = qemud_service_register(DEBUG_SERVICE_NAME, 0, NULL,
400 _adb_debug_service_connect, NULL, NULL);
401 if (serv != NULL) {
402 DD("Registered '%s' qemud service", DEBUG_SERVICE_NAME);
403 } else {
404 dwarning("%s: Could not register '%s' service",
405 __FUNCTION__, DEBUG_SERVICE_NAME);
406 }
Vladimir Chtchetkined86c7242011-12-09 15:45:46 -0800407 }
408}