Home | History | Annotate | Download | only in minadbd
      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 
     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 
     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  */
     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 
    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 
    137 void put_apacket(apacket *p)
    138 {
    139     free(p);
    140 }
    141 
    142 void handle_online(void)
    143 {
    144     D("adb: online\n");
    145 }
    146 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    374 static void adb_cleanup(void)
    375 {
    376     usb_cleanup();
    377 }
    378 
    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(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
    391         // listen on USB
    392         usb_init();
    393     }
    394 
    395     D("Event loop starting\n");
    396 
    397     fdevent_loop();
    398 
    399     usb_cleanup();
    400 
    401     return 0;
    402 }
    403