• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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__)
29 #define  DD(...)   VERBOSE_PRINT(adb,__VA_ARGS__)
30 #define  D_ACTIVE  VERBOSE_CHECK(adbclient)
31 #define  DD_ACTIVE VERBOSE_CHECK(adb)
32 #define  QB(b, s)  quote_bytes((const char*)b, (s < 32) ? s : 32)
33 
34 #define SERVICE_NAME        "adb"
35 #define DEBUG_SERVICE_NAME  "adb-debug"
36 /* Maximum length of the message that can be received from the guest. */
37 #define ADB_MAX_MSG_LEN     8
38 /* Enumerates ADB client state values. */
39 typedef 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. */
54 typedef struct AdbClient AdbClient;
55 struct 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;
62     /* 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;
66 };
67 
68 /* ADB debugging client descriptor. */
69 typedef struct AdbDbgClient AdbDbgClient;
70 struct AdbDbgClient {
71     /* QEMUD client pipe for this client. */
72     QemudClient*    qemud_client;
73 };
74 
75 /********************************************************************************
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  */
84 static void
_adb_on_host_connected(void * opaque,void * connection)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  */
111 static void
_adb_on_host_disconnect(void * opaque,void * connection)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  */
127 static void
_adb_on_host_data(void * opaque,void * connection,const void * buff,int size)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 */
144 static 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. */
158 static AdbClient*
_adb_client_new(void)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 */
169 static void
_adb_client_free(AdbClient * adb_client)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  */
183 static void
_adb_client_recv(void * opaque,uint8_t * msg,int msglen,QemudClient * client)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 
191     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 
214     /* Properly dispatch the message, depending on the client state. */
215     switch (adb_client->state) {
216         case ADBC_STATE_WAIT_ON_HOST:
217             /* At this state the only message that is allowed is 'accept' */
218             if (adb_client->msg_cur == 6 &&
219                 !memcmp(adb_client->msg_buffer, "accept", 6)) {
220                 adb_client->msg_cur = 0;
221                 /* 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' */
237             if (adb_client->msg_cur &&
238                 !memcmp(adb_client->msg_buffer, "start", 5)) {
239                 adb_client->msg_cur = 0;
240                 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. */
255 static void
_adb_client_close(void * opaque)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  */
275 static QemudClient*
_adb_service_connect(void * opaque,QemudService * serv,int channel,const char * client_param)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 /********************************************************************************
298  *                      Debugging ADB guest communication.
299  *******************************************************************************/
300 
301 /* Allocates AdbDbgClient instance. */
302 static AdbDbgClient*
_adb_dbg_client_new(void)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 */
313 static void
_adb_dbg_client_free(AdbDbgClient * adb_dbg_client)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  */
327 static void
_adb_dbg_client_recv(void * opaque,uint8_t * msg,int msglen,QemudClient * client)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. */
337 static void
_adb_dbg_client_close(void * opaque)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  */
350 static QemudClient*
_adb_debug_service_connect(void * opaque,QemudService * serv,int channel,const char * client_param)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 /********************************************************************************
374  *                      ADB service API.
375  *******************************************************************************/
376 
377 void
android_adb_service_init(void)378 android_adb_service_init(void)
379 {
380 static int _inited = 0;
381 
382     if (!adb_server_is_initialized()) {
383         return;
384     }
385 
386     if (!_inited) {
387         /* Register main ADB service. */
388         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);
397 
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         }
407     }
408 }
409