blob: 7e4f98ea36456cec786fda03fcfee3e1c54db207 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albert76649012015-02-24 15:51:19 -080018
Dan Albert33134262015-03-19 15:21:08 -070019#include "sysdeps.h"
Dan Albert76649012015-02-24 15:51:19 -080020#include "transport.h"
21
Dan Albert055f1aa2015-02-20 17:24:58 -080022#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <stdio.h>
25#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Spencer Low363af562015-11-07 18:51:54 -080029#include <algorithm>
Dan Albertc7915a32015-05-18 16:46:31 -070030#include <list>
31
Yabin Cuif4b99282015-08-27 12:03:11 -070032#include <base/logging.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070033#include <base/stringprintf.h>
Dan Albert1792c232015-05-18 13:06:53 -070034#include <base/strings.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070035
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#include "adb.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070037#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038
39static void transport_unref(atransport *t);
40
Dan Albertc7915a32015-05-18 16:46:31 -070041static std::list<atransport*> transport_list;
42static std::list<atransport*> pending_list;
Benoit Goby1c45ee92013-03-29 18:22:36 -070043
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044ADB_MUTEX_DEFINE( transport_lock );
45
Yabin Cuiaed3c612015-09-22 15:52:57 -070046static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010047 unsigned command = p->msg.command;
48 int len = p->msg.data_length;
49 char cmd[9];
50 char arg0[12], arg1[12];
51 int n;
52
53 for (n = 0; n < 4; n++) {
54 int b = (command >> (n*8)) & 255;
55 if (b < 32 || b >= 127)
56 break;
57 cmd[n] = (char)b;
58 }
59 if (n == 4) {
60 cmd[4] = 0;
61 } else {
62 /* There is some non-ASCII name in the command, so dump
63 * the hexadecimal value instead */
64 snprintf(cmd, sizeof cmd, "%08x", command);
65 }
66
67 if (p->msg.arg0 < 256U)
68 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
69 else
70 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
71
72 if (p->msg.arg1 < 256U)
73 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
74 else
75 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
76
Yabin Cuiaed3c612015-09-22 15:52:57 -070077 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
78 name, func, cmd, arg0, arg1, len);
79 result += dump_hex(p->data, len);
80 return result;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010081}
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010082
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010084read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080085{
Yabin Cui62641292015-07-30 19:58:10 -070086 char buff[8];
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010087 if (!name) {
88 snprintf(buff, sizeof buff, "fd=%d", fd);
89 name = buff;
90 }
Yabin Cui62641292015-07-30 19:58:10 -070091 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
92 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080093 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -070094 int r = adb_read(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080095 if(r > 0) {
96 len -= r;
Yabin Cui62641292015-07-30 19:58:10 -070097 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080098 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -070099 D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800100 return -1;
101 }
102 }
103
Yabin Cuiaed3c612015-09-22 15:52:57 -0700104 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800105 return 0;
106}
107
108static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100109write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800110{
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100111 char buff[8];
112 if (!name) {
113 snprintf(buff, sizeof buff, "fd=%d", fd);
114 name = buff;
115 }
Yabin Cuiaed3c612015-09-22 15:52:57 -0700116 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cui62641292015-07-30 19:58:10 -0700117 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
118 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800119 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700120 int r = adb_write(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800121 if(r > 0) {
122 len -= r;
123 p += r;
124 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700125 D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126 return -1;
127 }
128 }
129 return 0;
130}
131
132static void transport_socket_events(int fd, unsigned events, void *_t)
133{
Dan Albertbac34742015-02-25 17:51:28 -0800134 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700135 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800136 if(events & FDE_READ){
137 apacket *p = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100138 if(read_packet(fd, t->serial, &p)){
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700139 D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 } else {
141 handle_packet(p, (atransport *) _t);
142 }
143 }
144}
145
146void send_packet(apacket *p, atransport *t)
147{
148 unsigned char *x;
149 unsigned sum;
150 unsigned count;
151
152 p->msg.magic = p->msg.command ^ 0xffffffff;
153
154 count = p->msg.data_length;
155 x = (unsigned char *) p->data;
156 sum = 0;
157 while(count-- > 0){
158 sum += *x++;
159 }
160 p->msg.data_check = sum;
161
162 print_packet("send", p);
163
164 if (t == NULL) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700165 D("Transport is null");
JP Abgrall408fa572011-03-16 15:57:42 -0700166 // Zap errno because print_packet() and other stuff have errno effect.
167 errno = 0;
168 fatal_errno("Transport is null");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 }
170
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100171 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800172 fatal_errno("cannot enqueue packet on transport socket");
173 }
174}
175
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700176// The transport is opened by transport_register_func before
177// the read_transport and write_transport threads are started.
178//
179// The read_transport thread issues a SYNC(1, token) message to let
180// the write_transport thread know to start things up. In the event
181// of transport IO failure, the read_transport thread will post a
182// SYNC(0,0) message to ensure shutdown.
183//
184// The transport will not actually be closed until both threads exit, but the threads
185// will kick the transport on their way out to disconnect the underlying device.
186//
187// read_transport thread reads data from a transport (representing a usb/tcp connection),
188// and makes the main thread call handle_packet().
189static void *read_transport_thread(void *_t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190{
Dan Albertbac34742015-02-25 17:51:28 -0800191 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800192 apacket *p;
193
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700194 adb_thread_setname(android::base::StringPrintf("<-%s",
195 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700196 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100197 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 p = get_apacket();
199 p->msg.command = A_SYNC;
200 p->msg.arg0 = 1;
201 p->msg.arg1 = ++(t->sync_token);
202 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100203 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800204 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700205 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206 goto oops;
207 }
208
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700209 D("%s: data pump started", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 for(;;) {
211 p = get_apacket();
212
213 if(t->read_from_remote(p, t) == 0){
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700214 D("%s: received remote packet, sending to transport",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100215 t->serial);
216 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800217 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700218 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800219 goto oops;
220 }
221 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700222 D("%s: remote read failed for transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800223 put_apacket(p);
224 break;
225 }
226 }
227
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700228 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 p = get_apacket();
230 p->msg.command = A_SYNC;
231 p->msg.arg0 = 0;
232 p->msg.arg1 = 0;
233 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100234 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700236 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800237 }
238
239oops:
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700240 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 kick_transport(t);
242 transport_unref(t);
243 return 0;
244}
245
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700246// write_transport thread gets packets sent by the main thread (through send_packet()),
247// and writes to a transport (representing a usb/tcp connection).
248static void *write_transport_thread(void *_t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800249{
Dan Albertbac34742015-02-25 17:51:28 -0800250 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251 apacket *p;
252 int active = 0;
253
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700254 adb_thread_setname(android::base::StringPrintf("->%s",
255 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700256 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100257 t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258
259 for(;;){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100260 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700261 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100262 t->serial, t->fd );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263 break;
264 }
265 if(p->msg.command == A_SYNC){
266 if(p->msg.arg0 == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700267 D("%s: transport SYNC offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800268 put_apacket(p);
269 break;
270 } else {
271 if(p->msg.arg1 == t->sync_token) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700272 D("%s: transport SYNC online", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800273 active = 1;
274 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700275 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100276 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 }
278 }
279 } else {
280 if(active) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700281 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 t->write_to_remote(p, t);
283 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700284 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800285 }
286 }
287
288 put_apacket(p);
289 }
290
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700291 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 kick_transport(t);
293 transport_unref(t);
294 return 0;
295}
296
Yabin Cuif4b99282015-08-27 12:03:11 -0700297static void kick_transport_locked(atransport* t) {
298 CHECK(t != nullptr);
299 if (!t->kicked) {
300 t->kicked = true;
301 t->kick(t);
302 }
303}
304
305void kick_transport(atransport* t) {
306 adb_mutex_lock(&transport_lock);
307 kick_transport_locked(t);
308 adb_mutex_unlock(&transport_lock);
309}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800310
311static int transport_registration_send = -1;
312static int transport_registration_recv = -1;
313static fdevent transport_registration_fde;
314
315
316#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800317
318/* this adds support required by the 'track-devices' service.
319 * this is used to send the content of "list_transport" to any
320 * number of client connections that want it through a single
321 * live TCP connection
322 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800323struct device_tracker {
324 asocket socket;
325 int update_needed;
326 device_tracker* next;
327};
328
329/* linked list of all device trackers */
330static device_tracker* device_tracker_list;
331
332static void
333device_tracker_remove( device_tracker* tracker )
334{
335 device_tracker** pnode = &device_tracker_list;
336 device_tracker* node = *pnode;
337
338 adb_mutex_lock( &transport_lock );
339 while (node) {
340 if (node == tracker) {
341 *pnode = node->next;
342 break;
343 }
344 pnode = &node->next;
345 node = *pnode;
346 }
347 adb_mutex_unlock( &transport_lock );
348}
349
350static void
351device_tracker_close( asocket* socket )
352{
353 device_tracker* tracker = (device_tracker*) socket;
354 asocket* peer = socket->peer;
355
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700356 D( "device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800357 if (peer) {
358 peer->peer = NULL;
359 peer->close(peer);
360 }
361 device_tracker_remove(tracker);
362 free(tracker);
363}
364
365static int
366device_tracker_enqueue( asocket* socket, apacket* p )
367{
368 /* you can't read from a device tracker, close immediately */
369 put_apacket(p);
370 device_tracker_close(socket);
371 return -1;
372}
373
Elliott Hughese67f1f82015-04-30 17:32:03 -0700374static int device_tracker_send(device_tracker* tracker, const std::string& string) {
375 apacket* p = get_apacket();
376 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800377
Elliott Hughese67f1f82015-04-30 17:32:03 -0700378 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
379 memcpy(&p->data[4], string.data(), string.size());
380 p->len = 4 + string.size();
381 return peer->enqueue(peer, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800382}
383
Elliott Hughese67f1f82015-04-30 17:32:03 -0700384static void device_tracker_ready(asocket* socket) {
385 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800386
Elliott Hughese67f1f82015-04-30 17:32:03 -0700387 // We want to send the device list when the tracker connects
388 // for the first time, even if no update occurred.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800389 if (tracker->update_needed > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800390 tracker->update_needed = 0;
391
Elliott Hughese67f1f82015-04-30 17:32:03 -0700392 std::string transports = list_transports(false);
393 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800394 }
395}
396
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800397asocket*
398create_device_tracker(void)
399{
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700400 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
401 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800402
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700403 D( "device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800404
405 tracker->socket.enqueue = device_tracker_enqueue;
406 tracker->socket.ready = device_tracker_ready;
407 tracker->socket.close = device_tracker_close;
408 tracker->update_needed = 1;
409
410 tracker->next = device_tracker_list;
411 device_tracker_list = tracker;
412
413 return &tracker->socket;
414}
415
416
Elliott Hughese67f1f82015-04-30 17:32:03 -0700417// Call this function each time the transport list has changed.
418void update_transports() {
419 std::string transports = list_transports(false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800420
Elliott Hughese67f1f82015-04-30 17:32:03 -0700421 device_tracker* tracker = device_tracker_list;
422 while (tracker != nullptr) {
423 device_tracker* next = tracker->next;
424 // This may destroy the tracker if the connection is closed.
425 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800426 tracker = next;
427 }
428}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700429
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800430#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700431
432void update_transports() {
433 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436#endif // ADB_HOST
437
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438struct tmsg
439{
440 atransport *transport;
441 int action;
442};
443
444static int
445transport_read_action(int fd, struct tmsg* m)
446{
447 char *p = (char*)m;
448 int len = sizeof(*m);
449 int r;
450
451 while(len > 0) {
452 r = adb_read(fd, p, len);
453 if(r > 0) {
454 len -= r;
455 p += r;
456 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700457 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800458 return -1;
459 }
460 }
461 return 0;
462}
463
464static int
465transport_write_action(int fd, struct tmsg* m)
466{
467 char *p = (char*)m;
468 int len = sizeof(*m);
469 int r;
470
471 while(len > 0) {
472 r = adb_write(fd, p, len);
473 if(r > 0) {
474 len -= r;
475 p += r;
476 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700477 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800478 return -1;
479 }
480 }
481 return 0;
482}
483
484static void transport_registration_func(int _fd, unsigned ev, void *data)
485{
486 tmsg m;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800487 int s[2];
488 atransport *t;
489
490 if(!(ev & FDE_READ)) {
491 return;
492 }
493
494 if(transport_read_action(_fd, &m)) {
495 fatal_errno("cannot read transport registration socket");
496 }
497
498 t = m.transport;
499
Dan Albert1792c232015-05-18 13:06:53 -0700500 if (m.action == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700501 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800502
503 /* IMPORTANT: the remove closes one half of the
504 ** socket pair. The close closes the other half.
505 */
506 fdevent_remove(&(t->transport_fde));
507 adb_close(t->fd);
508
509 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700510 transport_list.remove(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800511 adb_mutex_unlock(&transport_lock);
512
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800513 if (t->product)
514 free(t->product);
515 if (t->serial)
516 free(t->serial);
Scott Andersone82c2db2012-05-25 14:10:02 -0700517 if (t->model)
518 free(t->model);
519 if (t->device)
520 free(t->device);
Scott Andersone109d262012-04-20 11:21:14 -0700521 if (t->devpath)
522 free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800523
Dan Albertc7915a32015-05-18 16:46:31 -0700524 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800525
526 update_transports();
527 return;
528 }
529
Mike Lockwood0927bf92009-08-08 12:37:44 -0400530 /* don't create transport threads for inaccessible devices */
Dan Albertdcd78a12015-05-18 16:43:57 -0700531 if (t->connection_state != kCsNoPerm) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800532 /* initial references are the two threads */
Mike Lockwood0927bf92009-08-08 12:37:44 -0400533 t->ref_count = 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800534
Dan Albertc7915a32015-05-18 16:46:31 -0700535 if (adb_socketpair(s)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400536 fatal_errno("cannot open transport socketpair");
537 }
538
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700539 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400540
541 t->transport_socket = s[0];
542 t->fd = s[1];
543
Mike Lockwood0927bf92009-08-08 12:37:44 -0400544 fdevent_install(&(t->transport_fde),
545 t->transport_socket,
546 transport_socket_events,
547 t);
548
549 fdevent_set(&(t->transport_fde), FDE_READ);
550
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700551 if (!adb_thread_create(write_transport_thread, t)) {
552 fatal_errno("cannot create write_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400553 }
554
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700555 if (!adb_thread_create(read_transport_thread, t)) {
556 fatal_errno("cannot create read_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400557 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800558 }
559
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800560 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700561 pending_list.remove(t);
562 transport_list.push_front(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800563 adb_mutex_unlock(&transport_lock);
564
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 update_transports();
566}
567
568void init_transport_registration(void)
569{
570 int s[2];
571
572 if(adb_socketpair(s)){
573 fatal_errno("cannot open transport registration socketpair");
574 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700575 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800576
577 transport_registration_send = s[0];
578 transport_registration_recv = s[1];
579
580 fdevent_install(&transport_registration_fde,
581 transport_registration_recv,
582 transport_registration_func,
583 0);
584
585 fdevent_set(&transport_registration_fde, FDE_READ);
586}
587
588/* the fdevent select pump is single threaded */
589static void register_transport(atransport *transport)
590{
591 tmsg m;
592 m.transport = transport;
593 m.action = 1;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700594 D("transport: %s registered", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800595 if(transport_write_action(transport_registration_send, &m)) {
596 fatal_errno("cannot write transport registration socket\n");
597 }
598}
599
600static void remove_transport(atransport *transport)
601{
602 tmsg m;
603 m.transport = transport;
604 m.action = 0;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700605 D("transport: %s removed", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800606 if(transport_write_action(transport_registration_send, &m)) {
607 fatal_errno("cannot write transport registration socket\n");
608 }
609}
610
611
Yabin Cuif4b99282015-08-27 12:03:11 -0700612static void transport_unref(atransport* t) {
613 CHECK(t != nullptr);
614 adb_mutex_lock(&transport_lock);
615 CHECK_GT(t->ref_count, 0u);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400616 t->ref_count--;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400617 if (t->ref_count == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700618 D("transport: %s unref (kicking and closing)", t->serial);
Yabin Cuif4b99282015-08-27 12:03:11 -0700619 kick_transport_locked(t);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400620 t->close(t);
621 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100622 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700623 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400624 }
Yabin Cuif4b99282015-08-27 12:03:11 -0700625 adb_mutex_unlock(&transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800626}
627
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700628static int qual_match(const char *to_test,
Elliott Hughes09a45a12015-04-03 16:12:15 -0700629 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700630{
631 if (!to_test || !*to_test)
632 /* Return true if both the qual and to_test are null strings. */
633 return !qual || !*qual;
634
635 if (!qual)
636 return 0;
637
638 if (prefix) {
639 while (*prefix) {
640 if (*prefix++ != *to_test++)
641 return 0;
642 }
643 }
644
645 while (*qual) {
646 char ch = *qual++;
Elliott Hughes09a45a12015-04-03 16:12:15 -0700647 if (sanitize_qual && !isalnum(ch))
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700648 ch = '_';
649 if (ch != *to_test++)
650 return 0;
651 }
652
653 /* Everything matched so far. Return true if *to_test is a NUL. */
654 return !*to_test;
655}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800656
Elliott Hughes8d28e192015-10-07 14:55:10 -0700657atransport* acquire_one_transport(TransportType type, const char* serial,
658 bool* is_ambiguous, std::string* error_out) {
659 atransport* result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800660
Elliott Hughes8d28e192015-10-07 14:55:10 -0700661 if (serial) {
662 *error_out = android::base::StringPrintf("device '%s' not found", serial);
663 } else if (type == kTransportLocal) {
664 *error_out = "no emulators found";
665 } else if (type == kTransportAny) {
666 *error_out = "no devices/emulators found";
667 } else {
668 *error_out = "no devices found";
669 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800670
671 adb_mutex_lock(&transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700672 for (const auto& t : transport_list) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700673 if (t->connection_state == kCsNoPerm) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700674 *error_out = "insufficient permissions for device";
Mike Lockwood37d31112009-08-08 13:53:16 -0400675 continue;
676 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400677
Elliott Hughes8d28e192015-10-07 14:55:10 -0700678 // Check for matching serial number.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800679 if (serial) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700680 if ((t->serial && !strcmp(serial, t->serial)) ||
681 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughes09a45a12015-04-03 16:12:15 -0700682 qual_match(serial, "product:", t->product, false) ||
683 qual_match(serial, "model:", t->model, true) ||
684 qual_match(serial, "device:", t->device, false)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700685 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700686 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700687 if (is_ambiguous) *is_ambiguous = true;
688 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700689 break;
690 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800691 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700692 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700694 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800695 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700696 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700697 if (is_ambiguous) *is_ambiguous = true;
698 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800699 break;
700 }
701 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700702 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700704 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700705 if (is_ambiguous) *is_ambiguous = true;
706 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800707 break;
708 }
709 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700710 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800711 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700712 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700713 if (is_ambiguous) *is_ambiguous = true;
714 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800715 break;
716 }
717 result = t;
718 }
719 }
720 }
721 adb_mutex_unlock(&transport_lock);
722
Elliott Hughes8d28e192015-10-07 14:55:10 -0700723 // Don't return unauthorized devices; the caller can't do anything with them.
724 if (result && result->connection_state == kCsUnauthorized) {
725 *error_out = "device unauthorized.\n";
726 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
727 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
728 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
729 *error_out += "\n";
730 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
731 *error_out += "Otherwise check for a confirmation dialog on your device.";
732 result = nullptr;
733 }
Benoit Goby77e8e582013-01-15 12:36:47 -0800734
Elliott Hughes8d28e192015-10-07 14:55:10 -0700735 // Don't return offline devices; the caller can't do anything with them.
736 if (result && result->connection_state == kCsOffline) {
737 *error_out = "device offline";
738 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800739 }
740
741 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700742 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800743 }
744
745 return result;
746}
747
Elliott Hughese67f1f82015-04-30 17:32:03 -0700748const char* atransport::connection_state_name() const {
749 switch (connection_state) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700750 case kCsOffline: return "offline";
751 case kCsBootloader: return "bootloader";
752 case kCsDevice: return "device";
753 case kCsHost: return "host";
754 case kCsRecovery: return "recovery";
755 case kCsNoPerm: return "no permissions";
756 case kCsSideload: return "sideload";
757 case kCsUnauthorized: return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800758 default: return "unknown";
759 }
760}
761
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100762void atransport::update_version(int version, size_t payload) {
763 protocol_version = std::min(version, A_VERSION);
764 max_payload = std::min(payload, MAX_PAYLOAD);
765}
766
767int atransport::get_protocol_version() const {
768 return protocol_version;
769}
770
771size_t atransport::get_max_payload() const {
772 return max_payload;
773}
774
David Pursell4e2fd362015-09-22 10:43:08 -0700775namespace {
David Pursell0955c662015-08-31 10:42:13 -0700776
David Pursell4e2fd362015-09-22 10:43:08 -0700777constexpr char kFeatureStringDelimiter = ',';
778
779} // namespace
Dan Albert1792c232015-05-18 13:06:53 -0700780
781const FeatureSet& supported_features() {
David Pursell4e2fd362015-09-22 10:43:08 -0700782 // Local static allocation to avoid global non-POD variables.
783 static const FeatureSet* features = new FeatureSet{
Todd Kennedy3e3b4ec2015-11-09 15:36:35 +0000784 kFeatureShell2
David Pursellbbe3d212015-09-25 08:37:13 -0700785 // Increment ADB_SERVER_VERSION whenever the feature list changes to
786 // make sure that the adb client and server features stay in sync
787 // (http://b/24370690).
David Pursell4e2fd362015-09-22 10:43:08 -0700788 };
789
790 return *features;
791}
792
793std::string FeatureSetToString(const FeatureSet& features) {
794 return android::base::Join(features, kFeatureStringDelimiter);
795}
796
797FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -0700798 if (features_string.empty()) {
799 return FeatureSet();
800 }
801
David Pursell4e2fd362015-09-22 10:43:08 -0700802 auto names = android::base::Split(features_string,
803 {kFeatureStringDelimiter});
804 return FeatureSet(names.begin(), names.end());
Dan Albert1792c232015-05-18 13:06:53 -0700805}
806
David Pursell70ef7b42015-09-30 13:35:42 -0700807bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
808 return feature_set.count(feature) > 0 &&
809 supported_features().count(feature) > 0;
810}
811
Dan Albert1792c232015-05-18 13:06:53 -0700812bool atransport::has_feature(const std::string& feature) const {
813 return features_.count(feature) > 0;
814}
815
David Pursell4e2fd362015-09-22 10:43:08 -0700816void atransport::SetFeatures(const std::string& features_string) {
817 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -0700818}
819
Yabin Cuib3298242015-08-28 15:09:44 -0700820void atransport::AddDisconnect(adisconnect* disconnect) {
821 disconnects_.push_back(disconnect);
822}
823
824void atransport::RemoveDisconnect(adisconnect* disconnect) {
825 disconnects_.remove(disconnect);
826}
827
828void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -0700829 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -0700830 disconnect->func(disconnect->opaque, this);
831 }
832 disconnects_.clear();
833}
834
Elliott Hughese67f1f82015-04-30 17:32:03 -0700835#if ADB_HOST
836
Dan Albertd99d9022015-05-06 16:48:52 -0700837static void append_transport_info(std::string* result, const char* key,
838 const char* value, bool sanitize) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700839 if (value == nullptr || *value == '\0') {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700840 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700841 }
842
Elliott Hughese67f1f82015-04-30 17:32:03 -0700843 *result += ' ';
844 *result += key;
845
846 for (const char* p = value; *p; ++p) {
847 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
848 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700849}
850
Dan Albertc7915a32015-05-18 16:46:31 -0700851static void append_transport(const atransport* t, std::string* result,
852 bool long_listing) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700853 const char* serial = t->serial;
Elliott Hughese67f1f82015-04-30 17:32:03 -0700854 if (!serial || !serial[0]) {
Dan Albertd99d9022015-05-06 16:48:52 -0700855 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -0700856 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700857
858 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700859 *result += serial;
860 *result += '\t';
861 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700862 } else {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700863 android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700864
Elliott Hughese67f1f82015-04-30 17:32:03 -0700865 append_transport_info(result, "", t->devpath, false);
866 append_transport_info(result, "product:", t->product, false);
867 append_transport_info(result, "model:", t->model, true);
868 append_transport_info(result, "device:", t->device, false);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700869 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700870 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700871}
872
Elliott Hughese67f1f82015-04-30 17:32:03 -0700873std::string list_transports(bool long_listing) {
874 std::string result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800875 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700876 for (const auto& t : transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700877 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800878 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800879 adb_mutex_unlock(&transport_lock);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700880 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800881}
882
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800883/* hack for osx */
Dan Albertc7915a32015-05-18 16:46:31 -0700884void close_usb_devices() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800885 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700886 for (const auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700887 if (!t->kicked) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888 t->kicked = 1;
889 t->kick(t);
890 }
891 }
892 adb_mutex_unlock(&transport_lock);
893}
894#endif // ADB_HOST
895
Dan Albertc7915a32015-05-18 16:46:31 -0700896int register_socket_transport(int s, const char *serial, int port, int local) {
897 atransport* t = new atransport();
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100898
899 if (!serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700900 char buf[32];
901 snprintf(buf, sizeof(buf), "T-%p", t);
902 serial = buf;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100903 }
Dan Albertc7915a32015-05-18 16:46:31 -0700904
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700905 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700906 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700907 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700908 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800909 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700910
911 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700912 for (const auto& transport : pending_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700913 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700914 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700915 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700916 return -1;
917 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800918 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700919
Elliott Hughes65fe2512015-10-07 15:59:35 -0700920 for (const auto& transport : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700921 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700922 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700923 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700924 return -1;
925 }
926 }
927
Dan Albertc7915a32015-05-18 16:46:31 -0700928 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700929 t->serial = strdup(serial);
930 adb_mutex_unlock(&transport_lock);
931
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800932 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700933 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800934}
935
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400936#if ADB_HOST
Dan Albertc7915a32015-05-18 16:46:31 -0700937atransport *find_transport(const char *serial) {
938 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400939
940 adb_mutex_lock(&transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700941 for (auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700942 if (t->serial && strcmp(serial, t->serial) == 0) {
943 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400944 break;
945 }
Dan Albertc7915a32015-05-18 16:46:31 -0700946 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400947 adb_mutex_unlock(&transport_lock);
948
Dan Albertc7915a32015-05-18 16:46:31 -0700949 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400950}
951
Yabin Cuif4b99282015-08-27 12:03:11 -0700952void kick_all_tcp_devices() {
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400953 adb_mutex_lock(&transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700954 for (auto& t : transport_list) {
955 // TCP/IP devices have adb_port == 0.
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400956 if (t->type == kTransportLocal && t->adb_port == 0) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700957 // Kicking breaks the read_transport thread of this transport out of any read, then
958 // the read_transport thread will notify the main thread to make this transport
959 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -0700960 // Finally, this transport will be closed and freed in the main thread.
961 kick_transport_locked(t);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400962 }
Dan Albertc7915a32015-05-18 16:46:31 -0700963 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400964 adb_mutex_unlock(&transport_lock);
965}
966
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400967#endif
968
Dan Albertc7915a32015-05-18 16:46:31 -0700969void register_usb_transport(usb_handle* usb, const char* serial,
970 const char* devpath, unsigned writeable) {
971 atransport* t = new atransport();
972
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700973 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800974 serial ? serial : "");
Dan Albertdcd78a12015-05-18 16:43:57 -0700975 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800976 if(serial) {
977 t->serial = strdup(serial);
978 }
Dan Albertc7915a32015-05-18 16:46:31 -0700979
980 if (devpath) {
Scott Andersone109d262012-04-20 11:21:14 -0700981 t->devpath = strdup(devpath);
982 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700983
984 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700985 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700986 adb_mutex_unlock(&transport_lock);
987
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800988 register_transport(t);
989}
990
Dan Albertdcd78a12015-05-18 16:43:57 -0700991// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertc7915a32015-05-18 16:46:31 -0700992void unregister_usb_transport(usb_handle *usb) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400993 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700994 transport_list.remove_if([usb](atransport* t) {
995 return t->usb == usb && t->connection_state == kCsNoPerm;
996 });
Mike Lockwood0927bf92009-08-08 12:37:44 -0400997 adb_mutex_unlock(&transport_lock);
998}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800999
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001000int check_header(apacket *p, atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001001{
1002 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001003 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001004 return -1;
1005 }
1006
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001007 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001008 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1009 << t->get_max_payload();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001010 return -1;
1011 }
1012
1013 return 0;
1014}
1015
1016int check_data(apacket *p)
1017{
1018 unsigned count, sum;
1019 unsigned char *x;
1020
1021 count = p->msg.data_length;
1022 x = p->data;
1023 sum = 0;
1024 while(count-- > 0) {
1025 sum += *x++;
1026 }
1027
1028 if(sum != p->msg.data_check) {
1029 return -1;
1030 } else {
1031 return 0;
1032 }
1033}