transport.c revision 0e7c4274c687446dbe30a814278d7a6b99da8c4e
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#include <stdio.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21#include <errno.h>
22
23#include "sysdeps.h"
24
25#define   TRACE_TAG  TRACE_TRANSPORT
26#include "adb.h"
27
28static void transport_unref(atransport *t);
29
30static atransport transport_list = {
31    .next = &transport_list,
32    .prev = &transport_list,
33};
34
35ADB_MUTEX_DEFINE( transport_lock );
36
37#if ADB_TRACE
38static void  dump_hex( const unsigned char*  ptr, size_t  len )
39{
40    int  nn, len2 = len;
41
42    if (len2 > 16) len2 = 16;
43
44    for (nn = 0; nn < len2; nn++)
45        D("%02x", ptr[nn]);
46    D("  ");
47
48    for (nn = 0; nn < len2; nn++) {
49        int  c = ptr[nn];
50        if (c < 32 || c > 127)
51            c = '.';
52        D("%c", c);
53    }
54    D("\n");
55    fflush(stdout);
56}
57#endif
58
59void
60kick_transport(atransport*  t)
61{
62    if (t && !t->kicked)
63    {
64        int  kicked;
65
66        adb_mutex_lock(&transport_lock);
67        kicked = t->kicked;
68        if (!kicked)
69            t->kicked = 1;
70        adb_mutex_unlock(&transport_lock);
71
72        if (!kicked)
73            t->kick(t);
74    }
75}
76
77void
78run_transport_disconnects(atransport*  t)
79{
80    adisconnect*  dis = t->disconnects.next;
81
82    D("%s: run_transport_disconnects\n", t->serial);
83    while (dis != &t->disconnects) {
84        adisconnect*  next = dis->next;
85        dis->func( dis->opaque, t );
86        dis = next;
87    }
88}
89
90#if ADB_TRACE
91static void
92dump_packet(const char* name, const char* func, apacket* p)
93{
94    unsigned  command = p->msg.command;
95    int       len     = p->msg.data_length;
96    char      cmd[9];
97    char      arg0[12], arg1[12];
98    int       n;
99
100    for (n = 0; n < 4; n++) {
101        int  b = (command >> (n*8)) & 255;
102        if (b < 32 || b >= 127)
103            break;
104        cmd[n] = (char)b;
105    }
106    if (n == 4) {
107        cmd[4] = 0;
108    } else {
109        /* There is some non-ASCII name in the command, so dump
110            * the hexadecimal value instead */
111        snprintf(cmd, sizeof cmd, "%08x", command);
112    }
113
114    if (p->msg.arg0 < 256U)
115        snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
116    else
117        snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
118
119    if (p->msg.arg1 < 256U)
120        snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
121    else
122        snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
123
124    D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
125        name, func, cmd, arg0, arg1, len);
126    dump_hex(p->data, len);
127}
128#endif /* ADB_TRACE */
129
130static int
131read_packet(int  fd, const char* name, apacket** ppacket)
132{
133    char *p = (char*)ppacket;  /* really read a packet address */
134    int   r;
135    int   len = sizeof(*ppacket);
136    char  buff[8];
137    if (!name) {
138        snprintf(buff, sizeof buff, "fd=%d", fd);
139        name = buff;
140    }
141    while(len > 0) {
142        r = adb_read(fd, p, len);
143        if(r > 0) {
144            len -= r;
145            p   += r;
146        } else {
147            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
148            if((r < 0) && (errno == EINTR)) continue;
149            return -1;
150        }
151    }
152
153#if ADB_TRACE
154    if (ADB_TRACING) {
155        dump_packet(name, "from remote", *ppacket);
156    }
157#endif
158    return 0;
159}
160
161static int
162write_packet(int  fd, const char* name, apacket** ppacket)
163{
164    char *p = (char*) ppacket;  /* we really write the packet address */
165    int r, len = sizeof(ppacket);
166    char buff[8];
167    if (!name) {
168        snprintf(buff, sizeof buff, "fd=%d", fd);
169        name = buff;
170    }
171
172#if ADB_TRACE
173    if (ADB_TRACING) {
174        dump_packet(name, "to remote", *ppacket);
175    }
176#endif
177    len = sizeof(ppacket);
178    while(len > 0) {
179        r = adb_write(fd, p, len);
180        if(r > 0) {
181            len -= r;
182            p += r;
183        } else {
184            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
185            if((r < 0) && (errno == EINTR)) continue;
186            return -1;
187        }
188    }
189    return 0;
190}
191
192static void transport_socket_events(int fd, unsigned events, void *_t)
193{
194    atransport *t = _t;
195    if(events & FDE_READ){
196        apacket *p = 0;
197        if(read_packet(fd, t->serial, &p)){
198            D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
199        } else {
200            handle_packet(p, (atransport *) _t);
201        }
202    }
203}
204
205void send_packet(apacket *p, atransport *t)
206{
207    unsigned char *x;
208    unsigned sum;
209    unsigned count;
210
211    p->msg.magic = p->msg.command ^ 0xffffffff;
212
213    count = p->msg.data_length;
214    x = (unsigned char *) p->data;
215    sum = 0;
216    while(count-- > 0){
217        sum += *x++;
218    }
219    p->msg.data_check = sum;
220
221    print_packet("send", p);
222
223    if (t == NULL) {
224        fatal_errno("Transport is null");
225        D("Transport is null \n");
226    }
227
228    if(write_packet(t->transport_socket, t->serial, &p)){
229        fatal_errno("cannot enqueue packet on transport socket");
230    }
231}
232
233/* The transport is opened by transport_register_func before
234** the input and output threads are started.
235**
236** The output thread issues a SYNC(1, token) message to let
237** the input thread know to start things up.  In the event
238** of transport IO failure, the output thread will post a
239** SYNC(0,0) message to ensure shutdown.
240**
241** The transport will not actually be closed until both
242** threads exit, but the input thread will kick the transport
243** on its way out to disconnect the underlying device.
244*/
245
246static void *output_thread(void *_t)
247{
248    atransport *t = _t;
249    apacket *p;
250
251    D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
252       t->serial, t->fd, t->sync_token + 1);
253    p = get_apacket();
254    p->msg.command = A_SYNC;
255    p->msg.arg0 = 1;
256    p->msg.arg1 = ++(t->sync_token);
257    p->msg.magic = A_SYNC ^ 0xffffffff;
258    if(write_packet(t->fd, t->serial, &p)) {
259        put_apacket(p);
260        D("%s: failed to write SYNC packet\n", t->serial);
261        goto oops;
262    }
263
264    D("%s: data pump started\n", t->serial);
265    for(;;) {
266        p = get_apacket();
267
268        if(t->read_from_remote(p, t) == 0){
269            D("%s: received remote packet, sending to transport\n",
270              t->serial);
271            if(write_packet(t->fd, t->serial, &p)){
272                put_apacket(p);
273                D("%s: failed to write apacket to transport\n", t->serial);
274                goto oops;
275            }
276        } else {
277            D("%s: remote read failed for transport\n", t->serial);
278            put_apacket(p);
279            break;
280        }
281    }
282
283    D("%s: SYNC offline for transport\n", t->serial);
284    p = get_apacket();
285    p->msg.command = A_SYNC;
286    p->msg.arg0 = 0;
287    p->msg.arg1 = 0;
288    p->msg.magic = A_SYNC ^ 0xffffffff;
289    if(write_packet(t->fd, t->serial, &p)) {
290        put_apacket(p);
291        D("%s: failed to write SYNC apacket to transport", t->serial);
292    }
293
294oops:
295    D("%s: transport output thread is exiting\n", t->serial);
296    kick_transport(t);
297    transport_unref(t);
298    return 0;
299}
300
301static void *input_thread(void *_t)
302{
303    atransport *t = _t;
304    apacket *p;
305    int active = 0;
306
307    D("%s: starting transport input thread, reading from fd %d\n",
308       t->serial, t->fd);
309
310    for(;;){
311        if(read_packet(t->fd, t->serial, &p)) {
312            D("%s: failed to read apacket from transport on fd %d\n",
313               t->serial, t->fd );
314            break;
315        }
316        if(p->msg.command == A_SYNC){
317            if(p->msg.arg0 == 0) {
318                D("%s: transport SYNC offline\n", t->serial);
319                put_apacket(p);
320                break;
321            } else {
322                if(p->msg.arg1 == t->sync_token) {
323                    D("%s: transport SYNC online\n", t->serial);
324                    active = 1;
325                } else {
326                    D("%s: transport ignoring SYNC %d != %d\n",
327                      t->serial, p->msg.arg1, t->sync_token);
328                }
329            }
330        } else {
331            if(active) {
332                D("%s: transport got packet, sending to remote\n", t->serial);
333                t->write_to_remote(p, t);
334            } else {
335                D("%s: transport ignoring packet while offline\n", t->serial);
336            }
337        }
338
339        put_apacket(p);
340    }
341
342    // this is necessary to avoid a race condition that occured when a transport closes
343    // while a client socket is still active.
344    close_all_sockets(t);
345
346    D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
347    kick_transport(t);
348    transport_unref(t);
349    return 0;
350}
351
352
353static int transport_registration_send = -1;
354static int transport_registration_recv = -1;
355static fdevent transport_registration_fde;
356
357
358#if ADB_HOST
359static int list_transports_msg(char*  buffer, size_t  bufferlen)
360{
361    char  head[5];
362    int   len;
363
364    len = list_transports(buffer+4, bufferlen-4);
365    snprintf(head, sizeof(head), "%04x", len);
366    memcpy(buffer, head, 4);
367    len += 4;
368    return len;
369}
370
371/* this adds support required by the 'track-devices' service.
372 * this is used to send the content of "list_transport" to any
373 * number of client connections that want it through a single
374 * live TCP connection
375 */
376typedef struct device_tracker  device_tracker;
377struct device_tracker {
378    asocket          socket;
379    int              update_needed;
380    device_tracker*  next;
381};
382
383/* linked list of all device trackers */
384static device_tracker*   device_tracker_list;
385
386static void
387device_tracker_remove( device_tracker*  tracker )
388{
389    device_tracker**  pnode = &device_tracker_list;
390    device_tracker*   node  = *pnode;
391
392    adb_mutex_lock( &transport_lock );
393    while (node) {
394        if (node == tracker) {
395            *pnode = node->next;
396            break;
397        }
398        pnode = &node->next;
399        node  = *pnode;
400    }
401    adb_mutex_unlock( &transport_lock );
402}
403
404static void
405device_tracker_close( asocket*  socket )
406{
407    device_tracker*  tracker = (device_tracker*) socket;
408    asocket*         peer    = socket->peer;
409
410    D( "device tracker %p removed\n", tracker);
411    if (peer) {
412        peer->peer = NULL;
413        peer->close(peer);
414    }
415    device_tracker_remove(tracker);
416    free(tracker);
417}
418
419static int
420device_tracker_enqueue( asocket*  socket, apacket*  p )
421{
422    /* you can't read from a device tracker, close immediately */
423    put_apacket(p);
424    device_tracker_close(socket);
425    return -1;
426}
427
428static int
429device_tracker_send( device_tracker*  tracker,
430                     const char*      buffer,
431                     int              len )
432{
433    apacket*  p = get_apacket();
434    asocket*  peer = tracker->socket.peer;
435
436    memcpy(p->data, buffer, len);
437    p->len = len;
438    return peer->enqueue( peer, p );
439}
440
441
442static void
443device_tracker_ready( asocket*  socket )
444{
445    device_tracker*  tracker = (device_tracker*) socket;
446
447    /* we want to send the device list when the tracker connects
448    * for the first time, even if no update occured */
449    if (tracker->update_needed > 0) {
450        char  buffer[1024];
451        int   len;
452
453        tracker->update_needed = 0;
454
455        len = list_transports_msg(buffer, sizeof(buffer));
456        device_tracker_send(tracker, buffer, len);
457    }
458}
459
460
461asocket*
462create_device_tracker(void)
463{
464    device_tracker*  tracker = calloc(1,sizeof(*tracker));
465
466    if(tracker == 0) fatal("cannot allocate device tracker");
467
468    D( "device tracker %p created\n", tracker);
469
470    tracker->socket.enqueue = device_tracker_enqueue;
471    tracker->socket.ready   = device_tracker_ready;
472    tracker->socket.close   = device_tracker_close;
473    tracker->update_needed  = 1;
474
475    tracker->next       = device_tracker_list;
476    device_tracker_list = tracker;
477
478    return &tracker->socket;
479}
480
481
482/* call this function each time the transport list has changed */
483void  update_transports(void)
484{
485    char             buffer[1024];
486    int              len;
487    device_tracker*  tracker;
488
489    len = list_transports_msg(buffer, sizeof(buffer));
490
491    tracker = device_tracker_list;
492    while (tracker != NULL) {
493        device_tracker*  next = tracker->next;
494        /* note: this may destroy the tracker if the connection is closed */
495        device_tracker_send(tracker, buffer, len);
496        tracker = next;
497    }
498}
499#else
500void  update_transports(void)
501{
502    // nothing to do on the device side
503}
504#endif // ADB_HOST
505
506typedef struct tmsg tmsg;
507struct tmsg
508{
509    atransport *transport;
510    int         action;
511};
512
513static int
514transport_read_action(int  fd, struct tmsg*  m)
515{
516    char *p   = (char*)m;
517    int   len = sizeof(*m);
518    int   r;
519
520    while(len > 0) {
521        r = adb_read(fd, p, len);
522        if(r > 0) {
523            len -= r;
524            p   += r;
525        } else {
526            if((r < 0) && (errno == EINTR)) continue;
527            D("transport_read_action: on fd %d, error %d: %s\n",
528              fd, errno, strerror(errno));
529            return -1;
530        }
531    }
532    return 0;
533}
534
535static int
536transport_write_action(int  fd, struct tmsg*  m)
537{
538    char *p   = (char*)m;
539    int   len = sizeof(*m);
540    int   r;
541
542    while(len > 0) {
543        r = adb_write(fd, p, len);
544        if(r > 0) {
545            len -= r;
546            p   += r;
547        } else {
548            if((r < 0) && (errno == EINTR)) continue;
549            D("transport_write_action: on fd %d, error %d: %s\n",
550              fd, errno, strerror(errno));
551            return -1;
552        }
553    }
554    return 0;
555}
556
557static void transport_registration_func(int _fd, unsigned ev, void *data)
558{
559    tmsg m;
560    adb_thread_t output_thread_ptr;
561    adb_thread_t input_thread_ptr;
562    int s[2];
563    atransport *t;
564
565    if(!(ev & FDE_READ)) {
566        return;
567    }
568
569    if(transport_read_action(_fd, &m)) {
570        fatal_errno("cannot read transport registration socket");
571    }
572
573    t = m.transport;
574
575    if(m.action == 0){
576        D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
577
578            /* IMPORTANT: the remove closes one half of the
579            ** socket pair.  The close closes the other half.
580            */
581        fdevent_remove(&(t->transport_fde));
582        adb_close(t->fd);
583
584        adb_mutex_lock(&transport_lock);
585        t->next->prev = t->prev;
586        t->prev->next = t->next;
587        adb_mutex_unlock(&transport_lock);
588
589        run_transport_disconnects(t);
590
591        if (t->product)
592            free(t->product);
593        if (t->serial)
594            free(t->serial);
595
596        memset(t,0xee,sizeof(atransport));
597        free(t);
598
599        update_transports();
600        return;
601    }
602
603    /* don't create transport threads for inaccessible devices */
604    if (t->connection_state != CS_NOPERM) {
605        /* initial references are the two threads */
606        t->ref_count = 2;
607
608        if(adb_socketpair(s)) {
609            fatal_errno("cannot open transport socketpair");
610        }
611
612        D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
613
614        t->transport_socket = s[0];
615        t->fd = s[1];
616
617        fdevent_install(&(t->transport_fde),
618                        t->transport_socket,
619                        transport_socket_events,
620                        t);
621
622        fdevent_set(&(t->transport_fde), FDE_READ);
623
624        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
625            fatal_errno("cannot create input thread");
626        }
627
628        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
629            fatal_errno("cannot create output thread");
630        }
631    }
632
633        /* put us on the master device list */
634    adb_mutex_lock(&transport_lock);
635    t->next = &transport_list;
636    t->prev = transport_list.prev;
637    t->next->prev = t;
638    t->prev->next = t;
639    adb_mutex_unlock(&transport_lock);
640
641    t->disconnects.next = t->disconnects.prev = &t->disconnects;
642
643    update_transports();
644}
645
646void init_transport_registration(void)
647{
648    int s[2];
649
650    if(adb_socketpair(s)){
651        fatal_errno("cannot open transport registration socketpair");
652    }
653
654    transport_registration_send = s[0];
655    transport_registration_recv = s[1];
656
657    fdevent_install(&transport_registration_fde,
658                    transport_registration_recv,
659                    transport_registration_func,
660                    0);
661
662    fdevent_set(&transport_registration_fde, FDE_READ);
663}
664
665/* the fdevent select pump is single threaded */
666static void register_transport(atransport *transport)
667{
668    tmsg m;
669    m.transport = transport;
670    m.action = 1;
671    D("transport: %s registered\n", transport->serial);
672    if(transport_write_action(transport_registration_send, &m)) {
673        fatal_errno("cannot write transport registration socket\n");
674    }
675}
676
677static void remove_transport(atransport *transport)
678{
679    tmsg m;
680    m.transport = transport;
681    m.action = 0;
682    D("transport: %s removed\n", transport->serial);
683    if(transport_write_action(transport_registration_send, &m)) {
684        fatal_errno("cannot write transport registration socket\n");
685    }
686}
687
688
689static void transport_unref_locked(atransport *t)
690{
691    t->ref_count--;
692    if (t->ref_count == 0) {
693        D("transport: %s unref (kicking and closing)\n", t->serial);
694        if (!t->kicked) {
695            t->kicked = 1;
696            t->kick(t);
697        }
698        t->close(t);
699        remove_transport(t);
700    } else {
701        D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
702    }
703}
704
705static void transport_unref(atransport *t)
706{
707    if (t) {
708        adb_mutex_lock(&transport_lock);
709        transport_unref_locked(t);
710        adb_mutex_unlock(&transport_lock);
711    }
712}
713
714void add_transport_disconnect(atransport*  t, adisconnect*  dis)
715{
716    adb_mutex_lock(&transport_lock);
717    dis->next       = &t->disconnects;
718    dis->prev       = dis->next->prev;
719    dis->prev->next = dis;
720    dis->next->prev = dis;
721    adb_mutex_unlock(&transport_lock);
722}
723
724void remove_transport_disconnect(atransport*  t, adisconnect*  dis)
725{
726    dis->prev->next = dis->next;
727    dis->next->prev = dis->prev;
728    dis->next = dis->prev = dis;
729}
730
731
732atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
733{
734    atransport *t;
735    atransport *result = NULL;
736    int ambiguous = 0;
737
738retry:
739    if (error_out)
740        *error_out = "device not found";
741
742    adb_mutex_lock(&transport_lock);
743    for (t = transport_list.next; t != &transport_list; t = t->next) {
744        if (t->connection_state == CS_NOPERM) {
745        if (error_out)
746            *error_out = "insufficient permissions for device";
747            continue;
748        }
749
750        /* check for matching serial number */
751        if (serial) {
752            if (t->serial && !strcmp(serial, t->serial)) {
753                result = t;
754                break;
755            }
756        } else {
757            if (ttype == kTransportUsb && t->type == kTransportUsb) {
758                if (result) {
759                    if (error_out)
760                        *error_out = "more than one device";
761                    ambiguous = 1;
762                    result = NULL;
763                    break;
764                }
765                result = t;
766            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
767                if (result) {
768                    if (error_out)
769                        *error_out = "more than one emulator";
770                    ambiguous = 1;
771                    result = NULL;
772                    break;
773                }
774                result = t;
775            } else if (ttype == kTransportAny) {
776                if (result) {
777                    if (error_out)
778                        *error_out = "more than one device and emulator";
779                    ambiguous = 1;
780                    result = NULL;
781                    break;
782                }
783                result = t;
784            }
785        }
786    }
787    adb_mutex_unlock(&transport_lock);
788
789    if (result) {
790         /* offline devices are ignored -- they are either being born or dying */
791        if (result && result->connection_state == CS_OFFLINE) {
792            if (error_out)
793                *error_out = "device offline";
794            result = NULL;
795        }
796         /* check for required connection state */
797        if (result && state != CS_ANY && result->connection_state != state) {
798            if (error_out)
799                *error_out = "invalid device state";
800            result = NULL;
801        }
802    }
803
804    if (result) {
805        /* found one that we can take */
806        if (error_out)
807            *error_out = NULL;
808    } else if (state != CS_ANY && (serial || !ambiguous)) {
809        adb_sleep_ms(1000);
810        goto retry;
811    }
812
813    return result;
814}
815
816#if ADB_HOST
817static const char *statename(atransport *t)
818{
819    switch(t->connection_state){
820    case CS_OFFLINE: return "offline";
821    case CS_BOOTLOADER: return "bootloader";
822    case CS_DEVICE: return "device";
823    case CS_HOST: return "host";
824    case CS_RECOVERY: return "recovery";
825    case CS_NOPERM: return "no permissions";
826    default: return "unknown";
827    }
828}
829
830int list_transports(char *buf, size_t  bufsize)
831{
832    char*       p   = buf;
833    char*       end = buf + bufsize;
834    int         len;
835    atransport *t;
836
837        /* XXX OVERRUN PROBLEMS XXX */
838    adb_mutex_lock(&transport_lock);
839    for(t = transport_list.next; t != &transport_list; t = t->next) {
840        const char* serial = t->serial;
841        if (!serial || !serial[0])
842            serial = "????????????";
843        len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
844
845        if (p + len >= end) {
846            /* discard last line if buffer is too short */
847            break;
848        }
849        p += len;
850    }
851    p[0] = 0;
852    adb_mutex_unlock(&transport_lock);
853    return p - buf;
854}
855
856
857/* hack for osx */
858void close_usb_devices()
859{
860    atransport *t;
861
862    adb_mutex_lock(&transport_lock);
863    for(t = transport_list.next; t != &transport_list; t = t->next) {
864        if ( !t->kicked ) {
865            t->kicked = 1;
866            t->kick(t);
867        }
868    }
869    adb_mutex_unlock(&transport_lock);
870}
871#endif // ADB_HOST
872
873void register_socket_transport(int s, const char *serial, int port, int local)
874{
875    atransport *t = calloc(1, sizeof(atransport));
876    char buff[32];
877
878    if (!serial) {
879        snprintf(buff, sizeof buff, "T-%p", t);
880        serial = buff;
881    }
882    D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
883    if ( init_socket_transport(t, s, port, local) < 0 ) {
884        adb_close(s);
885        free(t);
886        return;
887    }
888    if(serial) {
889        t->serial = strdup(serial);
890    }
891    register_transport(t);
892}
893
894#if ADB_HOST
895atransport *find_transport(const char *serial)
896{
897    atransport *t;
898
899    adb_mutex_lock(&transport_lock);
900    for(t = transport_list.next; t != &transport_list; t = t->next) {
901        if (t->serial && !strcmp(serial, t->serial)) {
902            break;
903        }
904     }
905    adb_mutex_unlock(&transport_lock);
906
907    if (t != &transport_list)
908        return t;
909    else
910        return 0;
911}
912
913void unregister_transport(atransport *t)
914{
915    adb_mutex_lock(&transport_lock);
916    t->next->prev = t->prev;
917    t->prev->next = t->next;
918    adb_mutex_unlock(&transport_lock);
919
920    kick_transport(t);
921    transport_unref(t);
922}
923
924// unregisters all non-emulator TCP transports
925void unregister_all_tcp_transports()
926{
927    atransport *t, *next;
928    adb_mutex_lock(&transport_lock);
929    for (t = transport_list.next; t != &transport_list; t = next) {
930        next = t->next;
931        if (t->type == kTransportLocal && t->adb_port == 0) {
932            t->next->prev = t->prev;
933            t->prev->next = next;
934            // we cannot call kick_transport when holding transport_lock
935            if (!t->kicked)
936            {
937                t->kicked = 1;
938                t->kick(t);
939            }
940            transport_unref_locked(t);
941        }
942     }
943
944    adb_mutex_unlock(&transport_lock);
945}
946
947#endif
948
949void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
950{
951    atransport *t = calloc(1, sizeof(atransport));
952    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
953      serial ? serial : "");
954    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
955    if(serial) {
956        t->serial = strdup(serial);
957    }
958    register_transport(t);
959}
960
961/* this should only be used for transports with connection_state == CS_NOPERM */
962void unregister_usb_transport(usb_handle *usb)
963{
964    atransport *t;
965    adb_mutex_lock(&transport_lock);
966    for(t = transport_list.next; t != &transport_list; t = t->next) {
967        if (t->usb == usb && t->connection_state == CS_NOPERM) {
968            t->next->prev = t->prev;
969            t->prev->next = t->next;
970            break;
971        }
972     }
973    adb_mutex_unlock(&transport_lock);
974}
975
976#undef TRACE_TAG
977#define TRACE_TAG  TRACE_RWX
978
979int readx(int fd, void *ptr, size_t len)
980{
981    char *p = ptr;
982    int r;
983#if ADB_TRACE
984    int  len0 = len;
985#endif
986    D("readx: fd=%d wanted=%d\n", fd, (int)len);
987    while(len > 0) {
988        r = adb_read(fd, p, len);
989        if(r > 0) {
990            len -= r;
991            p += r;
992        } else {
993            if (r < 0) {
994                D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
995                if (errno == EINTR)
996                    continue;
997            } else {
998                D("readx: fd=%d disconnected\n", fd);
999            }
1000            return -1;
1001        }
1002    }
1003
1004#if ADB_TRACE
1005    D("readx: fd=%d wanted=%d got=%d\n", fd, len0, len0 - len);
1006    dump_hex( ptr, len0 );
1007#endif
1008    return 0;
1009}
1010
1011int writex(int fd, const void *ptr, size_t len)
1012{
1013    char *p = (char*) ptr;
1014    int r;
1015
1016#if ADB_TRACE
1017    D("writex: fd=%d len=%d: ", fd, (int)len);
1018    dump_hex( ptr, len );
1019#endif
1020    while(len > 0) {
1021        r = adb_write(fd, p, len);
1022        if(r > 0) {
1023            len -= r;
1024            p += r;
1025        } else {
1026            if (r < 0) {
1027                D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
1028                if (errno == EINTR)
1029                    continue;
1030            } else {
1031                D("writex: fd=%d disconnected\n", fd);
1032            }
1033            return -1;
1034        }
1035    }
1036    return 0;
1037}
1038
1039int check_header(apacket *p)
1040{
1041    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
1042        D("check_header(): invalid magic\n");
1043        return -1;
1044    }
1045
1046    if(p->msg.data_length > MAX_PAYLOAD) {
1047        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
1048        return -1;
1049    }
1050
1051    return 0;
1052}
1053
1054int check_data(apacket *p)
1055{
1056    unsigned count, sum;
1057    unsigned char *x;
1058
1059    count = p->msg.data_length;
1060    x = p->data;
1061    sum = 0;
1062    while(count-- > 0) {
1063        sum += *x++;
1064    }
1065
1066    if(sum != p->msg.data_check) {
1067        return -1;
1068    } else {
1069        return 0;
1070    }
1071}
1072
1073