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