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