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