• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
31 #include <private/android_filesystem_config.h>
32 
33 #if ADB_TRACE
34 ADB_MUTEX_DEFINE( D_lock );
35 #endif
36 
37 int HOST = 0;
38 
39 static const char *adb_device_banner = "sideload";
40 
fatal(const char * fmt,...)41 void 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 
fatal_errno(const char * fmt,...)52 void 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 
63 int   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  */
adb_trace_init(void)70 void  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 
get_apacket(void)129 apacket *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 
put_apacket(apacket * p)137 void put_apacket(apacket *p)
138 {
139     free(p);
140 }
141 
handle_online(void)142 void handle_online(void)
143 {
144     D("adb: online\n");
145 }
146 
handle_offline(atransport * t)147 void 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
print_packet(const char * label,apacket * p)156 void 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 
send_ready(unsigned local,unsigned remote,atransport * t)194 static 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 
send_close(unsigned local,unsigned remote,atransport * t)204 static 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 
send_connect(atransport * t)214 static 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);
225 }
226 
parse_banner(char * banner,atransport * t)227 void 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 
handle_packet(apacket * p,atransport * t)283 void 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 
adb_cleanup(void)374 static void adb_cleanup(void)
375 {
376     usb_cleanup();
377 }
378 
adb_main()379 int 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.
390     if (access("/dev/android_adb", F_OK) == 0) {
391         // listen on USB
392         usb_init();
393     }
394 
395     if (setgid(AID_SHELL) != 0) {
396         fprintf(stderr, "failed to setgid to shell\n");
397         exit(1);
398     }
399     if (setuid(AID_SHELL) != 0) {
400         fprintf(stderr, "failed to setuid to shell\n");
401         exit(1);
402     }
403     fprintf(stderr, "userid is %d\n", getuid());
404 
405     D("Event loop starting\n");
406 
407     fdevent_loop();
408 
409     usb_cleanup();
410 
411     return 0;
412 }
413