blob: f8c8c615f12c92a71a81053b098c4d4563463a2c [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albert76649012015-02-24 15:51:19 -080018
Dan Albert33134262015-03-19 15:21:08 -070019#include "sysdeps.h"
Dan Albert76649012015-02-24 15:51:19 -080020#include "transport.h"
21
Dan Albert055f1aa2015-02-20 17:24:58 -080022#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <stdio.h>
25#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Spencer Low363af562015-11-07 18:51:54 -080029#include <algorithm>
Dan Albertc7915a32015-05-18 16:46:31 -070030#include <list>
31
Elliott Hughes4f713192015-12-04 22:00:26 -080032#include <android-base/logging.h>
33#include <android-base/stringprintf.h>
34#include <android-base/strings.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070035
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036#include "adb.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070037#include "adb_utils.h"
Elliott Hughes1b708d32015-12-11 19:07:01 -080038#include "diagnose_usb.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039
40static void transport_unref(atransport *t);
41
Josh Gaob7b1edf2015-11-11 17:56:12 -080042static auto& transport_list = *new std::list<atransport*>();
43static auto& pending_list = *new std::list<atransport*>();
Benoit Goby1c45ee92013-03-29 18:22:36 -070044
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080045ADB_MUTEX_DEFINE( transport_lock );
46
Todd Kennedy51c05ec2015-11-10 00:03:25 +000047const char* const kFeatureShell2 = "shell_v2";
48const char* const kFeatureCmd = "cmd";
49
Yabin Cuiaed3c612015-09-22 15:52:57 -070050static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner730ff3b2011-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 Cuiaed3c612015-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' Turner730ff3b2011-01-06 14:11:07 +010085}
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010086
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080087static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010088read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080089{
Yabin Cui62641292015-07-30 19:58:10 -070090 char buff[8];
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010091 if (!name) {
92 snprintf(buff, sizeof buff, "fd=%d", fd);
93 name = buff;
94 }
Yabin Cui62641292015-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 Projectdd7bc332009-03-03 19:32:55 -080097 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -070098 int r = adb_read(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080099 if(r > 0) {
100 len -= r;
Yabin Cui62641292015-07-30 19:58:10 -0700101 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800102 } else {
Yabin Cui7a3f8d62015-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 Projectdd7bc332009-03-03 19:32:55 -0800104 return -1;
105 }
106 }
107
Yabin Cuiaed3c612015-09-22 15:52:57 -0700108 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800109 return 0;
110}
111
112static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100113write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800114{
David 'Digit' Turner730ff3b2011-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 Cuiaed3c612015-09-22 15:52:57 -0700120 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cui62641292015-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 Projectdd7bc332009-03-03 19:32:55 -0800123 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700124 int r = adb_write(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800125 if(r > 0) {
126 len -= r;
127 p += r;
128 } else {
Yabin Cui7a3f8d62015-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 Projectdd7bc332009-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 Albertbac34742015-02-25 17:51:28 -0800138 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700139 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800140 if(events & FDE_READ){
141 apacket *p = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100142 if(read_packet(fd, t->serial, &p)){
Yabin Cui7a3f8d62015-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 Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700169 D("Transport is null");
JP Abgrall408fa572011-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 Projectdd7bc332009-03-03 19:32:55 -0800173 }
174
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100175 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800176 fatal_errno("cannot enqueue packet on transport socket");
177 }
178}
179
Yabin Cuid6ab3c22015-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 Projectdd7bc332009-03-03 19:32:55 -0800194{
Dan Albertbac34742015-02-25 17:51:28 -0800195 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800196 apacket *p;
197
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700198 adb_thread_setname(android::base::StringPrintf("<-%s",
199 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700200 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100201 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Projectdd7bc332009-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' Turner730ff3b2011-01-06 14:11:07 +0100207 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700209 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210 goto oops;
211 }
212
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700213 D("%s: data pump started", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800214 for(;;) {
215 p = get_apacket();
216
217 if(t->read_from_remote(p, t) == 0){
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700218 D("%s: received remote packet, sending to transport",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100219 t->serial);
220 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700222 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800223 goto oops;
224 }
225 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700226 D("%s: remote read failed for transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 put_apacket(p);
228 break;
229 }
230 }
231
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700232 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Projectdd7bc332009-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' Turner730ff3b2011-01-06 14:11:07 +0100238 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700240 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 }
242
243oops:
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700244 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 kick_transport(t);
246 transport_unref(t);
247 return 0;
248}
249
Yabin Cuid6ab3c22015-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 Projectdd7bc332009-03-03 19:32:55 -0800253{
Dan Albertbac34742015-02-25 17:51:28 -0800254 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800255 apacket *p;
256 int active = 0;
257
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700258 adb_thread_setname(android::base::StringPrintf("->%s",
259 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700260 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100261 t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262
263 for(;;){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100264 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700265 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100266 t->serial, t->fd );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 break;
268 }
269 if(p->msg.command == A_SYNC){
270 if(p->msg.arg0 == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700271 D("%s: transport SYNC offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 put_apacket(p);
273 break;
274 } else {
275 if(p->msg.arg1 == t->sync_token) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700276 D("%s: transport SYNC online", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 active = 1;
278 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700279 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100280 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 }
282 }
283 } else {
284 if(active) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700285 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800286 t->write_to_remote(p, t);
287 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700288 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800289 }
290 }
291
292 put_apacket(p);
293 }
294
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700295 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296 kick_transport(t);
297 transport_unref(t);
298 return 0;
299}
300
Yabin Cuif4b99282015-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 Projectdd7bc332009-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 Projectdd7bc332009-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 Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700360 D( "device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-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 Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800381
Elliott Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800386}
387
Elliott Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800390
Elliott Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800393 if (tracker->update_needed > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800394 tracker->update_needed = 0;
395
Elliott Hughese67f1f82015-04-30 17:32:03 -0700396 std::string transports = list_transports(false);
397 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800398 }
399}
400
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401asocket*
402create_device_tracker(void)
403{
Elliott Hughesdc3b4592015-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 Projectdd7bc332009-03-03 19:32:55 -0800406
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700407 D( "device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-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 Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800424
Elliott Hughese67f1f82015-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 Projectdd7bc332009-03-03 19:32:55 -0800430 tracker = next;
431 }
432}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700433
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800434#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700435
436void update_transports() {
437 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800438}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700439
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440#endif // ADB_HOST
441
The Android Open Source Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700461 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700481 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-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 Projectdd7bc332009-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 Albert1792c232015-05-18 13:06:53 -0700504 if (m.action == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700505 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Projectdd7bc332009-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 Albertc7915a32015-05-18 16:46:31 -0700514 transport_list.remove(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800515 adb_mutex_unlock(&transport_lock);
516
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800517 if (t->product)
518 free(t->product);
519 if (t->serial)
520 free(t->serial);
Scott Andersone82c2db2012-05-25 14:10:02 -0700521 if (t->model)
522 free(t->model);
523 if (t->device)
524 free(t->device);
Scott Andersone109d262012-04-20 11:21:14 -0700525 if (t->devpath)
526 free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800527
Dan Albertc7915a32015-05-18 16:46:31 -0700528 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800529
530 update_transports();
531 return;
532 }
533
Mike Lockwood0927bf92009-08-08 12:37:44 -0400534 /* don't create transport threads for inaccessible devices */
Dan Albertdcd78a12015-05-18 16:43:57 -0700535 if (t->connection_state != kCsNoPerm) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800536 /* initial references are the two threads */
Mike Lockwood0927bf92009-08-08 12:37:44 -0400537 t->ref_count = 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800538
Dan Albertc7915a32015-05-18 16:46:31 -0700539 if (adb_socketpair(s)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400540 fatal_errno("cannot open transport socketpair");
541 }
542
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700543 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400544
545 t->transport_socket = s[0];
546 t->fd = s[1];
547
Mike Lockwood0927bf92009-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 Cuid6ab3c22015-08-31 11:50:24 -0700555 if (!adb_thread_create(write_transport_thread, t)) {
556 fatal_errno("cannot create write_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400557 }
558
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700559 if (!adb_thread_create(read_transport_thread, t)) {
560 fatal_errno("cannot create read_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400561 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800562 }
563
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700565 pending_list.remove(t);
566 transport_list.push_front(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800567 adb_mutex_unlock(&transport_lock);
568
The Android Open Source Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700579 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700598 D("transport: %s registered", transport->serial);
The Android Open Source Projectdd7bc332009-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 Cui7a3f8d62015-09-02 17:44:28 -0700609 D("transport: %s removed", transport->serial);
The Android Open Source Projectdd7bc332009-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 Cuif4b99282015-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 Lockwoodcbbe79a2010-05-24 10:44:35 -0400620 t->ref_count--;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400621 if (t->ref_count == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700622 D("transport: %s unref (kicking and closing)", t->serial);
Yabin Cuif4b99282015-08-27 12:03:11 -0700623 kick_transport_locked(t);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400624 t->close(t);
625 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100626 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700627 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400628 }
Yabin Cuif4b99282015-08-27 12:03:11 -0700629 adb_mutex_unlock(&transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800630}
631
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700632static int qual_match(const char *to_test,
Elliott Hughes09a45a12015-04-03 16:12:15 -0700633 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson2ca3e6b2012-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 Hughes09a45a12015-04-03 16:12:15 -0700651 if (sanitize_qual && !isalnum(ch))
Scott Anderson2ca3e6b2012-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 Projectdd7bc332009-03-03 19:32:55 -0800660
Elliott Hughes8d28e192015-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 Projectdd7bc332009-03-03 19:32:55 -0800664
Elliott Hughes8d28e192015-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 Projectdd7bc332009-03-03 19:32:55 -0800674
675 adb_mutex_lock(&transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700676 for (const auto& t : transport_list) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700677 if (t->connection_state == kCsNoPerm) {
Elliott Hughes1b708d32015-12-11 19:07:01 -0800678#if ADB_HOST
David Purselld2acbd12015-12-02 15:14:31 -0800679 *error_out = UsbNoPermissionsLongHelpText();
Elliott Hughes1b708d32015-12-11 19:07:01 -0800680#endif
Mike Lockwood37d31112009-08-08 13:53:16 -0400681 continue;
682 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400683
Elliott Hughes8d28e192015-10-07 14:55:10 -0700684 // Check for matching serial number.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800685 if (serial) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700686 if ((t->serial && !strcmp(serial, t->serial)) ||
687 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughes09a45a12015-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 Anderson2ca3e6b2012-05-30 18:11:27 -0700691 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700692 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700693 if (is_ambiguous) *is_ambiguous = true;
694 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700695 break;
696 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700698 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800699 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700700 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800701 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700702 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700703 if (is_ambiguous) *is_ambiguous = true;
704 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800705 break;
706 }
707 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700708 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800709 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700710 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700711 if (is_ambiguous) *is_ambiguous = true;
712 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713 break;
714 }
715 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700716 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800717 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700718 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700719 if (is_ambiguous) *is_ambiguous = true;
720 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 break;
722 }
723 result = t;
724 }
725 }
726 }
727 adb_mutex_unlock(&transport_lock);
728
Elliott Hughes8d28e192015-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 Goby77e8e582013-01-15 12:36:47 -0800740
Elliott Hughes8d28e192015-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 Projectdd7bc332009-03-03 19:32:55 -0800745 }
746
747 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700748 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749 }
750
751 return result;
752}
753
David Purselld2acbd12015-12-02 15:14:31 -0800754const std::string atransport::connection_state_name() const {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700755 switch (connection_state) {
David Purselld2acbd12015-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 Hughes1b708d32015-12-11 19:07:01 -0800761 case kCsNoPerm: return UsbNoPermissionsShortHelpText();
David Purselld2acbd12015-12-02 15:14:31 -0800762 case kCsSideload: return "sideload";
763 case kCsUnauthorized: return "unauthorized";
764 default: return "unknown";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800765 }
766}
767
Tamas Berghammer3d2904c2015-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 Pursell4e2fd362015-09-22 10:43:08 -0700781namespace {
David Pursell0955c662015-08-31 10:42:13 -0700782
David Pursell4e2fd362015-09-22 10:43:08 -0700783constexpr char kFeatureStringDelimiter = ',';
784
785} // namespace
Dan Albert1792c232015-05-18 13:06:53 -0700786
787const FeatureSet& supported_features() {
David Pursell4e2fd362015-09-22 10:43:08 -0700788 // Local static allocation to avoid global non-POD variables.
789 static const FeatureSet* features = new FeatureSet{
Todd Kennedy51c05ec2015-11-10 00:03:25 +0000790 kFeatureShell2,
791 kFeatureCmd
David Pursellbbe3d212015-09-25 08:37:13 -0700792 // Increment ADB_SERVER_VERSION whenever the feature list changes to
793 // make sure that the adb client and server features stay in sync
794 // (http://b/24370690).
David Pursell4e2fd362015-09-22 10:43:08 -0700795 };
796
797 return *features;
798}
799
800std::string FeatureSetToString(const FeatureSet& features) {
801 return android::base::Join(features, kFeatureStringDelimiter);
802}
803
804FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -0700805 if (features_string.empty()) {
806 return FeatureSet();
807 }
808
David Pursell4e2fd362015-09-22 10:43:08 -0700809 auto names = android::base::Split(features_string,
810 {kFeatureStringDelimiter});
811 return FeatureSet(names.begin(), names.end());
Dan Albert1792c232015-05-18 13:06:53 -0700812}
813
David Pursell70ef7b42015-09-30 13:35:42 -0700814bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
815 return feature_set.count(feature) > 0 &&
816 supported_features().count(feature) > 0;
817}
818
Dan Albert1792c232015-05-18 13:06:53 -0700819bool atransport::has_feature(const std::string& feature) const {
820 return features_.count(feature) > 0;
821}
822
David Pursell4e2fd362015-09-22 10:43:08 -0700823void atransport::SetFeatures(const std::string& features_string) {
824 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -0700825}
826
Yabin Cuib3298242015-08-28 15:09:44 -0700827void atransport::AddDisconnect(adisconnect* disconnect) {
828 disconnects_.push_back(disconnect);
829}
830
831void atransport::RemoveDisconnect(adisconnect* disconnect) {
832 disconnects_.remove(disconnect);
833}
834
835void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -0700836 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -0700837 disconnect->func(disconnect->opaque, this);
838 }
839 disconnects_.clear();
840}
841
Elliott Hughese67f1f82015-04-30 17:32:03 -0700842#if ADB_HOST
843
Dan Albertd99d9022015-05-06 16:48:52 -0700844static void append_transport_info(std::string* result, const char* key,
845 const char* value, bool sanitize) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700846 if (value == nullptr || *value == '\0') {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700847 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700848 }
849
Elliott Hughese67f1f82015-04-30 17:32:03 -0700850 *result += ' ';
851 *result += key;
852
853 for (const char* p = value; *p; ++p) {
854 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
855 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700856}
857
Dan Albertc7915a32015-05-18 16:46:31 -0700858static void append_transport(const atransport* t, std::string* result,
859 bool long_listing) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700860 const char* serial = t->serial;
Elliott Hughese67f1f82015-04-30 17:32:03 -0700861 if (!serial || !serial[0]) {
Dan Albertd99d9022015-05-06 16:48:52 -0700862 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -0700863 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700864
865 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700866 *result += serial;
867 *result += '\t';
868 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700869 } else {
David Purselld2acbd12015-12-02 15:14:31 -0800870 android::base::StringAppendF(result, "%-22s %s", serial,
871 t->connection_state_name().c_str());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700872
Elliott Hughese67f1f82015-04-30 17:32:03 -0700873 append_transport_info(result, "", t->devpath, false);
874 append_transport_info(result, "product:", t->product, false);
875 append_transport_info(result, "model:", t->model, true);
876 append_transport_info(result, "device:", t->device, false);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700877 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700878 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700879}
880
Elliott Hughese67f1f82015-04-30 17:32:03 -0700881std::string list_transports(bool long_listing) {
882 std::string result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800883 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700884 for (const auto& t : transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700885 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800886 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800887 adb_mutex_unlock(&transport_lock);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700888 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800889}
890
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800891/* hack for osx */
Dan Albertc7915a32015-05-18 16:46:31 -0700892void close_usb_devices() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800893 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700894 for (const auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700895 if (!t->kicked) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896 t->kicked = 1;
897 t->kick(t);
898 }
899 }
900 adb_mutex_unlock(&transport_lock);
901}
902#endif // ADB_HOST
903
Dan Albertc7915a32015-05-18 16:46:31 -0700904int register_socket_transport(int s, const char *serial, int port, int local) {
905 atransport* t = new atransport();
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100906
907 if (!serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700908 char buf[32];
909 snprintf(buf, sizeof(buf), "T-%p", t);
910 serial = buf;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100911 }
Dan Albertc7915a32015-05-18 16:46:31 -0700912
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700913 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700914 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700915 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700916 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800917 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700918
919 adb_mutex_lock(&transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700920 for (const auto& transport : pending_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700921 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700922 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700923 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700924 return -1;
925 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800926 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700927
Elliott Hughes65fe2512015-10-07 15:59:35 -0700928 for (const auto& transport : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700929 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700930 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700931 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700932 return -1;
933 }
934 }
935
Dan Albertc7915a32015-05-18 16:46:31 -0700936 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700937 t->serial = strdup(serial);
938 adb_mutex_unlock(&transport_lock);
939
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800940 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700941 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800942}
943
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400944#if ADB_HOST
Dan Albertc7915a32015-05-18 16:46:31 -0700945atransport *find_transport(const char *serial) {
946 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400947
948 adb_mutex_lock(&transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700949 for (auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700950 if (t->serial && strcmp(serial, t->serial) == 0) {
951 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400952 break;
953 }
Dan Albertc7915a32015-05-18 16:46:31 -0700954 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400955 adb_mutex_unlock(&transport_lock);
956
Dan Albertc7915a32015-05-18 16:46:31 -0700957 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400958}
959
Yabin Cuif4b99282015-08-27 12:03:11 -0700960void kick_all_tcp_devices() {
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400961 adb_mutex_lock(&transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700962 for (auto& t : transport_list) {
963 // TCP/IP devices have adb_port == 0.
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400964 if (t->type == kTransportLocal && t->adb_port == 0) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700965 // Kicking breaks the read_transport thread of this transport out of any read, then
966 // the read_transport thread will notify the main thread to make this transport
967 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -0700968 // Finally, this transport will be closed and freed in the main thread.
969 kick_transport_locked(t);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400970 }
Dan Albertc7915a32015-05-18 16:46:31 -0700971 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400972 adb_mutex_unlock(&transport_lock);
973}
974
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400975#endif
976
Dan Albertc7915a32015-05-18 16:46:31 -0700977void register_usb_transport(usb_handle* usb, const char* serial,
978 const char* devpath, unsigned writeable) {
979 atransport* t = new atransport();
980
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700981 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800982 serial ? serial : "");
Dan Albertdcd78a12015-05-18 16:43:57 -0700983 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800984 if(serial) {
985 t->serial = strdup(serial);
986 }
Dan Albertc7915a32015-05-18 16:46:31 -0700987
988 if (devpath) {
Scott Andersone109d262012-04-20 11:21:14 -0700989 t->devpath = strdup(devpath);
990 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700991
992 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700993 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700994 adb_mutex_unlock(&transport_lock);
995
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 register_transport(t);
997}
998
Dan Albertdcd78a12015-05-18 16:43:57 -0700999// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertc7915a32015-05-18 16:46:31 -07001000void unregister_usb_transport(usb_handle *usb) {
Mike Lockwood0927bf92009-08-08 12:37:44 -04001001 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -07001002 transport_list.remove_if([usb](atransport* t) {
1003 return t->usb == usb && t->connection_state == kCsNoPerm;
1004 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001005 adb_mutex_unlock(&transport_lock);
1006}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001007
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001008int check_header(apacket *p, atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001009{
1010 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001011 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 return -1;
1013 }
1014
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001015 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001016 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1017 << t->get_max_payload();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 return -1;
1019 }
1020
1021 return 0;
1022}
1023
1024int check_data(apacket *p)
1025{
1026 unsigned count, sum;
1027 unsigned char *x;
1028
1029 count = p->msg.data_length;
1030 x = p->data;
1031 sum = 0;
1032 while(count-- > 0) {
1033 sum += *x++;
1034 }
1035
1036 if(sum != p->msg.data_check) {
1037 return -1;
1038 } else {
1039 return 0;
1040 }
1041}