transport.c revision 0927bf9690127bc45cf8837a1467759e9720399a
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
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void transport_unref(atransport *t)
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t) {
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_lock(&transport_lock);
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->ref_count--;
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("transport: %p R- (ref=%d)\n", t, t->ref_count);
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (t->ref_count == 0) {
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("transport: %p kicking and closing\n", t);
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!t->kicked) {
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                t->kicked = 1;
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                t->kick(t);
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t->close(t);
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            remove_transport(t);
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_unlock(&transport_lock);
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid add_transport_disconnect(atransport*  t, adisconnect*  dis)
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&transport_lock);
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->next       = &t->disconnects;
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->prev       = dis->next->prev;
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->prev->next = dis;
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->next->prev = dis;
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&transport_lock);
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid remove_transport_disconnect(atransport*  t, adisconnect*  dis)
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->prev->next = dis->next;
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->next->prev = dis->prev;
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dis->next = dis->prev = dis;
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectatransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t;
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *result = NULL;
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ambiguous = 0;
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectretry:
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (error_out)
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *error_out = "device not found";
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&transport_lock);
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (t = transport_list.next; t != &transport_list; t = t->next) {
7230927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        if (t->connection_state == CS_NOPERM) continue;
7240927bf9690127bc45cf8837a1467759e9720399aMike Lockwood
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* check for matching serial number */
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serial) {
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (t->serial && !strcmp(serial, t->serial)) {
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                result = t;
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ttype == kTransportUsb && t->type == kTransportUsb) {
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (result) {
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (error_out)
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        *error_out = "more than one device";
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ambiguous = 1;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    result = NULL;
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    break;
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                result = t;
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
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 emulator";
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 == kTransportAny) {
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 device and 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            }
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&transport_lock);
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (result) {
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         /* offline devices are ignored -- they are either being born or dying */
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result && result->connection_state == CS_OFFLINE) {
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (error_out)
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *error_out = "device offline";
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            result = NULL;
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
7710927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        if (result && result->connection_state == CS_NOPERM) {
7720927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            if (error_out)
7730927bf9690127bc45cf8837a1467759e9720399aMike Lockwood                *error_out = "no permissions for device";
7740927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            result = NULL;
7750927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        }
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project         /* check for required connection state */
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result && state != CS_ANY && result->connection_state != state) {
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (error_out)
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *error_out = "invalid device state";
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            result = NULL;
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (result) {
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* found one that we can take */
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (error_out)
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *error_out = NULL;
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else if (state != CS_ANY && (serial || !ambiguous)) {
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_sleep_ms(1000);
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        goto retry;
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char *statename(atransport *t)
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(t->connection_state){
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_OFFLINE: return "offline";
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_BOOTLOADER: return "bootloader";
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_DEVICE: return "device";
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_HOST: return "host";
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_RECOVERY: return "recovery";
8060927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    case CS_NOPERM: return "no permissions";
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default: return "unknown";
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint list_transports(char *buf, size_t  bufsize)
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*       p   = buf;
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*       end = buf + bufsize;
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int         len;
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t;
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* XXX OVERRUN PROBLEMS XXX */
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&transport_lock);
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = transport_list.next; t != &transport_list; t = t->next) {
8210927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        const char* serial = t->serial;
8220927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        if (!serial || !serial[0])
8230927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            serial = "????????????";
8240927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        len = snprintf(p, end - p, "%s\t%s\n", serial, statename(t));
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (p + len >= end) {
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* discard last line if buffer is too short */
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p += len;
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p[0] = 0;
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&transport_lock);
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return p - buf;
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* hack for osx */
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid close_usb_devices()
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t;
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&transport_lock);
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = transport_list.next; t != &transport_list; t = t->next) {
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ( !t->kicked ) {
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t->kicked = 1;
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t->kick(t);
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&transport_lock);
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif // ADB_HOST
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid register_socket_transport(int s, const char *serial, int  port)
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t = calloc(1, sizeof(atransport));
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("transport: %p init'ing for socket %d, on port %d\n", t, s, port);
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ( init_socket_transport(t, s, port) < 0 ) {
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(s);
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(t);
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(serial) {
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->serial = strdup(serial);
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    register_transport(t);
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8690927bf9690127bc45cf8837a1467759e9720399aMike Lockwoodvoid register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    atransport *t = calloc(1, sizeof(atransport));
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      serial ? serial : "");
8740927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(serial) {
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->serial = strdup(serial);
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    register_transport(t);
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8810927bf9690127bc45cf8837a1467759e9720399aMike Lockwood/* this should only be used for transports with connection_state == CS_NOPERM */
8820927bf9690127bc45cf8837a1467759e9720399aMike Lockwoodvoid unregister_usb_transport(usb_handle *usb)
8830927bf9690127bc45cf8837a1467759e9720399aMike Lockwood{
8840927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    atransport *t;
8850927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    adb_mutex_lock(&transport_lock);
8860927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    for(t = transport_list.next; t != &transport_list; t = t->next) {
8870927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        if (t->usb == usb && t->connection_state == CS_NOPERM) {
8880927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            t->next->prev = t->prev;
8890927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            t->prev->next = t->next;
8900927bf9690127bc45cf8837a1467759e9720399aMike Lockwood            break;
8910927bf9690127bc45cf8837a1467759e9720399aMike Lockwood        }
8920927bf9690127bc45cf8837a1467759e9720399aMike Lockwood     }
8930927bf9690127bc45cf8837a1467759e9720399aMike Lockwood    adb_mutex_unlock(&transport_lock);
8940927bf9690127bc45cf8837a1467759e9720399aMike Lockwood}
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
896dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef TRACE_TAG
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE_TAG  TRACE_RWX
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint readx(int fd, void *ptr, size_t len)
900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *p = ptr;
902dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_TRACE
904dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  len0 = len;
905dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
906dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("readx: %d %p %d\n", fd, ptr, (int)len);
907dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(len > 0) {
908dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = adb_read(fd, p, len);
909dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r > 0) {
910dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len -= r;
911dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p += r;
912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("readx: %d %d %s\n", fd, r, strerror(errno));
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if((r < 0) && (errno == EINTR)) continue;
915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
918dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_TRACE
920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("readx: %d ok: ", fd);
921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dump_hex( ptr, len0 );
922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
923dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint writex(int fd, const void *ptr, size_t len)
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *p = (char*) ptr;
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int r;
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_TRACE
932dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("writex: %d %p %d: ", fd, ptr, (int)len);
933dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    dump_hex( ptr, len );
934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
935dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(len > 0) {
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = adb_write(fd, p, len);
937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(r > 0) {
938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len -= r;
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p += r;
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            D("writex: %d %d %s\n", fd, r, strerror(errno));
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if((r < 0) && (errno == EINTR)) continue;
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("writex: %d ok\n", fd);
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint check_header(apacket *p)
952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("check_header(): invalid magic\n");
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(p->msg.data_length > MAX_PAYLOAD) {
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint check_data(apacket *p)
967dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count, sum;
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned char *x;
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = p->msg.data_length;
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = p->data;
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sum = 0;
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(count-- > 0) {
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        sum += *x++;
976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(sum != p->msg.data_check) {
979dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
980dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
982dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
983dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
984dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
985