19270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/*
29270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Copyright (C) 2007 The Android Open Source Project
39270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
49270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Licensed under the Apache License, Version 2.0 (the "License");
59270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * you may not use this file except in compliance with the License.
69270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * You may obtain a copy of the License at
79270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
89270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *      http://www.apache.org/licenses/LICENSE-2.0
99270a20a801403c9f60d6a701b39eae70d380403Doug Zongker *
109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * Unless required by applicable law or agreed to in writing, software
119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * distributed under the License is distributed on an "AS IS" BASIS,
129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * See the License for the specific language governing permissions and
149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker * limitations under the License.
159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker */
169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <stdio.h>
189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <stdlib.h>
199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <unistd.h>
209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <string.h>
219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include <errno.h>
229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include "sysdeps.h"
249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#define   TRACE_TAG  TRACE_TRANSPORT
269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#include "adb.h"
279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
289270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void transport_unref(atransport *t);
299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
309270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic atransport transport_list = {
319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    .next = &transport_list,
329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    .prev = &transport_list,
339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker};
349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
359270a20a801403c9f60d6a701b39eae70d380403Doug ZongkerADB_MUTEX_DEFINE( transport_lock );
369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#define MAX_DUMP_HEX_LEN 16
399270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void  dump_hex( const unsigned char*  ptr, size_t  len )
409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int  nn, len2 = len;
429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    // Build a string instead of logging each character.
439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for (nn = 0; nn < len2; nn++) {
499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        sprintf(pb, "%02x", ptr[nn]);
509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        pb += 2;
519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    sprintf(pb++, " ");
539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for (nn = 0; nn < len2; nn++) {
559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        int  c = ptr[nn];
569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (c < 32 || c > 127)
579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            c = '.';
589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        *pb++ =  c;
599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    *pb++ = '\0';
619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    DR("%s\n", buffer);
629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
659270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid
669270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerkick_transport(atransport*  t)
679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t && !t->kicked)
699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    {
709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        int  kicked;
719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_lock(&transport_lock);
739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        kicked = t->kicked;
749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (!kicked)
759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->kicked = 1;
769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_unlock(&transport_lock);
779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (!kicked)
799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->kick(t);
809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
839270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid
849270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerrun_transport_disconnects(atransport*  t)
859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adisconnect*  dis = t->disconnects.next;
879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: run_transport_disconnects\n", t->serial);
899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while (dis != &t->disconnects) {
909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adisconnect*  next = dis->next;
919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        dis->func( dis->opaque, t );
929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        dis = next;
939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
979270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void
989270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerdump_packet(const char* name, const char* func, apacket* p)
999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned  command = p->msg.command;
1019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int       len     = p->msg.data_length;
1029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char      cmd[9];
1039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char      arg0[12], arg1[12];
1049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int       n;
1059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for (n = 0; n < 4; n++) {
1079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        int  b = (command >> (n*8)) & 255;
1089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (b < 32 || b >= 127)
1099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            break;
1109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        cmd[n] = (char)b;
1119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (n == 4) {
1139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        cmd[4] = 0;
1149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else {
1159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* There is some non-ASCII name in the command, so dump
1169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            * the hexadecimal value instead */
1179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(cmd, sizeof cmd, "%08x", command);
1189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (p->msg.arg0 < 256U)
1219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
1229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    else
1239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
1249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (p->msg.arg1 < 256U)
1269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
1279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    else
1289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
1299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
1319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        name, func, cmd, arg0, arg1, len);
1329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dump_hex(p->data, len);
1339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif /* ADB_TRACE */
1359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1369270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int
1379270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerread_packet(int  fd, const char* name, apacket** ppacket)
1389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p = (char*)ppacket;  /* really read a packet address */
1409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   r;
1419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   len = sizeof(*ppacket);
1429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char  buff[8];
1439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (!name) {
1449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(buff, sizeof buff, "fd=%d", fd);
1459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        name = buff;
1469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
1489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_read(fd, p, len);
1499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
1509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
1519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p   += r;
1529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
1539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
1549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((r < 0) && (errno == EINTR)) continue;
1559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
1569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
1579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
1609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (ADB_TRACING) {
1619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        dump_packet(name, "from remote", *ppacket);
1629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
1649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
1659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1679270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int
1689270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerwrite_packet(int  fd, const char* name, apacket** ppacket)
1699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
1709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p = (char*) ppacket;  /* we really write the packet address */
1719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int r, len = sizeof(ppacket);
1729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char buff[8];
1739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (!name) {
1749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        snprintf(buff, sizeof buff, "fd=%d", fd);
1759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        name = buff;
1769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
1799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (ADB_TRACING) {
1809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        dump_packet(name, "to remote", *ppacket);
1819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
1839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    len = sizeof(ppacket);
1849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
1859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_write(fd, p, len);
1869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
1879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
1889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p += r;
1899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
1909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
1919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((r < 0) && (errno == EINTR)) continue;
1929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
1939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
1949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
1959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
1969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
1979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
1989270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void transport_socket_events(int fd, unsigned events, void *_t)
1999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t = _t;
2019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
2029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(events & FDE_READ){
2039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        apacket *p = 0;
2049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(read_packet(fd, t->serial, &p)){
2059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
2069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
2079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            handle_packet(p, (atransport *) _t);
2089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
2099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2129270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid send_packet(apacket *p, atransport *t)
2139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned char *x;
2159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned sum;
2169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned count;
2179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.magic = p->msg.command ^ 0xffffffff;
2199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    count = p->msg.data_length;
2219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    x = (unsigned char *) p->data;
2229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    sum = 0;
2239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(count-- > 0){
2249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        sum += *x++;
2259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.data_check = sum;
2279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    print_packet("send", p);
2299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t == NULL) {
2319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("Transport is null \n");
2329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        // Zap errno because print_packet() and other stuff have errno effect.
2339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        errno = 0;
2349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("Transport is null");
2359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(write_packet(t->transport_socket, t->serial, &p)){
2389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("cannot enqueue packet on transport socket");
2399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
2419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/* The transport is opened by transport_register_func before
2439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** the input and output threads are started.
2449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker**
2459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** The output thread issues a SYNC(1, token) message to let
2469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** the input thread know to start things up.  In the event
2479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** of transport IO failure, the output thread will post a
2489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** SYNC(0,0) message to ensure shutdown.
2499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker**
2509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** The transport will not actually be closed until both
2519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** threads exit, but the input thread will kick the transport
2529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker** on its way out to disconnect the underlying device.
2539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker*/
2549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2559270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void *output_thread(void *_t)
2569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
2579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t = _t;
2589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *p;
2599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
2619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker       t->serial, t->fd, t->sync_token + 1);
2629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p = get_apacket();
2639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.command = A_SYNC;
2649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg0 = 1;
2659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg1 = ++(t->sync_token);
2669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.magic = A_SYNC ^ 0xffffffff;
2679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(write_packet(t->fd, t->serial, &p)) {
2689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        put_apacket(p);
2699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("%s: failed to write SYNC packet\n", t->serial);
2709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        goto oops;
2719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: data pump started\n", t->serial);
2749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for(;;) {
2759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        p = get_apacket();
2769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(t->read_from_remote(p, t) == 0){
2789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: received remote packet, sending to transport\n",
2799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker              t->serial);
2809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if(write_packet(t->fd, t->serial, &p)){
2819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                put_apacket(p);
2829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("%s: failed to write apacket to transport\n", t->serial);
2839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                goto oops;
2849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
2859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
2869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: remote read failed for transport\n", t->serial);
2879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            put_apacket(p);
2889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            break;
2899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
2909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
2919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
2929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: SYNC offline for transport\n", t->serial);
2939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p = get_apacket();
2949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.command = A_SYNC;
2959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg0 = 0;
2969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.arg1 = 0;
2979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    p->msg.magic = A_SYNC ^ 0xffffffff;
2989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(write_packet(t->fd, t->serial, &p)) {
2999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        put_apacket(p);
3009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("%s: failed to write SYNC apacket to transport", t->serial);
3019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
3029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3039270a20a801403c9f60d6a701b39eae70d380403Doug Zongkeroops:
3049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: transport output thread is exiting\n", t->serial);
3059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    kick_transport(t);
3069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    transport_unref(t);
3079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
3089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
3099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3109270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void *input_thread(void *_t)
3119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
3129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t = _t;
3139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    apacket *p;
3149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int active = 0;
3159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: starting transport input thread, reading from fd %d\n",
3179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker       t->serial, t->fd);
3189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for(;;){
3209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(read_packet(t->fd, t->serial, &p)) {
3219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("%s: failed to read apacket from transport on fd %d\n",
3229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker               t->serial, t->fd );
3239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            break;
3249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(p->msg.command == A_SYNC){
3269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if(p->msg.arg0 == 0) {
3279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("%s: transport SYNC offline\n", t->serial);
3289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                put_apacket(p);
3299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                break;
3309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else {
3319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if(p->msg.arg1 == t->sync_token) {
3329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    D("%s: transport SYNC online\n", t->serial);
3339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    active = 1;
3349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                } else {
3359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    D("%s: transport ignoring SYNC %d != %d\n",
3369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                      t->serial, p->msg.arg1, t->sync_token);
3379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
3389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
3399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
3409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if(active) {
3419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("%s: transport got packet, sending to remote\n", t->serial);
3429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                t->write_to_remote(p, t);
3439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else {
3449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("%s: transport ignoring packet while offline\n", t->serial);
3459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
3469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        put_apacket(p);
3499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
3509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    // this is necessary to avoid a race condition that occured when a transport closes
3529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    // while a client socket is still active.
3539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    close_all_sockets(t);
3549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
3569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    kick_transport(t);
3579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    transport_unref(t);
3589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
3599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
3609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3629270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int transport_registration_send = -1;
3639270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int transport_registration_recv = -1;
3649270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic fdevent transport_registration_fde;
3659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3669270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid  update_transports(void)
3679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
3689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    // nothing to do on the device side
3699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
3709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3719270a20a801403c9f60d6a701b39eae70d380403Doug Zongkertypedef struct tmsg tmsg;
3729270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstruct tmsg
3739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
3749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *transport;
3759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int         action;
3769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker};
3779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3789270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int
3799270a20a801403c9f60d6a701b39eae70d380403Doug Zongkertransport_read_action(int  fd, struct tmsg*  m)
3809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
3819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p   = (char*)m;
3829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   len = sizeof(*m);
3839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   r;
3849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
3859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
3869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_read(fd, p, len);
3879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
3889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
3899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p   += r;
3909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
3919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((r < 0) && (errno == EINTR)) continue;
3929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("transport_read_action: on fd %d, error %d: %s\n",
3939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker              fd, errno, strerror(errno));
3949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
3959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
3969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
3979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
3989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
3999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4009270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic int
4019270a20a801403c9f60d6a701b39eae70d380403Doug Zongkertransport_write_action(int  fd, struct tmsg*  m)
4029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
4039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p   = (char*)m;
4049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   len = sizeof(*m);
4059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int   r;
4069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
4089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_write(fd, p, len);
4099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
4109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
4119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p   += r;
4129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
4139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if((r < 0) && (errno == EINTR)) continue;
4149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            D("transport_write_action: on fd %d, error %d: %s\n",
4159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker              fd, errno, strerror(errno));
4169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
4179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
4189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
4199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
4209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
4219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4229270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void transport_registration_func(int _fd, unsigned ev, void *data)
4239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
4249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    tmsg m;
4259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_thread_t output_thread_ptr;
4269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_thread_t input_thread_ptr;
4279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int s[2];
4289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t;
4299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(!(ev & FDE_READ)) {
4319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
4329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
4339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(transport_read_action(_fd, &m)) {
4359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("cannot read transport registration socket");
4369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
4379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t = m.transport;
4399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(m.action == 0){
4419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
4429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            /* IMPORTANT: the remove closes one half of the
4449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            ** socket pair.  The close closes the other half.
4459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            */
4469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fdevent_remove(&(t->transport_fde));
4479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_close(t->fd);
4489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_lock(&transport_lock);
4509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->next->prev = t->prev;
4519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->prev->next = t->next;
4529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_unlock(&transport_lock);
4539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        run_transport_disconnects(t);
4559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (t->product)
4579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            free(t->product);
4589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (t->serial)
4599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            free(t->serial);
4609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        memset(t,0xee,sizeof(atransport));
4629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        free(t);
4639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        update_transports();
4659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return;
4669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
4679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    /* don't create transport threads for inaccessible devices */
4699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t->connection_state != CS_NOPERM) {
4709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* initial references are the two threads */
4719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->ref_count = 2;
4729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(adb_socketpair(s)) {
4749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            fatal_errno("cannot open transport socketpair");
4759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
4769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
4789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->transport_socket = s[0];
4809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->fd = s[1];
4819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fdevent_install(&(t->transport_fde),
4839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        t->transport_socket,
4849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        transport_socket_events,
4859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        t);
4869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fdevent_set(&(t->transport_fde), FDE_READ);
4889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
4909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            fatal_errno("cannot create input thread");
4919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
4929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
4949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            fatal_errno("cannot create output thread");
4959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
4969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
4979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
4989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* put us on the master device list */
4999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_lock(&transport_lock);
5009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->next = &transport_list;
5019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->prev = transport_list.prev;
5029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->next->prev = t;
5039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->prev->next = t;
5049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_unlock(&transport_lock);
5059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->disconnects.next = t->disconnects.prev = &t->disconnects;
5079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    update_transports();
5099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5119270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid init_transport_registration(void)
5129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int s[2];
5149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(adb_socketpair(s)){
5169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("cannot open transport registration socketpair");
5179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
5189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    transport_registration_send = s[0];
5209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    transport_registration_recv = s[1];
5219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fdevent_install(&transport_registration_fde,
5239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    transport_registration_recv,
5249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    transport_registration_func,
5259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    0);
5269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    fdevent_set(&transport_registration_fde, FDE_READ);
5289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/* the fdevent select pump is single threaded */
5319270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void register_transport(atransport *transport)
5329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    tmsg m;
5349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    m.transport = transport;
5359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    m.action = 1;
5369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("transport: %s registered\n", transport->serial);
5379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(transport_write_action(transport_registration_send, &m)) {
5389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("cannot write transport registration socket\n");
5399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
5409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5429270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void remove_transport(atransport *transport)
5439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    tmsg m;
5459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    m.transport = transport;
5469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    m.action = 0;
5479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("transport: %s removed\n", transport->serial);
5489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(transport_write_action(transport_registration_send, &m)) {
5499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        fatal_errno("cannot write transport registration socket\n");
5509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
5519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5549270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void transport_unref_locked(atransport *t)
5559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    t->ref_count--;
5579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t->ref_count == 0) {
5589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("transport: %s unref (kicking and closing)\n", t->serial);
5599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (!t->kicked) {
5609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->kicked = 1;
5619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->kick(t);
5629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
5639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->close(t);
5649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        remove_transport(t);
5659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else {
5669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
5679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
5689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5709270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerstatic void transport_unref(atransport *t)
5719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (t) {
5739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_lock(&transport_lock);
5749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        transport_unref_locked(t);
5759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_mutex_unlock(&transport_lock);
5769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
5779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5799270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid add_transport_disconnect(atransport*  t, adisconnect*  dis)
5809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_lock(&transport_lock);
5829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->next       = &t->disconnects;
5839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->prev       = dis->next->prev;
5849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->prev->next = dis;
5859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->next->prev = dis;
5869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_unlock(&transport_lock);
5879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5899270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid remove_transport_disconnect(atransport*  t, adisconnect*  dis)
5909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->prev->next = dis->next;
5929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->next->prev = dis->prev;
5939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dis->next = dis->prev = dis;
5949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
5959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
5979270a20a801403c9f60d6a701b39eae70d380403Doug Zongkeratransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
5989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
5999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t;
6009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *result = NULL;
6019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int ambiguous = 0;
6029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6039270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerretry:
6049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (error_out)
6059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        *error_out = "device not found";
6069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_lock(&transport_lock);
6089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for (t = transport_list.next; t != &transport_list; t = t->next) {
6099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (t->connection_state == CS_NOPERM) {
6109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (error_out)
6119270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            *error_out = "insufficient permissions for device";
6129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            continue;
6139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
6149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* check for matching serial number */
6169270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (serial) {
6179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (t->serial && !strcmp(serial, t->serial)) {
6189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                result = t;
6199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                break;
6209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
6219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
6229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (ttype == kTransportUsb && t->type == kTransportUsb) {
6239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (result) {
6249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    if (error_out)
6259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        *error_out = "more than one device";
6269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    ambiguous = 1;
6279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    result = NULL;
6289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    break;
6299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
6309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                result = t;
6319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
6329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (result) {
6339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    if (error_out)
6349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        *error_out = "more than one emulator";
6359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    ambiguous = 1;
6369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    result = NULL;
6379270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    break;
6389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
6399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                result = t;
6409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else if (ttype == kTransportAny) {
6419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (result) {
6429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    if (error_out)
6439270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                        *error_out = "more than one device and emulator";
6449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    ambiguous = 1;
6459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    result = NULL;
6469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    break;
6479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                }
6489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                result = t;
6499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
6509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
6519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
6529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_unlock(&transport_lock);
6539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (result) {
6559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker         /* offline devices are ignored -- they are either being born or dying */
6569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (result && result->connection_state == CS_OFFLINE) {
6579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (error_out)
6589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                *error_out = "device offline";
6599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            result = NULL;
6609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
6619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker         /* check for required connection state */
6629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (result && state != CS_ANY && result->connection_state != state) {
6639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (error_out)
6649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                *error_out = "invalid device state";
6659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            result = NULL;
6669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
6679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
6689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if (result) {
6709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        /* found one that we can take */
6719270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (error_out)
6729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            *error_out = NULL;
6739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else if (state != CS_ANY && (serial || !ambiguous)) {
6749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        adb_sleep_ms(1000);
6759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        goto retry;
6769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
6779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return result;
6799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
6809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6819270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
6829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
6839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t = calloc(1, sizeof(atransport));
6849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
6859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker      serial ? serial : "");
6869270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
6879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(serial) {
6889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        t->serial = strdup(serial);
6899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
6909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    register_transport(t);
6919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
6929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
6939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker/* this should only be used for transports with connection_state == CS_NOPERM */
6949270a20a801403c9f60d6a701b39eae70d380403Doug Zongkervoid unregister_usb_transport(usb_handle *usb)
6959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
6969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    atransport *t;
6979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_lock(&transport_lock);
6989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    for(t = transport_list.next; t != &transport_list; t = t->next) {
6999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if (t->usb == usb && t->connection_state == CS_NOPERM) {
7009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->next->prev = t->prev;
7019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            t->prev->next = t->next;
7029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            break;
7039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
7049270a20a801403c9f60d6a701b39eae70d380403Doug Zongker     }
7059270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    adb_mutex_unlock(&transport_lock);
7069270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
7079270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7089270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#undef TRACE_TAG
7099270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#define TRACE_TAG  TRACE_RWX
7109270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7119270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint readx(int fd, void *ptr, size_t len)
7129270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
7139270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p = ptr;
7149270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int r;
7159270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
716f3bb31c32fa879ccce358c15c93b7bd8582d1756Mark Salyzyn    size_t len0 = len;
7179270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
7189270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("readx: fd=%d wanted=%d\n", fd, (int)len);
7199270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
7209270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_read(fd, p, len);
7219270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
7229270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
7239270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p += r;
7249270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
7259270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (r < 0) {
7269270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
7279270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (errno == EINTR)
7289270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    continue;
7299270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else {
7309270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("readx: fd=%d disconnected\n", fd);
7319270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
7329270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
7339270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
7349270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
7359270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7369270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
737f3bb31c32fa879ccce358c15c93b7bd8582d1756Mark Salyzyn    D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
7389270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dump_hex( ptr, len0 );
7399270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
7409270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
7419270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
7429270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7439270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint writex(int fd, const void *ptr, size_t len)
7449270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
7459270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    char *p = (char*) ptr;
7469270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    int r;
7479270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7489270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#if ADB_TRACE
7499270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    D("writex: fd=%d len=%d: ", fd, (int)len);
7509270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    dump_hex( ptr, len );
7519270a20a801403c9f60d6a701b39eae70d380403Doug Zongker#endif
7529270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(len > 0) {
7539270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        r = adb_write(fd, p, len);
7549270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        if(r > 0) {
7559270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            len -= r;
7569270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            p += r;
7579270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        } else {
7589270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            if (r < 0) {
7599270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
7609270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                if (errno == EINTR)
7619270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                    continue;
7629270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            } else {
7639270a20a801403c9f60d6a701b39eae70d380403Doug Zongker                D("writex: fd=%d disconnected\n", fd);
7649270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            }
7659270a20a801403c9f60d6a701b39eae70d380403Doug Zongker            return -1;
7669270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        }
7679270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
7689270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
7699270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
7709270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7719270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint check_header(apacket *p)
7729270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
7739270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
7749270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("check_header(): invalid magic\n");
7759270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return -1;
7769270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
7779270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7789270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(p->msg.data_length > MAX_PAYLOAD) {
7799270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
7809270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return -1;
7819270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
7829270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7839270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    return 0;
7849270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
7859270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7869270a20a801403c9f60d6a701b39eae70d380403Doug Zongkerint check_data(apacket *p)
7879270a20a801403c9f60d6a701b39eae70d380403Doug Zongker{
7889270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned count, sum;
7899270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    unsigned char *x;
7909270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7919270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    count = p->msg.data_length;
7929270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    x = p->data;
7939270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    sum = 0;
7949270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    while(count-- > 0) {
7959270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        sum += *x++;
7969270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
7979270a20a801403c9f60d6a701b39eae70d380403Doug Zongker
7989270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    if(sum != p->msg.data_check) {
7999270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return -1;
8009270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    } else {
8019270a20a801403c9f60d6a701b39eae70d380403Doug Zongker        return 0;
8029270a20a801403c9f60d6a701b39eae70d380403Doug Zongker    }
8039270a20a801403c9f60d6a701b39eae70d380403Doug Zongker}
804