blob: 127d072be94dc9c8f7182d0638fd3080c8850f89 [file] [log] [blame]
Doug Zongker9270a202012-01-09 15:16:13 -08001/*
2 * Copyright (C) 2007 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#define TRACE_TAG TRACE_ADB
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <ctype.h>
22#include <stdarg.h>
23#include <errno.h>
24#include <string.h>
25#include <time.h>
26#include <sys/time.h>
27
28#include "sysdeps.h"
29#include "adb.h"
30
Doug Zongker9270a202012-01-09 15:16:13 -080031#include <private/android_filesystem_config.h>
Doug Zongker9270a202012-01-09 15:16:13 -080032
33#if ADB_TRACE
34ADB_MUTEX_DEFINE( D_lock );
35#endif
36
37int HOST = 0;
38
39static const char *adb_device_banner = "sideload";
40
41void fatal(const char *fmt, ...)
42{
43 va_list ap;
44 va_start(ap, fmt);
45 fprintf(stderr, "error: ");
46 vfprintf(stderr, fmt, ap);
47 fprintf(stderr, "\n");
48 va_end(ap);
49 exit(-1);
50}
51
52void fatal_errno(const char *fmt, ...)
53{
54 va_list ap;
55 va_start(ap, fmt);
56 fprintf(stderr, "error: %s: ", strerror(errno));
57 vfprintf(stderr, fmt, ap);
58 fprintf(stderr, "\n");
59 va_end(ap);
60 exit(-1);
61}
62
63int adb_trace_mask;
64
65/* read a comma/space/colum/semi-column separated list of tags
66 * from the ADB_TRACE environment variable and build the trace
67 * mask from it. note that '1' and 'all' are special cases to
68 * enable all tracing
69 */
70void adb_trace_init(void)
71{
72 const char* p = getenv("ADB_TRACE");
73 const char* q;
74
75 static const struct {
76 const char* tag;
77 int flag;
78 } tags[] = {
79 { "1", 0 },
80 { "all", 0 },
81 { "adb", TRACE_ADB },
82 { "sockets", TRACE_SOCKETS },
83 { "packets", TRACE_PACKETS },
84 { "rwx", TRACE_RWX },
85 { "usb", TRACE_USB },
86 { "sync", TRACE_SYNC },
87 { "sysdeps", TRACE_SYSDEPS },
88 { "transport", TRACE_TRANSPORT },
89 { "jdwp", TRACE_JDWP },
90 { "services", TRACE_SERVICES },
91 { NULL, 0 }
92 };
93
94 if (p == NULL)
95 return;
96
97 /* use a comma/column/semi-colum/space separated list */
98 while (*p) {
99 int len, tagn;
100
101 q = strpbrk(p, " ,:;");
102 if (q == NULL) {
103 q = p + strlen(p);
104 }
105 len = q - p;
106
107 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
108 {
109 int taglen = strlen(tags[tagn].tag);
110
111 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
112 {
113 int flag = tags[tagn].flag;
114 if (flag == 0) {
115 adb_trace_mask = ~0;
116 return;
117 }
118 adb_trace_mask |= (1 << flag);
119 break;
120 }
121 }
122 p = q;
123 if (*p)
124 p++;
125 }
126}
127
128
129apacket *get_apacket(void)
130{
131 apacket *p = malloc(sizeof(apacket));
132 if(p == 0) fatal("failed to allocate an apacket");
133 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
134 return p;
135}
136
137void put_apacket(apacket *p)
138{
139 free(p);
140}
141
142void handle_online(void)
143{
144 D("adb: online\n");
145}
146
147void handle_offline(atransport *t)
148{
149 D("adb: offline\n");
150 //Close the associated usb
151 run_transport_disconnects(t);
152}
153
154#if TRACE_PACKETS
155#define DUMPMAX 32
156void print_packet(const char *label, apacket *p)
157{
158 char *tag;
159 char *x;
160 unsigned count;
161
162 switch(p->msg.command){
163 case A_SYNC: tag = "SYNC"; break;
164 case A_CNXN: tag = "CNXN" ; break;
165 case A_OPEN: tag = "OPEN"; break;
166 case A_OKAY: tag = "OKAY"; break;
167 case A_CLSE: tag = "CLSE"; break;
168 case A_WRTE: tag = "WRTE"; break;
169 default: tag = "????"; break;
170 }
171
172 fprintf(stderr, "%s: %s %08x %08x %04x \"",
173 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
174 count = p->msg.data_length;
175 x = (char*) p->data;
176 if(count > DUMPMAX) {
177 count = DUMPMAX;
178 tag = "\n";
179 } else {
180 tag = "\"\n";
181 }
182 while(count-- > 0){
183 if((*x >= ' ') && (*x < 127)) {
184 fputc(*x, stderr);
185 } else {
186 fputc('.', stderr);
187 }
188 x++;
189 }
190 fprintf(stderr, tag);
191}
192#endif
193
194static void send_ready(unsigned local, unsigned remote, atransport *t)
195{
196 D("Calling send_ready \n");
197 apacket *p = get_apacket();
198 p->msg.command = A_OKAY;
199 p->msg.arg0 = local;
200 p->msg.arg1 = remote;
201 send_packet(p, t);
202}
203
204static void send_close(unsigned local, unsigned remote, atransport *t)
205{
206 D("Calling send_close \n");
207 apacket *p = get_apacket();
208 p->msg.command = A_CLSE;
209 p->msg.arg0 = local;
210 p->msg.arg1 = remote;
211 send_packet(p, t);
212}
213
214static void send_connect(atransport *t)
215{
216 D("Calling send_connect \n");
217 apacket *cp = get_apacket();
218 cp->msg.command = A_CNXN;
219 cp->msg.arg0 = A_VERSION;
220 cp->msg.arg1 = MAX_PAYLOAD;
221 snprintf((char*) cp->data, sizeof cp->data, "%s::",
222 HOST ? "host" : adb_device_banner);
223 cp->msg.data_length = strlen((char*) cp->data) + 1;
224 send_packet(cp, t);
Doug Zongker9270a202012-01-09 15:16:13 -0800225}
226
227void parse_banner(char *banner, atransport *t)
228{
229 char *type, *product, *end;
230
231 D("parse_banner: %s\n", banner);
232 type = banner;
233 product = strchr(type, ':');
234 if(product) {
235 *product++ = 0;
236 } else {
237 product = "";
238 }
239
240 /* remove trailing ':' */
241 end = strchr(product, ':');
242 if(end) *end = 0;
243
244 /* save product name in device structure */
245 if (t->product == NULL) {
246 t->product = strdup(product);
247 } else if (strcmp(product, t->product) != 0) {
248 free(t->product);
249 t->product = strdup(product);
250 }
251
252 if(!strcmp(type, "bootloader")){
253 D("setting connection_state to CS_BOOTLOADER\n");
254 t->connection_state = CS_BOOTLOADER;
255 update_transports();
256 return;
257 }
258
259 if(!strcmp(type, "device")) {
260 D("setting connection_state to CS_DEVICE\n");
261 t->connection_state = CS_DEVICE;
262 update_transports();
263 return;
264 }
265
266 if(!strcmp(type, "recovery")) {
267 D("setting connection_state to CS_RECOVERY\n");
268 t->connection_state = CS_RECOVERY;
269 update_transports();
270 return;
271 }
272
273 if(!strcmp(type, "sideload")) {
274 D("setting connection_state to CS_SIDELOAD\n");
275 t->connection_state = CS_SIDELOAD;
276 update_transports();
277 return;
278 }
279
280 t->connection_state = CS_HOST;
281}
282
283void handle_packet(apacket *p, atransport *t)
284{
285 asocket *s;
286
287 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
288 ((char*) (&(p->msg.command)))[1],
289 ((char*) (&(p->msg.command)))[2],
290 ((char*) (&(p->msg.command)))[3]);
291 print_packet("recv", p);
292
293 switch(p->msg.command){
294 case A_SYNC:
295 if(p->msg.arg0){
296 send_packet(p, t);
297 if(HOST) send_connect(t);
298 } else {
299 t->connection_state = CS_OFFLINE;
300 handle_offline(t);
301 send_packet(p, t);
302 }
303 return;
304
305 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
306 /* XXX verify version, etc */
307 if(t->connection_state != CS_OFFLINE) {
308 t->connection_state = CS_OFFLINE;
309 handle_offline(t);
310 }
311 parse_banner((char*) p->data, t);
312 handle_online();
313 if(!HOST) send_connect(t);
314 break;
315
316 case A_OPEN: /* OPEN(local-id, 0, "destination") */
317 if(t->connection_state != CS_OFFLINE) {
318 char *name = (char*) p->data;
319 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
320 s = create_local_service_socket(name);
321 if(s == 0) {
322 send_close(0, p->msg.arg0, t);
323 } else {
324 s->peer = create_remote_socket(p->msg.arg0, t);
325 s->peer->peer = s;
326 send_ready(s->id, s->peer->id, t);
327 s->ready(s);
328 }
329 }
330 break;
331
332 case A_OKAY: /* READY(local-id, remote-id, "") */
333 if(t->connection_state != CS_OFFLINE) {
334 if((s = find_local_socket(p->msg.arg1))) {
335 if(s->peer == 0) {
336 s->peer = create_remote_socket(p->msg.arg0, t);
337 s->peer->peer = s;
338 }
339 s->ready(s);
340 }
341 }
342 break;
343
344 case A_CLSE: /* CLOSE(local-id, remote-id, "") */
345 if(t->connection_state != CS_OFFLINE) {
346 if((s = find_local_socket(p->msg.arg1))) {
347 s->close(s);
348 }
349 }
350 break;
351
352 case A_WRTE:
353 if(t->connection_state != CS_OFFLINE) {
354 if((s = find_local_socket(p->msg.arg1))) {
355 unsigned rid = p->msg.arg0;
356 p->len = p->msg.data_length;
357
358 if(s->enqueue(s, p) == 0) {
359 D("Enqueue the socket\n");
360 send_ready(s->id, rid, t);
361 }
362 return;
363 }
364 }
365 break;
366
367 default:
368 printf("handle_packet: what is %08x?!\n", p->msg.command);
369 }
370
371 put_apacket(p);
372}
373
Doug Zongker9270a202012-01-09 15:16:13 -0800374static void adb_cleanup(void)
375{
376 usb_cleanup();
377}
378
Doug Zongker9270a202012-01-09 15:16:13 -0800379int adb_main()
380{
381 atexit(adb_cleanup);
382#if defined(HAVE_FORKEXEC)
383 // No SIGCHLD. Let the service subproc handle its children.
384 signal(SIGPIPE, SIG_IGN);
385#endif
386
387 init_transport_registration();
388
389 // The minimal version of adbd only uses USB.
Da Zhou65ad9282014-01-17 01:04:07 -0800390 if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
Doug Zongker9270a202012-01-09 15:16:13 -0800391 // listen on USB
392 usb_init();
393 }
394
Doug Zongker9270a202012-01-09 15:16:13 -0800395 D("Event loop starting\n");
396
397 fdevent_loop();
398
399 usb_cleanup();
400
401 return 0;
402}