blob: 6a030d399f32f3015c044907c484044efddfbe3e [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
Yabin Cui4d64fd82015-08-27 12:03:11 -070032#include <base/logging.h>
Elliott Hughes88b4c852015-04-30 17:32:03 -070033#include <base/stringprintf.h>
Dan Albertbe8e54b2015-05-18 13:06:53 -070034#include <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"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080038
39static void transport_unref(atransport *t);
40
Josh Gaoe3a87d02015-11-11 17:56:12 -080041static auto& transport_list = *new std::list<atransport*>();
42static auto& pending_list = *new std::list<atransport*>();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070043
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080044ADB_MUTEX_DEFINE( transport_lock );
45
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -080046const char* const kFeatureShell2 = "shell_v2";
47const char* const kFeatureCmd = "cmd";
48
Yabin Cui19bec5b2015-09-22 15:52:57 -070049static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +010050 unsigned command = p->msg.command;
51 int len = p->msg.data_length;
52 char cmd[9];
53 char arg0[12], arg1[12];
54 int n;
55
56 for (n = 0; n < 4; n++) {
57 int b = (command >> (n*8)) & 255;
58 if (b < 32 || b >= 127)
59 break;
60 cmd[n] = (char)b;
61 }
62 if (n == 4) {
63 cmd[4] = 0;
64 } else {
65 /* There is some non-ASCII name in the command, so dump
66 * the hexadecimal value instead */
67 snprintf(cmd, sizeof cmd, "%08x", command);
68 }
69
70 if (p->msg.arg0 < 256U)
71 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
72 else
73 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
74
75 if (p->msg.arg1 < 256U)
76 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
77 else
78 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
79
Yabin Cui19bec5b2015-09-22 15:52:57 -070080 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
81 name, func, cmd, arg0, arg1, len);
82 result += dump_hex(p->data, len);
83 return result;
David 'Digit' Turner58f59682011-01-06 14:11:07 +010084}
David 'Digit' Turner58f59682011-01-06 14:11:07 +010085
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080086static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +010087read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080088{
Yabin Cuia96dabf2015-07-30 19:58:10 -070089 char buff[8];
David 'Digit' Turner58f59682011-01-06 14:11:07 +010090 if (!name) {
91 snprintf(buff, sizeof buff, "fd=%d", fd);
92 name = buff;
93 }
Yabin Cuia96dabf2015-07-30 19:58:10 -070094 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
95 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080096 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -070097 int r = adb_read(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080098 if(r > 0) {
99 len -= r;
Yabin Cuia96dabf2015-07-30 19:58:10 -0700100 p += r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800101 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700102 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 -0800103 return -1;
104 }
105 }
106
Yabin Cui19bec5b2015-09-22 15:52:57 -0700107 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800108 return 0;
109}
110
111static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100112write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800113{
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100114 char buff[8];
115 if (!name) {
116 snprintf(buff, sizeof buff, "fd=%d", fd);
117 name = buff;
118 }
Yabin Cui19bec5b2015-09-22 15:52:57 -0700119 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cuia96dabf2015-07-30 19:58:10 -0700120 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
121 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800122 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -0700123 int r = adb_write(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800124 if(r > 0) {
125 len -= r;
126 p += r;
127 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700128 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 -0800129 return -1;
130 }
131 }
132 return 0;
133}
134
135static void transport_socket_events(int fd, unsigned events, void *_t)
136{
Dan Albertf30d73c2015-02-25 17:51:28 -0800137 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui815ad882015-09-02 17:44:28 -0700138 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800139 if(events & FDE_READ){
140 apacket *p = 0;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100141 if(read_packet(fd, t->serial, &p)){
Yabin Cui815ad882015-09-02 17:44:28 -0700142 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 -0800143 } else {
144 handle_packet(p, (atransport *) _t);
145 }
146 }
147}
148
149void send_packet(apacket *p, atransport *t)
150{
151 unsigned char *x;
152 unsigned sum;
153 unsigned count;
154
155 p->msg.magic = p->msg.command ^ 0xffffffff;
156
157 count = p->msg.data_length;
158 x = (unsigned char *) p->data;
159 sum = 0;
160 while(count-- > 0){
161 sum += *x++;
162 }
163 p->msg.data_check = sum;
164
165 print_packet("send", p);
166
167 if (t == NULL) {
Yabin Cui815ad882015-09-02 17:44:28 -0700168 D("Transport is null");
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700169 // Zap errno because print_packet() and other stuff have errno effect.
170 errno = 0;
171 fatal_errno("Transport is null");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800172 }
173
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100174 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800175 fatal_errno("cannot enqueue packet on transport socket");
176 }
177}
178
Yabin Cui4e222292015-08-31 11:50:24 -0700179// The transport is opened by transport_register_func before
180// the read_transport and write_transport threads are started.
181//
182// The read_transport thread issues a SYNC(1, token) message to let
183// the write_transport thread know to start things up. In the event
184// of transport IO failure, the read_transport thread will post a
185// SYNC(0,0) message to ensure shutdown.
186//
187// The transport will not actually be closed until both threads exit, but the threads
188// will kick the transport on their way out to disconnect the underlying device.
189//
190// read_transport thread reads data from a transport (representing a usb/tcp connection),
191// and makes the main thread call handle_packet().
192static void *read_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800193{
Dan Albertf30d73c2015-02-25 17:51:28 -0800194 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800195 apacket *p;
196
Yabin Cui4e222292015-08-31 11:50:24 -0700197 adb_thread_setname(android::base::StringPrintf("<-%s",
198 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700199 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100200 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800201 p = get_apacket();
202 p->msg.command = A_SYNC;
203 p->msg.arg0 = 1;
204 p->msg.arg1 = ++(t->sync_token);
205 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100206 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800207 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700208 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800209 goto oops;
210 }
211
Yabin Cui815ad882015-09-02 17:44:28 -0700212 D("%s: data pump started", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800213 for(;;) {
214 p = get_apacket();
215
216 if(t->read_from_remote(p, t) == 0){
Yabin Cui815ad882015-09-02 17:44:28 -0700217 D("%s: received remote packet, sending to transport",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100218 t->serial);
219 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800220 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700221 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800222 goto oops;
223 }
224 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700225 D("%s: remote read failed for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800226 put_apacket(p);
227 break;
228 }
229 }
230
Yabin Cui815ad882015-09-02 17:44:28 -0700231 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800232 p = get_apacket();
233 p->msg.command = A_SYNC;
234 p->msg.arg0 = 0;
235 p->msg.arg1 = 0;
236 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100237 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800238 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700239 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800240 }
241
242oops:
Yabin Cui815ad882015-09-02 17:44:28 -0700243 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800244 kick_transport(t);
245 transport_unref(t);
246 return 0;
247}
248
Yabin Cui4e222292015-08-31 11:50:24 -0700249// write_transport thread gets packets sent by the main thread (through send_packet()),
250// and writes to a transport (representing a usb/tcp connection).
251static void *write_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800252{
Dan Albertf30d73c2015-02-25 17:51:28 -0800253 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800254 apacket *p;
255 int active = 0;
256
Yabin Cui4e222292015-08-31 11:50:24 -0700257 adb_thread_setname(android::base::StringPrintf("->%s",
258 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700259 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100260 t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800261
262 for(;;){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100263 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700264 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100265 t->serial, t->fd );
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800266 break;
267 }
268 if(p->msg.command == A_SYNC){
269 if(p->msg.arg0 == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700270 D("%s: transport SYNC offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800271 put_apacket(p);
272 break;
273 } else {
274 if(p->msg.arg1 == t->sync_token) {
Yabin Cui815ad882015-09-02 17:44:28 -0700275 D("%s: transport SYNC online", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800276 active = 1;
277 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700278 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100279 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800280 }
281 }
282 } else {
283 if(active) {
Yabin Cui815ad882015-09-02 17:44:28 -0700284 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285 t->write_to_remote(p, t);
286 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700287 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800288 }
289 }
290
291 put_apacket(p);
292 }
293
Yabin Cui815ad882015-09-02 17:44:28 -0700294 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800295 kick_transport(t);
296 transport_unref(t);
297 return 0;
298}
299
Yabin Cui4d64fd82015-08-27 12:03:11 -0700300static void kick_transport_locked(atransport* t) {
301 CHECK(t != nullptr);
302 if (!t->kicked) {
303 t->kicked = true;
304 t->kick(t);
305 }
306}
307
308void kick_transport(atransport* t) {
309 adb_mutex_lock(&transport_lock);
310 kick_transport_locked(t);
311 adb_mutex_unlock(&transport_lock);
312}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800313
314static int transport_registration_send = -1;
315static int transport_registration_recv = -1;
316static fdevent transport_registration_fde;
317
318
319#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800320
321/* this adds support required by the 'track-devices' service.
322 * this is used to send the content of "list_transport" to any
323 * number of client connections that want it through a single
324 * live TCP connection
325 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800326struct device_tracker {
327 asocket socket;
328 int update_needed;
329 device_tracker* next;
330};
331
332/* linked list of all device trackers */
333static device_tracker* device_tracker_list;
334
335static void
336device_tracker_remove( device_tracker* tracker )
337{
338 device_tracker** pnode = &device_tracker_list;
339 device_tracker* node = *pnode;
340
341 adb_mutex_lock( &transport_lock );
342 while (node) {
343 if (node == tracker) {
344 *pnode = node->next;
345 break;
346 }
347 pnode = &node->next;
348 node = *pnode;
349 }
350 adb_mutex_unlock( &transport_lock );
351}
352
353static void
354device_tracker_close( asocket* socket )
355{
356 device_tracker* tracker = (device_tracker*) socket;
357 asocket* peer = socket->peer;
358
Yabin Cui815ad882015-09-02 17:44:28 -0700359 D( "device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800360 if (peer) {
361 peer->peer = NULL;
362 peer->close(peer);
363 }
364 device_tracker_remove(tracker);
365 free(tracker);
366}
367
368static int
369device_tracker_enqueue( asocket* socket, apacket* p )
370{
371 /* you can't read from a device tracker, close immediately */
372 put_apacket(p);
373 device_tracker_close(socket);
374 return -1;
375}
376
Elliott Hughes88b4c852015-04-30 17:32:03 -0700377static int device_tracker_send(device_tracker* tracker, const std::string& string) {
378 apacket* p = get_apacket();
379 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800380
Elliott Hughes88b4c852015-04-30 17:32:03 -0700381 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
382 memcpy(&p->data[4], string.data(), string.size());
383 p->len = 4 + string.size();
384 return peer->enqueue(peer, p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800385}
386
Elliott Hughes88b4c852015-04-30 17:32:03 -0700387static void device_tracker_ready(asocket* socket) {
388 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800389
Elliott Hughes88b4c852015-04-30 17:32:03 -0700390 // We want to send the device list when the tracker connects
391 // for the first time, even if no update occurred.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800392 if (tracker->update_needed > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800393 tracker->update_needed = 0;
394
Elliott Hughes88b4c852015-04-30 17:32:03 -0700395 std::string transports = list_transports(false);
396 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800397 }
398}
399
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800400asocket*
401create_device_tracker(void)
402{
Elliott Hughesd0269c92015-04-21 19:39:52 -0700403 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
404 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800405
Yabin Cui815ad882015-09-02 17:44:28 -0700406 D( "device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800407
408 tracker->socket.enqueue = device_tracker_enqueue;
409 tracker->socket.ready = device_tracker_ready;
410 tracker->socket.close = device_tracker_close;
411 tracker->update_needed = 1;
412
413 tracker->next = device_tracker_list;
414 device_tracker_list = tracker;
415
416 return &tracker->socket;
417}
418
419
Elliott Hughes88b4c852015-04-30 17:32:03 -0700420// Call this function each time the transport list has changed.
421void update_transports() {
422 std::string transports = list_transports(false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800423
Elliott Hughes88b4c852015-04-30 17:32:03 -0700424 device_tracker* tracker = device_tracker_list;
425 while (tracker != nullptr) {
426 device_tracker* next = tracker->next;
427 // This may destroy the tracker if the connection is closed.
428 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800429 tracker = next;
430 }
431}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700432
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800433#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700434
435void update_transports() {
436 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800437}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700438
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800439#endif // ADB_HOST
440
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800441struct tmsg
442{
443 atransport *transport;
444 int action;
445};
446
447static int
448transport_read_action(int fd, struct tmsg* m)
449{
450 char *p = (char*)m;
451 int len = sizeof(*m);
452 int r;
453
454 while(len > 0) {
455 r = adb_read(fd, p, len);
456 if(r > 0) {
457 len -= r;
458 p += r;
459 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700460 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800461 return -1;
462 }
463 }
464 return 0;
465}
466
467static int
468transport_write_action(int fd, struct tmsg* m)
469{
470 char *p = (char*)m;
471 int len = sizeof(*m);
472 int r;
473
474 while(len > 0) {
475 r = adb_write(fd, p, len);
476 if(r > 0) {
477 len -= r;
478 p += r;
479 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700480 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800481 return -1;
482 }
483 }
484 return 0;
485}
486
487static void transport_registration_func(int _fd, unsigned ev, void *data)
488{
489 tmsg m;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800490 int s[2];
491 atransport *t;
492
493 if(!(ev & FDE_READ)) {
494 return;
495 }
496
497 if(transport_read_action(_fd, &m)) {
498 fatal_errno("cannot read transport registration socket");
499 }
500
501 t = m.transport;
502
Dan Albertbe8e54b2015-05-18 13:06:53 -0700503 if (m.action == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700504 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800505
506 /* IMPORTANT: the remove closes one half of the
507 ** socket pair. The close closes the other half.
508 */
509 fdevent_remove(&(t->transport_fde));
510 adb_close(t->fd);
511
512 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700513 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800514 adb_mutex_unlock(&transport_lock);
515
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800516 if (t->product)
517 free(t->product);
518 if (t->serial)
519 free(t->serial);
Scott Andersonfa020922012-05-25 14:10:02 -0700520 if (t->model)
521 free(t->model);
522 if (t->device)
523 free(t->device);
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700524 if (t->devpath)
525 free(t->devpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800526
Dan Albertecce5032015-05-18 16:46:31 -0700527 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800528
529 update_transports();
530 return;
531 }
532
Mike Lockwoode45583f2009-08-08 12:37:44 -0400533 /* don't create transport threads for inaccessible devices */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700534 if (t->connection_state != kCsNoPerm) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800535 /* initial references are the two threads */
Mike Lockwoode45583f2009-08-08 12:37:44 -0400536 t->ref_count = 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800537
Dan Albertecce5032015-05-18 16:46:31 -0700538 if (adb_socketpair(s)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400539 fatal_errno("cannot open transport socketpair");
540 }
541
Yabin Cui815ad882015-09-02 17:44:28 -0700542 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwoode45583f2009-08-08 12:37:44 -0400543
544 t->transport_socket = s[0];
545 t->fd = s[1];
546
Mike Lockwoode45583f2009-08-08 12:37:44 -0400547 fdevent_install(&(t->transport_fde),
548 t->transport_socket,
549 transport_socket_events,
550 t);
551
552 fdevent_set(&(t->transport_fde), FDE_READ);
553
Yabin Cui4e222292015-08-31 11:50:24 -0700554 if (!adb_thread_create(write_transport_thread, t)) {
555 fatal_errno("cannot create write_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400556 }
557
Yabin Cui4e222292015-08-31 11:50:24 -0700558 if (!adb_thread_create(read_transport_thread, t)) {
559 fatal_errno("cannot create read_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400560 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800561 }
562
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800563 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700564 pending_list.remove(t);
565 transport_list.push_front(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800566 adb_mutex_unlock(&transport_lock);
567
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800568 update_transports();
569}
570
571void init_transport_registration(void)
572{
573 int s[2];
574
575 if(adb_socketpair(s)){
576 fatal_errno("cannot open transport registration socketpair");
577 }
Yabin Cui815ad882015-09-02 17:44:28 -0700578 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800579
580 transport_registration_send = s[0];
581 transport_registration_recv = s[1];
582
583 fdevent_install(&transport_registration_fde,
584 transport_registration_recv,
585 transport_registration_func,
586 0);
587
588 fdevent_set(&transport_registration_fde, FDE_READ);
589}
590
591/* the fdevent select pump is single threaded */
592static void register_transport(atransport *transport)
593{
594 tmsg m;
595 m.transport = transport;
596 m.action = 1;
Yabin Cui815ad882015-09-02 17:44:28 -0700597 D("transport: %s registered", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800598 if(transport_write_action(transport_registration_send, &m)) {
599 fatal_errno("cannot write transport registration socket\n");
600 }
601}
602
603static void remove_transport(atransport *transport)
604{
605 tmsg m;
606 m.transport = transport;
607 m.action = 0;
Yabin Cui815ad882015-09-02 17:44:28 -0700608 D("transport: %s removed", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800609 if(transport_write_action(transport_registration_send, &m)) {
610 fatal_errno("cannot write transport registration socket\n");
611 }
612}
613
614
Yabin Cui4d64fd82015-08-27 12:03:11 -0700615static void transport_unref(atransport* t) {
616 CHECK(t != nullptr);
617 adb_mutex_lock(&transport_lock);
618 CHECK_GT(t->ref_count, 0u);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400619 t->ref_count--;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400620 if (t->ref_count == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700621 D("transport: %s unref (kicking and closing)", t->serial);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700622 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400623 t->close(t);
624 remove_transport(t);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100625 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700626 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400627 }
Yabin Cui4d64fd82015-08-27 12:03:11 -0700628 adb_mutex_unlock(&transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800629}
630
Scott Anderson27042382012-05-30 18:11:27 -0700631static int qual_match(const char *to_test,
Elliott Hughesabfa7202015-04-03 16:12:15 -0700632 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson27042382012-05-30 18:11:27 -0700633{
634 if (!to_test || !*to_test)
635 /* Return true if both the qual and to_test are null strings. */
636 return !qual || !*qual;
637
638 if (!qual)
639 return 0;
640
641 if (prefix) {
642 while (*prefix) {
643 if (*prefix++ != *to_test++)
644 return 0;
645 }
646 }
647
648 while (*qual) {
649 char ch = *qual++;
Elliott Hughesabfa7202015-04-03 16:12:15 -0700650 if (sanitize_qual && !isalnum(ch))
Scott Anderson27042382012-05-30 18:11:27 -0700651 ch = '_';
652 if (ch != *to_test++)
653 return 0;
654 }
655
656 /* Everything matched so far. Return true if *to_test is a NUL. */
657 return !*to_test;
658}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659
Elliott Hughes67943d12015-10-07 14:55:10 -0700660atransport* acquire_one_transport(TransportType type, const char* serial,
661 bool* is_ambiguous, std::string* error_out) {
662 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800663
Elliott Hughes67943d12015-10-07 14:55:10 -0700664 if (serial) {
665 *error_out = android::base::StringPrintf("device '%s' not found", serial);
666 } else if (type == kTransportLocal) {
667 *error_out = "no emulators found";
668 } else if (type == kTransportAny) {
669 *error_out = "no devices/emulators found";
670 } else {
671 *error_out = "no devices found";
672 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800673
674 adb_mutex_lock(&transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -0700675 for (const auto& t : transport_list) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700676 if (t->connection_state == kCsNoPerm) {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800677 *error_out = UsbNoPermissionsLongHelpText();
678 // If we couldn't figure out a reasonable help message default to something generic.
679 if (error_out->empty()) {
680 *error_out = "insufficient permissions for device";
681 }
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400682 continue;
683 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400684
Elliott Hughes67943d12015-10-07 14:55:10 -0700685 // Check for matching serial number.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800686 if (serial) {
Scott Anderson27042382012-05-30 18:11:27 -0700687 if ((t->serial && !strcmp(serial, t->serial)) ||
688 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughesabfa7202015-04-03 16:12:15 -0700689 qual_match(serial, "product:", t->product, false) ||
690 qual_match(serial, "model:", t->model, true) ||
691 qual_match(serial, "device:", t->device, false)) {
Scott Anderson27042382012-05-30 18:11:27 -0700692 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700693 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700694 if (is_ambiguous) *is_ambiguous = true;
695 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -0700696 break;
697 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800698 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700699 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800700 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700701 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800702 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700703 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700704 if (is_ambiguous) *is_ambiguous = true;
705 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800706 break;
707 }
708 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700709 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800710 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700711 *error_out = "more than one emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700712 if (is_ambiguous) *is_ambiguous = true;
713 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800714 break;
715 }
716 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700717 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800718 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700719 *error_out = "more than one device/emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700720 if (is_ambiguous) *is_ambiguous = true;
721 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800722 break;
723 }
724 result = t;
725 }
726 }
727 }
728 adb_mutex_unlock(&transport_lock);
729
Elliott Hughes67943d12015-10-07 14:55:10 -0700730 // Don't return unauthorized devices; the caller can't do anything with them.
731 if (result && result->connection_state == kCsUnauthorized) {
732 *error_out = "device unauthorized.\n";
733 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
734 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
735 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
736 *error_out += "\n";
737 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
738 *error_out += "Otherwise check for a confirmation dialog on your device.";
739 result = nullptr;
740 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700741
Elliott Hughes67943d12015-10-07 14:55:10 -0700742 // Don't return offline devices; the caller can't do anything with them.
743 if (result && result->connection_state == kCsOffline) {
744 *error_out = "device offline";
745 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800746 }
747
748 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700749 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800750 }
751
752 return result;
753}
754
David Pursell6e5c7eb2015-12-02 15:14:31 -0800755const std::string atransport::connection_state_name() const {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700756 switch (connection_state) {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800757 case kCsOffline: return "offline";
758 case kCsBootloader: return "bootloader";
759 case kCsDevice: return "device";
760 case kCsHost: return "host";
761 case kCsRecovery: return "recovery";
762 case kCsNoPerm: {
763 std::string message = UsbNoPermissionsShortHelpText();
764 return message.empty() ? "no permissions" : message;
765 }
766 case kCsSideload: return "sideload";
767 case kCsUnauthorized: return "unauthorized";
768 default: return "unknown";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800769 }
770}
771
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100772void atransport::update_version(int version, size_t payload) {
773 protocol_version = std::min(version, A_VERSION);
774 max_payload = std::min(payload, MAX_PAYLOAD);
775}
776
777int atransport::get_protocol_version() const {
778 return protocol_version;
779}
780
781size_t atransport::get_max_payload() const {
782 return max_payload;
783}
784
David Pursella07dbad2015-09-22 10:43:08 -0700785namespace {
David Pursell8da19a42015-08-31 10:42:13 -0700786
David Pursella07dbad2015-09-22 10:43:08 -0700787constexpr char kFeatureStringDelimiter = ',';
788
789} // namespace
Dan Albertbe8e54b2015-05-18 13:06:53 -0700790
791const FeatureSet& supported_features() {
David Pursella07dbad2015-09-22 10:43:08 -0700792 // Local static allocation to avoid global non-POD variables.
793 static const FeatureSet* features = new FeatureSet{
Todd Kennedy1e2f7dc2015-11-03 16:53:08 -0800794 kFeatureShell2,
Elliott Hughesd5eeac92015-11-06 18:05:16 -0800795 // Internal master has 'cmd'. AOSP master doesn't.
796 // kFeatureCmd
797
David Pursell6d5fad32015-09-25 08:37:13 -0700798 // Increment ADB_SERVER_VERSION whenever the feature list changes to
799 // make sure that the adb client and server features stay in sync
800 // (http://b/24370690).
David Pursella07dbad2015-09-22 10:43:08 -0700801 };
802
803 return *features;
804}
805
806std::string FeatureSetToString(const FeatureSet& features) {
807 return android::base::Join(features, kFeatureStringDelimiter);
808}
809
810FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -0700811 if (features_string.empty()) {
812 return FeatureSet();
813 }
814
David Pursella07dbad2015-09-22 10:43:08 -0700815 auto names = android::base::Split(features_string,
816 {kFeatureStringDelimiter});
817 return FeatureSet(names.begin(), names.end());
Dan Albertbe8e54b2015-05-18 13:06:53 -0700818}
819
David Pursell22fc5e92015-09-30 13:35:42 -0700820bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
821 return feature_set.count(feature) > 0 &&
822 supported_features().count(feature) > 0;
823}
824
Dan Albertbe8e54b2015-05-18 13:06:53 -0700825bool atransport::has_feature(const std::string& feature) const {
826 return features_.count(feature) > 0;
827}
828
David Pursella07dbad2015-09-22 10:43:08 -0700829void atransport::SetFeatures(const std::string& features_string) {
830 features_ = StringToFeatureSet(features_string);
Dan Albertbe8e54b2015-05-18 13:06:53 -0700831}
832
Yabin Cui2d4c1982015-08-28 15:09:44 -0700833void atransport::AddDisconnect(adisconnect* disconnect) {
834 disconnects_.push_back(disconnect);
835}
836
837void atransport::RemoveDisconnect(adisconnect* disconnect) {
838 disconnects_.remove(disconnect);
839}
840
841void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -0700842 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -0700843 disconnect->func(disconnect->opaque, this);
844 }
845 disconnects_.clear();
846}
847
Elliott Hughes88b4c852015-04-30 17:32:03 -0700848#if ADB_HOST
849
Dan Alberta8c34142015-05-06 16:48:52 -0700850static void append_transport_info(std::string* result, const char* key,
851 const char* value, bool sanitize) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700852 if (value == nullptr || *value == '\0') {
Scott Anderson27042382012-05-30 18:11:27 -0700853 return;
Scott Anderson27042382012-05-30 18:11:27 -0700854 }
855
Elliott Hughes88b4c852015-04-30 17:32:03 -0700856 *result += ' ';
857 *result += key;
858
859 for (const char* p = value; *p; ++p) {
860 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
861 }
Scott Anderson27042382012-05-30 18:11:27 -0700862}
863
Dan Albertecce5032015-05-18 16:46:31 -0700864static void append_transport(const atransport* t, std::string* result,
865 bool long_listing) {
Scott Anderson27042382012-05-30 18:11:27 -0700866 const char* serial = t->serial;
Elliott Hughes88b4c852015-04-30 17:32:03 -0700867 if (!serial || !serial[0]) {
Dan Alberta8c34142015-05-06 16:48:52 -0700868 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -0700869 }
Scott Anderson27042382012-05-30 18:11:27 -0700870
871 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700872 *result += serial;
873 *result += '\t';
874 *result += t->connection_state_name();
Scott Anderson27042382012-05-30 18:11:27 -0700875 } else {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800876 android::base::StringAppendF(result, "%-22s %s", serial,
877 t->connection_state_name().c_str());
Scott Anderson27042382012-05-30 18:11:27 -0700878
Elliott Hughes88b4c852015-04-30 17:32:03 -0700879 append_transport_info(result, "", t->devpath, false);
880 append_transport_info(result, "product:", t->product, false);
881 append_transport_info(result, "model:", t->model, true);
882 append_transport_info(result, "device:", t->device, false);
Scott Anderson27042382012-05-30 18:11:27 -0700883 }
Elliott Hughes88b4c852015-04-30 17:32:03 -0700884 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -0700885}
886
Elliott Hughes88b4c852015-04-30 17:32:03 -0700887std::string list_transports(bool long_listing) {
888 std::string result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800889 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700890 for (const auto& t : transport_list) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700891 append_transport(t, &result, long_listing);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800892 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800893 adb_mutex_unlock(&transport_lock);
Elliott Hughes88b4c852015-04-30 17:32:03 -0700894 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800895}
896
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800897/* hack for osx */
Dan Albertecce5032015-05-18 16:46:31 -0700898void close_usb_devices() {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800899 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700900 for (const auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700901 if (!t->kicked) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800902 t->kicked = 1;
903 t->kick(t);
904 }
905 }
906 adb_mutex_unlock(&transport_lock);
907}
908#endif // ADB_HOST
909
Dan Albertecce5032015-05-18 16:46:31 -0700910int register_socket_transport(int s, const char *serial, int port, int local) {
911 atransport* t = new atransport();
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100912
913 if (!serial) {
Dan Albertecce5032015-05-18 16:46:31 -0700914 char buf[32];
915 snprintf(buf, sizeof(buf), "T-%p", t);
916 serial = buf;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100917 }
Dan Albertecce5032015-05-18 16:46:31 -0700918
Yabin Cui815ad882015-09-02 17:44:28 -0700919 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700920 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -0700921 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700922 return -1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800923 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700924
925 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700926 for (const auto& transport : pending_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700927 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700928 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700929 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700930 return -1;
931 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800932 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700933
Elliott Hughes85952832015-10-07 15:59:35 -0700934 for (const auto& transport : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700935 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700936 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700937 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700938 return -1;
939 }
940 }
941
Dan Albertecce5032015-05-18 16:46:31 -0700942 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700943 t->serial = strdup(serial);
944 adb_mutex_unlock(&transport_lock);
945
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800946 register_transport(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700947 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800948}
949
Mike Lockwood81ffe172009-10-11 23:04:18 -0400950#if ADB_HOST
Dan Albertecce5032015-05-18 16:46:31 -0700951atransport *find_transport(const char *serial) {
952 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400953
954 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700955 for (auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700956 if (t->serial && strcmp(serial, t->serial) == 0) {
957 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400958 break;
959 }
Dan Albertecce5032015-05-18 16:46:31 -0700960 }
Mike Lockwood81ffe172009-10-11 23:04:18 -0400961 adb_mutex_unlock(&transport_lock);
962
Dan Albertecce5032015-05-18 16:46:31 -0700963 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400964}
965
Yabin Cui4d64fd82015-08-27 12:03:11 -0700966void kick_all_tcp_devices() {
Mike Lockwood81ffe172009-10-11 23:04:18 -0400967 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700968 for (auto& t : transport_list) {
969 // TCP/IP devices have adb_port == 0.
Mike Lockwood01c2c302010-05-24 10:44:35 -0400970 if (t->type == kTransportLocal && t->adb_port == 0) {
Yabin Cui4e222292015-08-31 11:50:24 -0700971 // Kicking breaks the read_transport thread of this transport out of any read, then
972 // the read_transport thread will notify the main thread to make this transport
973 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -0700974 // Finally, this transport will be closed and freed in the main thread.
975 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400976 }
Dan Albertecce5032015-05-18 16:46:31 -0700977 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400978 adb_mutex_unlock(&transport_lock);
979}
980
Mike Lockwood81ffe172009-10-11 23:04:18 -0400981#endif
982
Dan Albertecce5032015-05-18 16:46:31 -0700983void register_usb_transport(usb_handle* usb, const char* serial,
984 const char* devpath, unsigned writeable) {
985 atransport* t = new atransport();
986
Yabin Cui815ad882015-09-02 17:44:28 -0700987 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800988 serial ? serial : "");
Dan Albert9a50f4c2015-05-18 16:43:57 -0700989 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800990 if(serial) {
991 t->serial = strdup(serial);
992 }
Dan Albertecce5032015-05-18 16:46:31 -0700993
994 if (devpath) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700995 t->devpath = strdup(devpath);
996 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700997
998 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700999 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001000 adb_mutex_unlock(&transport_lock);
1001
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001002 register_transport(t);
1003}
1004
Dan Albert9a50f4c2015-05-18 16:43:57 -07001005// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertecce5032015-05-18 16:46:31 -07001006void unregister_usb_transport(usb_handle *usb) {
Mike Lockwoode45583f2009-08-08 12:37:44 -04001007 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -07001008 transport_list.remove_if([usb](atransport* t) {
1009 return t->usb == usb && t->connection_state == kCsNoPerm;
1010 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001011 adb_mutex_unlock(&transport_lock);
1012}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001013
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001014int check_header(apacket *p, atransport *t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001015{
1016 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001017 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001018 return -1;
1019 }
1020
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001021 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001022 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1023 << t->get_max_payload();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001024 return -1;
1025 }
1026
1027 return 0;
1028}
1029
1030int check_data(apacket *p)
1031{
1032 unsigned count, sum;
1033 unsigned char *x;
1034
1035 count = p->msg.data_length;
1036 x = p->data;
1037 sum = 0;
1038 while(count-- > 0) {
1039 sum += *x++;
1040 }
1041
1042 if(sum != p->msg.data_check) {
1043 return -1;
1044 } else {
1045 return 0;
1046 }
1047}