adb.c revision 65ad928602479379187d6fbe1d924f0fd60bea0e
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
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);
225}
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
374static void adb_cleanup(void)
375{
376    usb_cleanup();
377}
378
379int 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(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, 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