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