transport.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
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        /* initial references are the two threads */
588    t->ref_count = 2;
589
590    if(adb_socketpair(s)) {
591        fatal_errno("cannot open transport socketpair");
592    }
593
594    D("transport: %p (%d,%d) starting\n", t, s[0], s[1]);
595
596    t->transport_socket = s[0];
597    t->fd = s[1];
598
599        /* put us on the master device list */
600    adb_mutex_lock(&transport_lock);
601    t->next = &transport_list;
602    t->prev = transport_list.prev;
603    t->next->prev = t;
604    t->prev->next = t;
605    adb_mutex_unlock(&transport_lock);
606
607    D("transport: %p install %d\n", t, t->transport_socket );
608    fdevent_install(&(t->transport_fde),
609                    t->transport_socket,
610                    transport_socket_events,
611                    t);
612
613    fdevent_set(&(t->transport_fde), FDE_READ);
614
615    if(adb_thread_create(&input_thread_ptr, input_thread, t)){
616        fatal_errno("cannot create input thread");
617    }
618
619    if(adb_thread_create(&output_thread_ptr, output_thread, t)){
620        fatal_errno("cannot create output thread");
621    }
622
623    t->disconnects.next = t->disconnects.prev = &t->disconnects;
624
625    update_transports();
626}
627
628void init_transport_registration(void)
629{
630    int s[2];
631
632    if(adb_socketpair(s)){
633        fatal_errno("cannot open transport registration socketpair");
634    }
635
636    transport_registration_send = s[0];
637    transport_registration_recv = s[1];
638
639    fdevent_install(&transport_registration_fde,
640                    transport_registration_recv,
641                    transport_registration_func,
642                    0);
643
644    fdevent_set(&transport_registration_fde, FDE_READ);
645}
646
647/* the fdevent select pump is single threaded */
648static void register_transport(atransport *transport)
649{
650    tmsg m;
651    m.transport = transport;
652    m.action = 1;
653    D("transport: %p registered\n", transport);
654    if(transport_write_action(transport_registration_send, &m)) {
655        fatal_errno("cannot write transport registration socket\n");
656    }
657}
658
659static void remove_transport(atransport *transport)
660{
661    tmsg m;
662    m.transport = transport;
663    m.action = 0;
664    D("transport: %p removed\n", transport);
665    if(transport_write_action(transport_registration_send, &m)) {
666        fatal_errno("cannot write transport registration socket\n");
667    }
668}
669
670
671static void transport_unref(atransport *t)
672{
673    if (t) {
674        adb_mutex_lock(&transport_lock);
675        t->ref_count--;
676        D("transport: %p R- (ref=%d)\n", t, t->ref_count);
677        if (t->ref_count == 0) {
678            D("transport: %p kicking and closing\n", t);
679            if (!t->kicked) {
680                t->kicked = 1;
681                t->kick(t);
682            }
683            t->close(t);
684            remove_transport(t);
685        }
686        adb_mutex_unlock(&transport_lock);
687    }
688}
689
690void add_transport_disconnect(atransport*  t, adisconnect*  dis)
691{
692    adb_mutex_lock(&transport_lock);
693    dis->next       = &t->disconnects;
694    dis->prev       = dis->next->prev;
695    dis->prev->next = dis;
696    dis->next->prev = dis;
697    adb_mutex_unlock(&transport_lock);
698}
699
700void remove_transport_disconnect(atransport*  t, adisconnect*  dis)
701{
702    dis->prev->next = dis->next;
703    dis->next->prev = dis->prev;
704    dis->next = dis->prev = dis;
705}
706
707
708atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
709{
710    atransport *t;
711    atransport *result = NULL;
712    int ambiguous = 0;
713
714retry:
715    if (error_out)
716        *error_out = "device not found";
717
718    adb_mutex_lock(&transport_lock);
719    for (t = transport_list.next; t != &transport_list; t = t->next) {
720        /* check for matching serial number */
721        if (serial) {
722            if (t->serial && !strcmp(serial, t->serial)) {
723                result = t;
724                break;
725            }
726        } else {
727            if (ttype == kTransportUsb && t->type == kTransportUsb) {
728                if (result) {
729                    if (error_out)
730                        *error_out = "more than one device";
731                    ambiguous = 1;
732                    result = NULL;
733                    break;
734                }
735                result = t;
736            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
737                if (result) {
738                    if (error_out)
739                        *error_out = "more than one emulator";
740                    ambiguous = 1;
741                    result = NULL;
742                    break;
743                }
744                result = t;
745            } else if (ttype == kTransportAny) {
746                if (result) {
747                    if (error_out)
748                        *error_out = "more than one device and emulator";
749                    ambiguous = 1;
750                    result = NULL;
751                    break;
752                }
753                result = t;
754            }
755        }
756    }
757    adb_mutex_unlock(&transport_lock);
758
759    if (result) {
760         /* offline devices are ignored -- they are either being born or dying */
761        if (result && result->connection_state == CS_OFFLINE) {
762            if (error_out)
763                *error_out = "device offline";
764            result = NULL;
765        }
766
767         /* check for required connection state */
768        if (result && state != CS_ANY && result->connection_state != state) {
769            if (error_out)
770                *error_out = "invalid device state";
771            result = NULL;
772        }
773    }
774
775    if (result) {
776        /* found one that we can take */
777        if (error_out)
778            *error_out = NULL;
779    } else if (state != CS_ANY && (serial || !ambiguous)) {
780        adb_sleep_ms(1000);
781        goto retry;
782    }
783
784    return result;
785}
786
787#if ADB_HOST
788static const char *statename(atransport *t)
789{
790    switch(t->connection_state){
791    case CS_OFFLINE: return "offline";
792    case CS_BOOTLOADER: return "bootloader";
793    case CS_DEVICE: return "device";
794    case CS_HOST: return "host";
795    case CS_RECOVERY: return "recovery";
796    default: return "unknown";
797    }
798}
799
800int list_transports(char *buf, size_t  bufsize)
801{
802    char*       p   = buf;
803    char*       end = buf + bufsize;
804    int         len;
805    atransport *t;
806
807        /* XXX OVERRUN PROBLEMS XXX */
808    adb_mutex_lock(&transport_lock);
809    for(t = transport_list.next; t != &transport_list; t = t->next) {
810        len = snprintf(p, end - p, "%s\t%s\n",
811                t->serial ? t->serial : "",
812                statename(t));
813
814        if (p + len >= end) {
815            /* discard last line if buffer is too short */
816            break;
817        }
818        p += len;
819    }
820    p[0] = 0;
821    adb_mutex_unlock(&transport_lock);
822    return p - buf;
823}
824
825
826/* hack for osx */
827void close_usb_devices()
828{
829    atransport *t;
830
831    adb_mutex_lock(&transport_lock);
832    for(t = transport_list.next; t != &transport_list; t = t->next) {
833        if ( !t->kicked ) {
834            t->kicked = 1;
835            t->kick(t);
836        }
837    }
838    adb_mutex_unlock(&transport_lock);
839}
840#endif // ADB_HOST
841
842void register_socket_transport(int s, const char *serial, int  port)
843{
844    atransport *t = calloc(1, sizeof(atransport));
845    D("transport: %p init'ing for socket %d, on port %d\n", t, s, port);
846    if ( init_socket_transport(t, s, port) < 0 ) {
847        adb_close(s);
848        free(t);
849        return;
850    }
851    if(serial) {
852        t->serial = strdup(serial);
853    }
854    register_transport(t);
855}
856
857void register_usb_transport(usb_handle *usb, const char *serial)
858{
859    atransport *t = calloc(1, sizeof(atransport));
860    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
861      serial ? serial : "");
862    init_usb_transport(t, usb);
863    if(serial) {
864        t->serial = strdup(serial);
865    }
866    register_transport(t);
867}
868
869
870#undef TRACE_TAG
871#define TRACE_TAG  TRACE_RWX
872
873int readx(int fd, void *ptr, size_t len)
874{
875    char *p = ptr;
876    int r;
877#if ADB_TRACE
878    int  len0 = len;
879#endif
880    D("readx: %d %p %d\n", fd, ptr, (int)len);
881    while(len > 0) {
882        r = adb_read(fd, p, len);
883        if(r > 0) {
884            len -= r;
885            p += r;
886        } else {
887            D("readx: %d %d %s\n", fd, r, strerror(errno));
888            if((r < 0) && (errno == EINTR)) continue;
889            return -1;
890        }
891    }
892
893#if ADB_TRACE
894    D("readx: %d ok: ", fd);
895    dump_hex( ptr, len0 );
896#endif
897    return 0;
898}
899
900int writex(int fd, const void *ptr, size_t len)
901{
902    char *p = (char*) ptr;
903    int r;
904
905#if ADB_TRACE
906    D("writex: %d %p %d: ", fd, ptr, (int)len);
907    dump_hex( ptr, len );
908#endif
909    while(len > 0) {
910        r = adb_write(fd, p, len);
911        if(r > 0) {
912            len -= r;
913            p += r;
914        } else {
915            D("writex: %d %d %s\n", fd, r, strerror(errno));
916            if((r < 0) && (errno == EINTR)) continue;
917            return -1;
918        }
919    }
920
921    D("writex: %d ok\n", fd);
922    return 0;
923}
924
925int check_header(apacket *p)
926{
927    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
928        D("check_header(): invalid magic\n");
929        return -1;
930    }
931
932    if(p->msg.data_length > MAX_PAYLOAD) {
933        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
934        return -1;
935    }
936
937    return 0;
938}
939
940int check_data(apacket *p)
941{
942    unsigned count, sum;
943    unsigned char *x;
944
945    count = p->msg.data_length;
946    x = p->data;
947    sum = 0;
948    while(count-- > 0) {
949        sum += *x++;
950    }
951
952    if(sum != p->msg.data_check) {
953        return -1;
954    } else {
955        return 0;
956    }
957}
958
959