blob: 6020ad5b12f366f4b3f5cfcfde50ca4bf275828a [file] [log] [blame]
The Android Open Source Project9ca14dc2009-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 Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albertb302d122015-02-24 15:51:19 -080018
Dan Albertdb6fe642015-03-19 15:21:08 -070019#include "sysdeps.h"
Dan Albertb302d122015-02-24 15:51:19 -080020#include "transport.h"
21
Dan Albert4895c522015-02-20 17:24:58 -080022#include <ctype.h>
Dan Albertb302d122015-02-24 15:51:19 -080023#include <errno.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080024#include <stdio.h>
25#include <stdlib.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include <string.h>
Dan Albertb302d122015-02-24 15:51:19 -080027#include <unistd.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080028
Spencer Low28bc2cb2015-11-07 18:51:54 -080029#include <algorithm>
Dan Albertecce5032015-05-18 16:46:31 -070030#include <list>
31
Elliott Hughesf55ead92015-12-04 22:00:26 -080032#include <android-base/logging.h>
33#include <android-base/stringprintf.h>
34#include <android-base/strings.h>
Elliott Hughes88b4c852015-04-30 17:32:03 -070035
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080036#include "adb.h"
Elliott Hughes88b4c852015-04-30 17:32:03 -070037#include "adb_utils.h"
Elliott Hughes70097492015-12-11 19:07:01 -080038#include "diagnose_usb.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080039
40static void transport_unref(atransport *t);
41
Josh Gaoe3a87d02015-11-11 17:56:12 -080042static auto& transport_list = *new std::list<atransport*>();
43static auto& pending_list = *new std::list<atransport*>();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070044
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080045ADB_MUTEX_DEFINE( transport_lock );
46
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -080047const char* const kFeatureShell2 = "shell_v2";
48const char* const kFeatureCmd = "cmd";
49
Yabin Cui19bec5b2015-09-22 15:52:57 -070050static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +010051 unsigned command = p->msg.command;
52 int len = p->msg.data_length;
53 char cmd[9];
54 char arg0[12], arg1[12];
55 int n;
56
57 for (n = 0; n < 4; n++) {
58 int b = (command >> (n*8)) & 255;
59 if (b < 32 || b >= 127)
60 break;
61 cmd[n] = (char)b;
62 }
63 if (n == 4) {
64 cmd[4] = 0;
65 } else {
66 /* There is some non-ASCII name in the command, so dump
67 * the hexadecimal value instead */
68 snprintf(cmd, sizeof cmd, "%08x", command);
69 }
70
71 if (p->msg.arg0 < 256U)
72 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
73 else
74 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
75
76 if (p->msg.arg1 < 256U)
77 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
78 else
79 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
80
Yabin Cui19bec5b2015-09-22 15:52:57 -070081 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
82 name, func, cmd, arg0, arg1, len);
83 result += dump_hex(p->data, len);
84 return result;
David 'Digit' Turner58f59682011-01-06 14:11:07 +010085}
David 'Digit' Turner58f59682011-01-06 14:11:07 +010086
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080087static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +010088read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080089{
Yabin Cuia96dabf2015-07-30 19:58:10 -070090 char buff[8];
David 'Digit' Turner58f59682011-01-06 14:11:07 +010091 if (!name) {
92 snprintf(buff, sizeof buff, "fd=%d", fd);
93 name = buff;
94 }
Yabin Cuia96dabf2015-07-30 19:58:10 -070095 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
96 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080097 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -070098 int r = adb_read(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080099 if(r > 0) {
100 len -= r;
Yabin Cuia96dabf2015-07-30 19:58:10 -0700101 p += r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800102 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700103 D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800104 return -1;
105 }
106 }
107
Yabin Cui19bec5b2015-09-22 15:52:57 -0700108 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800109 return 0;
110}
111
112static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100113write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800114{
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100115 char buff[8];
116 if (!name) {
117 snprintf(buff, sizeof buff, "fd=%d", fd);
118 name = buff;
119 }
Yabin Cui19bec5b2015-09-22 15:52:57 -0700120 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cuia96dabf2015-07-30 19:58:10 -0700121 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
122 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800123 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -0700124 int r = adb_write(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800125 if(r > 0) {
126 len -= r;
127 p += r;
128 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700129 D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800130 return -1;
131 }
132 }
133 return 0;
134}
135
136static void transport_socket_events(int fd, unsigned events, void *_t)
137{
Dan Albertf30d73c2015-02-25 17:51:28 -0800138 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui815ad882015-09-02 17:44:28 -0700139 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800140 if(events & FDE_READ){
141 apacket *p = 0;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100142 if(read_packet(fd, t->serial, &p)){
Yabin Cui815ad882015-09-02 17:44:28 -0700143 D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800144 } else {
145 handle_packet(p, (atransport *) _t);
146 }
147 }
148}
149
150void send_packet(apacket *p, atransport *t)
151{
152 unsigned char *x;
153 unsigned sum;
154 unsigned count;
155
156 p->msg.magic = p->msg.command ^ 0xffffffff;
157
158 count = p->msg.data_length;
159 x = (unsigned char *) p->data;
160 sum = 0;
161 while(count-- > 0){
162 sum += *x++;
163 }
164 p->msg.data_check = sum;
165
166 print_packet("send", p);
167
168 if (t == NULL) {
Yabin Cui815ad882015-09-02 17:44:28 -0700169 D("Transport is null");
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700170 // Zap errno because print_packet() and other stuff have errno effect.
171 errno = 0;
172 fatal_errno("Transport is null");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800173 }
174
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100175 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800176 fatal_errno("cannot enqueue packet on transport socket");
177 }
178}
179
Yabin Cui4e222292015-08-31 11:50:24 -0700180// The transport is opened by transport_register_func before
181// the read_transport and write_transport threads are started.
182//
183// The read_transport thread issues a SYNC(1, token) message to let
184// the write_transport thread know to start things up. In the event
185// of transport IO failure, the read_transport thread will post a
186// SYNC(0,0) message to ensure shutdown.
187//
188// The transport will not actually be closed until both threads exit, but the threads
189// will kick the transport on their way out to disconnect the underlying device.
190//
191// read_transport thread reads data from a transport (representing a usb/tcp connection),
192// and makes the main thread call handle_packet().
193static void *read_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800194{
Dan Albertf30d73c2015-02-25 17:51:28 -0800195 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800196 apacket *p;
197
Yabin Cui4e222292015-08-31 11:50:24 -0700198 adb_thread_setname(android::base::StringPrintf("<-%s",
199 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700200 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100201 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800202 p = get_apacket();
203 p->msg.command = A_SYNC;
204 p->msg.arg0 = 1;
205 p->msg.arg1 = ++(t->sync_token);
206 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100207 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800208 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700209 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800210 goto oops;
211 }
212
Yabin Cui815ad882015-09-02 17:44:28 -0700213 D("%s: data pump started", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800214 for(;;) {
215 p = get_apacket();
216
217 if(t->read_from_remote(p, t) == 0){
Yabin Cui815ad882015-09-02 17:44:28 -0700218 D("%s: received remote packet, sending to transport",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100219 t->serial);
220 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800221 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700222 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800223 goto oops;
224 }
225 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700226 D("%s: remote read failed for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800227 put_apacket(p);
228 break;
229 }
230 }
231
Yabin Cui815ad882015-09-02 17:44:28 -0700232 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800233 p = get_apacket();
234 p->msg.command = A_SYNC;
235 p->msg.arg0 = 0;
236 p->msg.arg1 = 0;
237 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100238 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800239 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700240 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800241 }
242
243oops:
Yabin Cui815ad882015-09-02 17:44:28 -0700244 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800245 kick_transport(t);
246 transport_unref(t);
247 return 0;
248}
249
Yabin Cui4e222292015-08-31 11:50:24 -0700250// write_transport thread gets packets sent by the main thread (through send_packet()),
251// and writes to a transport (representing a usb/tcp connection).
252static void *write_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800253{
Dan Albertf30d73c2015-02-25 17:51:28 -0800254 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800255 apacket *p;
256 int active = 0;
257
Yabin Cui4e222292015-08-31 11:50:24 -0700258 adb_thread_setname(android::base::StringPrintf("->%s",
259 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700260 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100261 t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800262
263 for(;;){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100264 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700265 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100266 t->serial, t->fd );
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800267 break;
268 }
269 if(p->msg.command == A_SYNC){
270 if(p->msg.arg0 == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700271 D("%s: transport SYNC offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800272 put_apacket(p);
273 break;
274 } else {
275 if(p->msg.arg1 == t->sync_token) {
Yabin Cui815ad882015-09-02 17:44:28 -0700276 D("%s: transport SYNC online", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800277 active = 1;
278 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700279 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100280 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800281 }
282 }
283 } else {
284 if(active) {
Yabin Cui815ad882015-09-02 17:44:28 -0700285 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800286 t->write_to_remote(p, t);
287 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700288 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800289 }
290 }
291
292 put_apacket(p);
293 }
294
Yabin Cui815ad882015-09-02 17:44:28 -0700295 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800296 kick_transport(t);
297 transport_unref(t);
298 return 0;
299}
300
Yabin Cui4d64fd82015-08-27 12:03:11 -0700301static void kick_transport_locked(atransport* t) {
302 CHECK(t != nullptr);
303 if (!t->kicked) {
304 t->kicked = true;
305 t->kick(t);
306 }
307}
308
309void kick_transport(atransport* t) {
310 adb_mutex_lock(&transport_lock);
311 kick_transport_locked(t);
312 adb_mutex_unlock(&transport_lock);
313}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800314
315static int transport_registration_send = -1;
316static int transport_registration_recv = -1;
317static fdevent transport_registration_fde;
318
319
320#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800321
322/* this adds support required by the 'track-devices' service.
323 * this is used to send the content of "list_transport" to any
324 * number of client connections that want it through a single
325 * live TCP connection
326 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800327struct device_tracker {
328 asocket socket;
329 int update_needed;
330 device_tracker* next;
331};
332
333/* linked list of all device trackers */
334static device_tracker* device_tracker_list;
335
336static void
337device_tracker_remove( device_tracker* tracker )
338{
339 device_tracker** pnode = &device_tracker_list;
340 device_tracker* node = *pnode;
341
342 adb_mutex_lock( &transport_lock );
343 while (node) {
344 if (node == tracker) {
345 *pnode = node->next;
346 break;
347 }
348 pnode = &node->next;
349 node = *pnode;
350 }
351 adb_mutex_unlock( &transport_lock );
352}
353
354static void
355device_tracker_close( asocket* socket )
356{
357 device_tracker* tracker = (device_tracker*) socket;
358 asocket* peer = socket->peer;
359
Yabin Cui815ad882015-09-02 17:44:28 -0700360 D( "device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800361 if (peer) {
362 peer->peer = NULL;
363 peer->close(peer);
364 }
365 device_tracker_remove(tracker);
366 free(tracker);
367}
368
369static int
370device_tracker_enqueue( asocket* socket, apacket* p )
371{
372 /* you can't read from a device tracker, close immediately */
373 put_apacket(p);
374 device_tracker_close(socket);
375 return -1;
376}
377
Elliott Hughes88b4c852015-04-30 17:32:03 -0700378static int device_tracker_send(device_tracker* tracker, const std::string& string) {
379 apacket* p = get_apacket();
380 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800381
Elliott Hughes88b4c852015-04-30 17:32:03 -0700382 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
383 memcpy(&p->data[4], string.data(), string.size());
384 p->len = 4 + string.size();
385 return peer->enqueue(peer, p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800386}
387
Elliott Hughes88b4c852015-04-30 17:32:03 -0700388static void device_tracker_ready(asocket* socket) {
389 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800390
Elliott Hughes88b4c852015-04-30 17:32:03 -0700391 // We want to send the device list when the tracker connects
392 // for the first time, even if no update occurred.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800393 if (tracker->update_needed > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800394 tracker->update_needed = 0;
395
Elliott Hughes88b4c852015-04-30 17:32:03 -0700396 std::string transports = list_transports(false);
397 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800398 }
399}
400
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800401asocket*
402create_device_tracker(void)
403{
Elliott Hughesd0269c92015-04-21 19:39:52 -0700404 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
405 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800406
Yabin Cui815ad882015-09-02 17:44:28 -0700407 D( "device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800408
409 tracker->socket.enqueue = device_tracker_enqueue;
410 tracker->socket.ready = device_tracker_ready;
411 tracker->socket.close = device_tracker_close;
412 tracker->update_needed = 1;
413
414 tracker->next = device_tracker_list;
415 device_tracker_list = tracker;
416
417 return &tracker->socket;
418}
419
420
Elliott Hughes88b4c852015-04-30 17:32:03 -0700421// Call this function each time the transport list has changed.
422void update_transports() {
423 std::string transports = list_transports(false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800424
Elliott Hughes88b4c852015-04-30 17:32:03 -0700425 device_tracker* tracker = device_tracker_list;
426 while (tracker != nullptr) {
427 device_tracker* next = tracker->next;
428 // This may destroy the tracker if the connection is closed.
429 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800430 tracker = next;
431 }
432}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700433
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800434#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700435
436void update_transports() {
437 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800438}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700439
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800440#endif // ADB_HOST
441
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800442struct tmsg
443{
444 atransport *transport;
445 int action;
446};
447
448static int
449transport_read_action(int fd, struct tmsg* m)
450{
451 char *p = (char*)m;
452 int len = sizeof(*m);
453 int r;
454
455 while(len > 0) {
456 r = adb_read(fd, p, len);
457 if(r > 0) {
458 len -= r;
459 p += r;
460 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700461 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800462 return -1;
463 }
464 }
465 return 0;
466}
467
468static int
469transport_write_action(int fd, struct tmsg* m)
470{
471 char *p = (char*)m;
472 int len = sizeof(*m);
473 int r;
474
475 while(len > 0) {
476 r = adb_write(fd, p, len);
477 if(r > 0) {
478 len -= r;
479 p += r;
480 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700481 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800482 return -1;
483 }
484 }
485 return 0;
486}
487
488static void transport_registration_func(int _fd, unsigned ev, void *data)
489{
490 tmsg m;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800491 int s[2];
492 atransport *t;
493
494 if(!(ev & FDE_READ)) {
495 return;
496 }
497
498 if(transport_read_action(_fd, &m)) {
499 fatal_errno("cannot read transport registration socket");
500 }
501
502 t = m.transport;
503
Dan Albertbe8e54b2015-05-18 13:06:53 -0700504 if (m.action == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700505 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800506
507 /* IMPORTANT: the remove closes one half of the
508 ** socket pair. The close closes the other half.
509 */
510 fdevent_remove(&(t->transport_fde));
511 adb_close(t->fd);
512
513 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700514 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800515 adb_mutex_unlock(&transport_lock);
516
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800517 if (t->product)
518 free(t->product);
519 if (t->serial)
520 free(t->serial);
Scott Andersonfa020922012-05-25 14:10:02 -0700521 if (t->model)
522 free(t->model);
523 if (t->device)
524 free(t->device);
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700525 if (t->devpath)
526 free(t->devpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800527
Dan Albertecce5032015-05-18 16:46:31 -0700528 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800529
530 update_transports();
531 return;
532 }
533
Mike Lockwoode45583f2009-08-08 12:37:44 -0400534 /* don't create transport threads for inaccessible devices */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700535 if (t->connection_state != kCsNoPerm) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800536 /* initial references are the two threads */
Mike Lockwoode45583f2009-08-08 12:37:44 -0400537 t->ref_count = 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800538
Dan Albertecce5032015-05-18 16:46:31 -0700539 if (adb_socketpair(s)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400540 fatal_errno("cannot open transport socketpair");
541 }
542
Yabin Cui815ad882015-09-02 17:44:28 -0700543 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwoode45583f2009-08-08 12:37:44 -0400544
545 t->transport_socket = s[0];
546 t->fd = s[1];
547
Mike Lockwoode45583f2009-08-08 12:37:44 -0400548 fdevent_install(&(t->transport_fde),
549 t->transport_socket,
550 transport_socket_events,
551 t);
552
553 fdevent_set(&(t->transport_fde), FDE_READ);
554
Yabin Cui4e222292015-08-31 11:50:24 -0700555 if (!adb_thread_create(write_transport_thread, t)) {
556 fatal_errno("cannot create write_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400557 }
558
Yabin Cui4e222292015-08-31 11:50:24 -0700559 if (!adb_thread_create(read_transport_thread, t)) {
560 fatal_errno("cannot create read_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400561 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800562 }
563
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800564 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700565 pending_list.remove(t);
566 transport_list.push_front(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800567 adb_mutex_unlock(&transport_lock);
568
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800569 update_transports();
570}
571
572void init_transport_registration(void)
573{
574 int s[2];
575
576 if(adb_socketpair(s)){
577 fatal_errno("cannot open transport registration socketpair");
578 }
Yabin Cui815ad882015-09-02 17:44:28 -0700579 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800580
581 transport_registration_send = s[0];
582 transport_registration_recv = s[1];
583
584 fdevent_install(&transport_registration_fde,
585 transport_registration_recv,
586 transport_registration_func,
587 0);
588
589 fdevent_set(&transport_registration_fde, FDE_READ);
590}
591
592/* the fdevent select pump is single threaded */
593static void register_transport(atransport *transport)
594{
595 tmsg m;
596 m.transport = transport;
597 m.action = 1;
Yabin Cui815ad882015-09-02 17:44:28 -0700598 D("transport: %s registered", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800599 if(transport_write_action(transport_registration_send, &m)) {
600 fatal_errno("cannot write transport registration socket\n");
601 }
602}
603
604static void remove_transport(atransport *transport)
605{
606 tmsg m;
607 m.transport = transport;
608 m.action = 0;
Yabin Cui815ad882015-09-02 17:44:28 -0700609 D("transport: %s removed", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800610 if(transport_write_action(transport_registration_send, &m)) {
611 fatal_errno("cannot write transport registration socket\n");
612 }
613}
614
615
Yabin Cui4d64fd82015-08-27 12:03:11 -0700616static void transport_unref(atransport* t) {
617 CHECK(t != nullptr);
618 adb_mutex_lock(&transport_lock);
619 CHECK_GT(t->ref_count, 0u);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400620 t->ref_count--;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400621 if (t->ref_count == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700622 D("transport: %s unref (kicking and closing)", t->serial);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700623 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400624 t->close(t);
625 remove_transport(t);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100626 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700627 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400628 }
Yabin Cui4d64fd82015-08-27 12:03:11 -0700629 adb_mutex_unlock(&transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800630}
631
Scott Anderson27042382012-05-30 18:11:27 -0700632static int qual_match(const char *to_test,
Elliott Hughesabfa7202015-04-03 16:12:15 -0700633 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson27042382012-05-30 18:11:27 -0700634{
635 if (!to_test || !*to_test)
636 /* Return true if both the qual and to_test are null strings. */
637 return !qual || !*qual;
638
639 if (!qual)
640 return 0;
641
642 if (prefix) {
643 while (*prefix) {
644 if (*prefix++ != *to_test++)
645 return 0;
646 }
647 }
648
649 while (*qual) {
650 char ch = *qual++;
Elliott Hughesabfa7202015-04-03 16:12:15 -0700651 if (sanitize_qual && !isalnum(ch))
Scott Anderson27042382012-05-30 18:11:27 -0700652 ch = '_';
653 if (ch != *to_test++)
654 return 0;
655 }
656
657 /* Everything matched so far. Return true if *to_test is a NUL. */
658 return !*to_test;
659}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800660
Elliott Hughes67943d12015-10-07 14:55:10 -0700661atransport* acquire_one_transport(TransportType type, const char* serial,
662 bool* is_ambiguous, std::string* error_out) {
663 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800664
Elliott Hughes67943d12015-10-07 14:55:10 -0700665 if (serial) {
666 *error_out = android::base::StringPrintf("device '%s' not found", serial);
667 } else if (type == kTransportLocal) {
668 *error_out = "no emulators found";
669 } else if (type == kTransportAny) {
670 *error_out = "no devices/emulators found";
671 } else {
672 *error_out = "no devices found";
673 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800674
675 adb_mutex_lock(&transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -0700676 for (const auto& t : transport_list) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700677 if (t->connection_state == kCsNoPerm) {
Elliott Hughes70097492015-12-11 19:07:01 -0800678#if ADB_HOST
David Pursell6e5c7eb2015-12-02 15:14:31 -0800679 *error_out = UsbNoPermissionsLongHelpText();
Elliott Hughes70097492015-12-11 19:07:01 -0800680#endif
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400681 continue;
682 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400683
Elliott Hughes67943d12015-10-07 14:55:10 -0700684 // Check for matching serial number.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800685 if (serial) {
Scott Anderson27042382012-05-30 18:11:27 -0700686 if ((t->serial && !strcmp(serial, t->serial)) ||
687 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughesabfa7202015-04-03 16:12:15 -0700688 qual_match(serial, "product:", t->product, false) ||
689 qual_match(serial, "model:", t->model, true) ||
690 qual_match(serial, "device:", t->device, false)) {
Scott Anderson27042382012-05-30 18:11:27 -0700691 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700692 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700693 if (is_ambiguous) *is_ambiguous = true;
694 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -0700695 break;
696 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800697 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700698 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800699 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700700 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800701 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700702 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700703 if (is_ambiguous) *is_ambiguous = true;
704 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800705 break;
706 }
707 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700708 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800709 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700710 *error_out = "more than one emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700711 if (is_ambiguous) *is_ambiguous = true;
712 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800713 break;
714 }
715 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700716 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800717 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700718 *error_out = "more than one device/emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700719 if (is_ambiguous) *is_ambiguous = true;
720 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800721 break;
722 }
723 result = t;
724 }
725 }
726 }
727 adb_mutex_unlock(&transport_lock);
728
Elliott Hughes67943d12015-10-07 14:55:10 -0700729 // Don't return unauthorized devices; the caller can't do anything with them.
730 if (result && result->connection_state == kCsUnauthorized) {
731 *error_out = "device unauthorized.\n";
732 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
733 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
734 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
735 *error_out += "\n";
736 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
737 *error_out += "Otherwise check for a confirmation dialog on your device.";
738 result = nullptr;
739 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700740
Elliott Hughes67943d12015-10-07 14:55:10 -0700741 // Don't return offline devices; the caller can't do anything with them.
742 if (result && result->connection_state == kCsOffline) {
743 *error_out = "device offline";
744 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800745 }
746
747 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700748 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800749 }
750
751 return result;
752}
753
David Pursell6e5c7eb2015-12-02 15:14:31 -0800754const std::string atransport::connection_state_name() const {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700755 switch (connection_state) {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800756 case kCsOffline: return "offline";
757 case kCsBootloader: return "bootloader";
758 case kCsDevice: return "device";
759 case kCsHost: return "host";
760 case kCsRecovery: return "recovery";
Elliott Hughes70097492015-12-11 19:07:01 -0800761 case kCsNoPerm: return UsbNoPermissionsShortHelpText();
David Pursell6e5c7eb2015-12-02 15:14:31 -0800762 case kCsSideload: return "sideload";
763 case kCsUnauthorized: return "unauthorized";
764 default: return "unknown";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800765 }
766}
767
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100768void atransport::update_version(int version, size_t payload) {
769 protocol_version = std::min(version, A_VERSION);
770 max_payload = std::min(payload, MAX_PAYLOAD);
771}
772
773int atransport::get_protocol_version() const {
774 return protocol_version;
775}
776
777size_t atransport::get_max_payload() const {
778 return max_payload;
779}
780
David Pursella07dbad2015-09-22 10:43:08 -0700781namespace {
David Pursell8da19a42015-08-31 10:42:13 -0700782
David Pursella07dbad2015-09-22 10:43:08 -0700783constexpr char kFeatureStringDelimiter = ',';
784
785} // namespace
Dan Albertbe8e54b2015-05-18 13:06:53 -0700786
787const FeatureSet& supported_features() {
David Pursella07dbad2015-09-22 10:43:08 -0700788 // Local static allocation to avoid global non-POD variables.
789 static const FeatureSet* features = new FeatureSet{
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -0800790 kFeatureShell2,
Elliott Hughesd5eeac92015-11-06 18:05:16 -0800791 // Internal master has 'cmd'. AOSP master doesn't.
792 // kFeatureCmd
793
David Pursell6d5fad32015-09-25 08:37:13 -0700794 // Increment ADB_SERVER_VERSION whenever the feature list changes to
795 // make sure that the adb client and server features stay in sync
796 // (http://b/24370690).
David Pursella07dbad2015-09-22 10:43:08 -0700797 };
798
799 return *features;
800}
801
802std::string FeatureSetToString(const FeatureSet& features) {
803 return android::base::Join(features, kFeatureStringDelimiter);
804}
805
806FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -0700807 if (features_string.empty()) {
808 return FeatureSet();
809 }
810
David Pursella07dbad2015-09-22 10:43:08 -0700811 auto names = android::base::Split(features_string,
812 {kFeatureStringDelimiter});
813 return FeatureSet(names.begin(), names.end());
Dan Albertbe8e54b2015-05-18 13:06:53 -0700814}
815
David Pursell22fc5e92015-09-30 13:35:42 -0700816bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
817 return feature_set.count(feature) > 0 &&
818 supported_features().count(feature) > 0;
819}
820
Dan Albertbe8e54b2015-05-18 13:06:53 -0700821bool atransport::has_feature(const std::string& feature) const {
822 return features_.count(feature) > 0;
823}
824
David Pursella07dbad2015-09-22 10:43:08 -0700825void atransport::SetFeatures(const std::string& features_string) {
826 features_ = StringToFeatureSet(features_string);
Dan Albertbe8e54b2015-05-18 13:06:53 -0700827}
828
Yabin Cui2d4c1982015-08-28 15:09:44 -0700829void atransport::AddDisconnect(adisconnect* disconnect) {
830 disconnects_.push_back(disconnect);
831}
832
833void atransport::RemoveDisconnect(adisconnect* disconnect) {
834 disconnects_.remove(disconnect);
835}
836
837void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -0700838 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -0700839 disconnect->func(disconnect->opaque, this);
840 }
841 disconnects_.clear();
842}
843
Elliott Hughes88b4c852015-04-30 17:32:03 -0700844#if ADB_HOST
845
Dan Alberta8c34142015-05-06 16:48:52 -0700846static void append_transport_info(std::string* result, const char* key,
847 const char* value, bool sanitize) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700848 if (value == nullptr || *value == '\0') {
Scott Anderson27042382012-05-30 18:11:27 -0700849 return;
Scott Anderson27042382012-05-30 18:11:27 -0700850 }
851
Elliott Hughes88b4c852015-04-30 17:32:03 -0700852 *result += ' ';
853 *result += key;
854
855 for (const char* p = value; *p; ++p) {
856 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
857 }
Scott Anderson27042382012-05-30 18:11:27 -0700858}
859
Dan Albertecce5032015-05-18 16:46:31 -0700860static void append_transport(const atransport* t, std::string* result,
861 bool long_listing) {
Scott Anderson27042382012-05-30 18:11:27 -0700862 const char* serial = t->serial;
Elliott Hughes88b4c852015-04-30 17:32:03 -0700863 if (!serial || !serial[0]) {
Dan Alberta8c34142015-05-06 16:48:52 -0700864 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -0700865 }
Scott Anderson27042382012-05-30 18:11:27 -0700866
867 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700868 *result += serial;
869 *result += '\t';
870 *result += t->connection_state_name();
Scott Anderson27042382012-05-30 18:11:27 -0700871 } else {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800872 android::base::StringAppendF(result, "%-22s %s", serial,
873 t->connection_state_name().c_str());
Scott Anderson27042382012-05-30 18:11:27 -0700874
Elliott Hughes88b4c852015-04-30 17:32:03 -0700875 append_transport_info(result, "", t->devpath, false);
876 append_transport_info(result, "product:", t->product, false);
877 append_transport_info(result, "model:", t->model, true);
878 append_transport_info(result, "device:", t->device, false);
Scott Anderson27042382012-05-30 18:11:27 -0700879 }
Elliott Hughes88b4c852015-04-30 17:32:03 -0700880 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -0700881}
882
Elliott Hughes88b4c852015-04-30 17:32:03 -0700883std::string list_transports(bool long_listing) {
884 std::string result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800885 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700886 for (const auto& t : transport_list) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700887 append_transport(t, &result, long_listing);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800888 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800889 adb_mutex_unlock(&transport_lock);
Elliott Hughes88b4c852015-04-30 17:32:03 -0700890 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800891}
892
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800893/* hack for osx */
Dan Albertecce5032015-05-18 16:46:31 -0700894void close_usb_devices() {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800895 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700896 for (const auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700897 if (!t->kicked) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800898 t->kicked = 1;
899 t->kick(t);
900 }
901 }
902 adb_mutex_unlock(&transport_lock);
903}
904#endif // ADB_HOST
905
Dan Albertecce5032015-05-18 16:46:31 -0700906int register_socket_transport(int s, const char *serial, int port, int local) {
907 atransport* t = new atransport();
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100908
909 if (!serial) {
Dan Albertecce5032015-05-18 16:46:31 -0700910 char buf[32];
911 snprintf(buf, sizeof(buf), "T-%p", t);
912 serial = buf;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100913 }
Dan Albertecce5032015-05-18 16:46:31 -0700914
Yabin Cui815ad882015-09-02 17:44:28 -0700915 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700916 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -0700917 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700918 return -1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800919 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700920
921 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700922 for (const auto& transport : pending_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700923 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700924 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700925 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700926 return -1;
927 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800928 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700929
Elliott Hughes85952832015-10-07 15:59:35 -0700930 for (const auto& transport : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700931 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700932 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700933 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700934 return -1;
935 }
936 }
937
Dan Albertecce5032015-05-18 16:46:31 -0700938 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700939 t->serial = strdup(serial);
940 adb_mutex_unlock(&transport_lock);
941
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800942 register_transport(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700943 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800944}
945
Mike Lockwood81ffe172009-10-11 23:04:18 -0400946#if ADB_HOST
Dan Albertecce5032015-05-18 16:46:31 -0700947atransport *find_transport(const char *serial) {
948 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400949
950 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700951 for (auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700952 if (t->serial && strcmp(serial, t->serial) == 0) {
953 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400954 break;
955 }
Dan Albertecce5032015-05-18 16:46:31 -0700956 }
Mike Lockwood81ffe172009-10-11 23:04:18 -0400957 adb_mutex_unlock(&transport_lock);
958
Dan Albertecce5032015-05-18 16:46:31 -0700959 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400960}
961
Yabin Cui4d64fd82015-08-27 12:03:11 -0700962void kick_all_tcp_devices() {
Mike Lockwood81ffe172009-10-11 23:04:18 -0400963 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700964 for (auto& t : transport_list) {
965 // TCP/IP devices have adb_port == 0.
Mike Lockwood01c2c302010-05-24 10:44:35 -0400966 if (t->type == kTransportLocal && t->adb_port == 0) {
Yabin Cui4e222292015-08-31 11:50:24 -0700967 // Kicking breaks the read_transport thread of this transport out of any read, then
968 // the read_transport thread will notify the main thread to make this transport
969 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -0700970 // Finally, this transport will be closed and freed in the main thread.
971 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400972 }
Dan Albertecce5032015-05-18 16:46:31 -0700973 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400974 adb_mutex_unlock(&transport_lock);
975}
976
Mike Lockwood81ffe172009-10-11 23:04:18 -0400977#endif
978
Dan Albertecce5032015-05-18 16:46:31 -0700979void register_usb_transport(usb_handle* usb, const char* serial,
980 const char* devpath, unsigned writeable) {
981 atransport* t = new atransport();
982
Yabin Cui815ad882015-09-02 17:44:28 -0700983 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800984 serial ? serial : "");
Dan Albert9a50f4c2015-05-18 16:43:57 -0700985 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800986 if(serial) {
987 t->serial = strdup(serial);
988 }
Dan Albertecce5032015-05-18 16:46:31 -0700989
990 if (devpath) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700991 t->devpath = strdup(devpath);
992 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700993
994 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700995 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700996 adb_mutex_unlock(&transport_lock);
997
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800998 register_transport(t);
999}
1000
Dan Albert9a50f4c2015-05-18 16:43:57 -07001001// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertecce5032015-05-18 16:46:31 -07001002void unregister_usb_transport(usb_handle *usb) {
Mike Lockwoode45583f2009-08-08 12:37:44 -04001003 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -07001004 transport_list.remove_if([usb](atransport* t) {
1005 return t->usb == usb && t->connection_state == kCsNoPerm;
1006 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001007 adb_mutex_unlock(&transport_lock);
1008}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001009
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001010int check_header(apacket *p, atransport *t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001011{
1012 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001013 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001014 return -1;
1015 }
1016
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001017 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001018 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1019 << t->get_max_payload();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001020 return -1;
1021 }
1022
1023 return 0;
1024}
1025
1026int check_data(apacket *p)
1027{
1028 unsigned count, sum;
1029 unsigned char *x;
1030
1031 count = p->msg.data_length;
1032 x = p->data;
1033 sum = 0;
1034 while(count-- > 0) {
1035 sum += *x++;
1036 }
1037
1038 if(sum != p->msg.data_check) {
1039 return -1;
1040 } else {
1041 return 0;
1042 }
1043}