blob: e9e774fd98adc4514e15bf05f1c3d53b93c5e2c4 [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
Dan Albertecce5032015-05-18 16:46:31 -070029#include <list>
30
Yabin Cui4d64fd82015-08-27 12:03:11 -070031#include <base/logging.h>
Elliott Hughes88b4c852015-04-30 17:32:03 -070032#include <base/stringprintf.h>
Dan Albertbe8e54b2015-05-18 13:06:53 -070033#include <base/strings.h>
Elliott Hughes88b4c852015-04-30 17:32:03 -070034
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080035#include "adb.h"
Elliott Hughes88b4c852015-04-30 17:32:03 -070036#include "adb_utils.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080037
38static void transport_unref(atransport *t);
39
Dan Albertecce5032015-05-18 16:46:31 -070040static std::list<atransport*> transport_list;
41static std::list<atransport*> pending_list;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070042
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080043ADB_MUTEX_DEFINE( transport_lock );
44
Yabin Cui19bec5b2015-09-22 15:52:57 -070045static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +010046 unsigned command = p->msg.command;
47 int len = p->msg.data_length;
48 char cmd[9];
49 char arg0[12], arg1[12];
50 int n;
51
52 for (n = 0; n < 4; n++) {
53 int b = (command >> (n*8)) & 255;
54 if (b < 32 || b >= 127)
55 break;
56 cmd[n] = (char)b;
57 }
58 if (n == 4) {
59 cmd[4] = 0;
60 } else {
61 /* There is some non-ASCII name in the command, so dump
62 * the hexadecimal value instead */
63 snprintf(cmd, sizeof cmd, "%08x", command);
64 }
65
66 if (p->msg.arg0 < 256U)
67 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
68 else
69 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
70
71 if (p->msg.arg1 < 256U)
72 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
73 else
74 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
75
Yabin Cui19bec5b2015-09-22 15:52:57 -070076 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
77 name, func, cmd, arg0, arg1, len);
78 result += dump_hex(p->data, len);
79 return result;
David 'Digit' Turner58f59682011-01-06 14:11:07 +010080}
David 'Digit' Turner58f59682011-01-06 14:11:07 +010081
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080082static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +010083read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080084{
Yabin Cuia96dabf2015-07-30 19:58:10 -070085 char buff[8];
David 'Digit' Turner58f59682011-01-06 14:11:07 +010086 if (!name) {
87 snprintf(buff, sizeof buff, "fd=%d", fd);
88 name = buff;
89 }
Yabin Cuia96dabf2015-07-30 19:58:10 -070090 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
91 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080092 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -070093 int r = adb_read(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080094 if(r > 0) {
95 len -= r;
Yabin Cuia96dabf2015-07-30 19:58:10 -070096 p += r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080097 } else {
Yabin Cui815ad882015-09-02 17:44:28 -070098 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 -080099 return -1;
100 }
101 }
102
Yabin Cui19bec5b2015-09-22 15:52:57 -0700103 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800104 return 0;
105}
106
107static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100108write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800109{
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100110 char buff[8];
111 if (!name) {
112 snprintf(buff, sizeof buff, "fd=%d", fd);
113 name = buff;
114 }
Yabin Cui19bec5b2015-09-22 15:52:57 -0700115 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cuia96dabf2015-07-30 19:58:10 -0700116 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
117 int len = sizeof(apacket*);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800118 while(len > 0) {
Yabin Cuia96dabf2015-07-30 19:58:10 -0700119 int r = adb_write(fd, p, len);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800120 if(r > 0) {
121 len -= r;
122 p += r;
123 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700124 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 -0800125 return -1;
126 }
127 }
128 return 0;
129}
130
131static void transport_socket_events(int fd, unsigned events, void *_t)
132{
Dan Albertf30d73c2015-02-25 17:51:28 -0800133 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui815ad882015-09-02 17:44:28 -0700134 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800135 if(events & FDE_READ){
136 apacket *p = 0;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100137 if(read_packet(fd, t->serial, &p)){
Yabin Cui815ad882015-09-02 17:44:28 -0700138 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 -0800139 } else {
140 handle_packet(p, (atransport *) _t);
141 }
142 }
143}
144
145void send_packet(apacket *p, atransport *t)
146{
147 unsigned char *x;
148 unsigned sum;
149 unsigned count;
150
151 p->msg.magic = p->msg.command ^ 0xffffffff;
152
153 count = p->msg.data_length;
154 x = (unsigned char *) p->data;
155 sum = 0;
156 while(count-- > 0){
157 sum += *x++;
158 }
159 p->msg.data_check = sum;
160
161 print_packet("send", p);
162
163 if (t == NULL) {
Yabin Cui815ad882015-09-02 17:44:28 -0700164 D("Transport is null");
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700165 // Zap errno because print_packet() and other stuff have errno effect.
166 errno = 0;
167 fatal_errno("Transport is null");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800168 }
169
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100170 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800171 fatal_errno("cannot enqueue packet on transport socket");
172 }
173}
174
Yabin Cui4e222292015-08-31 11:50:24 -0700175// The transport is opened by transport_register_func before
176// the read_transport and write_transport threads are started.
177//
178// The read_transport thread issues a SYNC(1, token) message to let
179// the write_transport thread know to start things up. In the event
180// of transport IO failure, the read_transport thread will post a
181// SYNC(0,0) message to ensure shutdown.
182//
183// The transport will not actually be closed until both threads exit, but the threads
184// will kick the transport on their way out to disconnect the underlying device.
185//
186// read_transport thread reads data from a transport (representing a usb/tcp connection),
187// and makes the main thread call handle_packet().
188static void *read_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800189{
Dan Albertf30d73c2015-02-25 17:51:28 -0800190 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800191 apacket *p;
192
Yabin Cui4e222292015-08-31 11:50:24 -0700193 adb_thread_setname(android::base::StringPrintf("<-%s",
194 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700195 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100196 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800197 p = get_apacket();
198 p->msg.command = A_SYNC;
199 p->msg.arg0 = 1;
200 p->msg.arg1 = ++(t->sync_token);
201 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100202 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800203 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700204 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800205 goto oops;
206 }
207
Yabin Cui815ad882015-09-02 17:44:28 -0700208 D("%s: data pump started", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800209 for(;;) {
210 p = get_apacket();
211
212 if(t->read_from_remote(p, t) == 0){
Yabin Cui815ad882015-09-02 17:44:28 -0700213 D("%s: received remote packet, sending to transport",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100214 t->serial);
215 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800216 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700217 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800218 goto oops;
219 }
220 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700221 D("%s: remote read failed for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800222 put_apacket(p);
223 break;
224 }
225 }
226
Yabin Cui815ad882015-09-02 17:44:28 -0700227 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800228 p = get_apacket();
229 p->msg.command = A_SYNC;
230 p->msg.arg0 = 0;
231 p->msg.arg1 = 0;
232 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100233 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800234 put_apacket(p);
Yabin Cui815ad882015-09-02 17:44:28 -0700235 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800236 }
237
238oops:
Yabin Cui815ad882015-09-02 17:44:28 -0700239 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800240 kick_transport(t);
241 transport_unref(t);
242 return 0;
243}
244
Yabin Cui4e222292015-08-31 11:50:24 -0700245// write_transport thread gets packets sent by the main thread (through send_packet()),
246// and writes to a transport (representing a usb/tcp connection).
247static void *write_transport_thread(void *_t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800248{
Dan Albertf30d73c2015-02-25 17:51:28 -0800249 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800250 apacket *p;
251 int active = 0;
252
Yabin Cui4e222292015-08-31 11:50:24 -0700253 adb_thread_setname(android::base::StringPrintf("->%s",
254 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui815ad882015-09-02 17:44:28 -0700255 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100256 t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800257
258 for(;;){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100259 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700260 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100261 t->serial, t->fd );
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800262 break;
263 }
264 if(p->msg.command == A_SYNC){
265 if(p->msg.arg0 == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700266 D("%s: transport SYNC offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800267 put_apacket(p);
268 break;
269 } else {
270 if(p->msg.arg1 == t->sync_token) {
Yabin Cui815ad882015-09-02 17:44:28 -0700271 D("%s: transport SYNC online", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800272 active = 1;
273 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700274 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100275 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800276 }
277 }
278 } else {
279 if(active) {
Yabin Cui815ad882015-09-02 17:44:28 -0700280 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800281 t->write_to_remote(p, t);
282 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700283 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800284 }
285 }
286
287 put_apacket(p);
288 }
289
Yabin Cui815ad882015-09-02 17:44:28 -0700290 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800291 kick_transport(t);
292 transport_unref(t);
293 return 0;
294}
295
Yabin Cui4d64fd82015-08-27 12:03:11 -0700296static void kick_transport_locked(atransport* t) {
297 CHECK(t != nullptr);
298 if (!t->kicked) {
299 t->kicked = true;
300 t->kick(t);
301 }
302}
303
304void kick_transport(atransport* t) {
305 adb_mutex_lock(&transport_lock);
306 kick_transport_locked(t);
307 adb_mutex_unlock(&transport_lock);
308}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800309
310static int transport_registration_send = -1;
311static int transport_registration_recv = -1;
312static fdevent transport_registration_fde;
313
314
315#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800316
317/* this adds support required by the 'track-devices' service.
318 * this is used to send the content of "list_transport" to any
319 * number of client connections that want it through a single
320 * live TCP connection
321 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800322struct device_tracker {
323 asocket socket;
324 int update_needed;
325 device_tracker* next;
326};
327
328/* linked list of all device trackers */
329static device_tracker* device_tracker_list;
330
331static void
332device_tracker_remove( device_tracker* tracker )
333{
334 device_tracker** pnode = &device_tracker_list;
335 device_tracker* node = *pnode;
336
337 adb_mutex_lock( &transport_lock );
338 while (node) {
339 if (node == tracker) {
340 *pnode = node->next;
341 break;
342 }
343 pnode = &node->next;
344 node = *pnode;
345 }
346 adb_mutex_unlock( &transport_lock );
347}
348
349static void
350device_tracker_close( asocket* socket )
351{
352 device_tracker* tracker = (device_tracker*) socket;
353 asocket* peer = socket->peer;
354
Yabin Cui815ad882015-09-02 17:44:28 -0700355 D( "device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800356 if (peer) {
357 peer->peer = NULL;
358 peer->close(peer);
359 }
360 device_tracker_remove(tracker);
361 free(tracker);
362}
363
364static int
365device_tracker_enqueue( asocket* socket, apacket* p )
366{
367 /* you can't read from a device tracker, close immediately */
368 put_apacket(p);
369 device_tracker_close(socket);
370 return -1;
371}
372
Elliott Hughes88b4c852015-04-30 17:32:03 -0700373static int device_tracker_send(device_tracker* tracker, const std::string& string) {
374 apacket* p = get_apacket();
375 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800376
Elliott Hughes88b4c852015-04-30 17:32:03 -0700377 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
378 memcpy(&p->data[4], string.data(), string.size());
379 p->len = 4 + string.size();
380 return peer->enqueue(peer, p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800381}
382
Elliott Hughes88b4c852015-04-30 17:32:03 -0700383static void device_tracker_ready(asocket* socket) {
384 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800385
Elliott Hughes88b4c852015-04-30 17:32:03 -0700386 // We want to send the device list when the tracker connects
387 // for the first time, even if no update occurred.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800388 if (tracker->update_needed > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800389 tracker->update_needed = 0;
390
Elliott Hughes88b4c852015-04-30 17:32:03 -0700391 std::string transports = list_transports(false);
392 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800393 }
394}
395
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800396asocket*
397create_device_tracker(void)
398{
Elliott Hughesd0269c92015-04-21 19:39:52 -0700399 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
400 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800401
Yabin Cui815ad882015-09-02 17:44:28 -0700402 D( "device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800403
404 tracker->socket.enqueue = device_tracker_enqueue;
405 tracker->socket.ready = device_tracker_ready;
406 tracker->socket.close = device_tracker_close;
407 tracker->update_needed = 1;
408
409 tracker->next = device_tracker_list;
410 device_tracker_list = tracker;
411
412 return &tracker->socket;
413}
414
415
Elliott Hughes88b4c852015-04-30 17:32:03 -0700416// Call this function each time the transport list has changed.
417void update_transports() {
418 std::string transports = list_transports(false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800419
Elliott Hughes88b4c852015-04-30 17:32:03 -0700420 device_tracker* tracker = device_tracker_list;
421 while (tracker != nullptr) {
422 device_tracker* next = tracker->next;
423 // This may destroy the tracker if the connection is closed.
424 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800425 tracker = next;
426 }
427}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700428
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800429#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700430
431void update_transports() {
432 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800433}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700434
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800435#endif // ADB_HOST
436
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800437struct tmsg
438{
439 atransport *transport;
440 int action;
441};
442
443static int
444transport_read_action(int fd, struct tmsg* m)
445{
446 char *p = (char*)m;
447 int len = sizeof(*m);
448 int r;
449
450 while(len > 0) {
451 r = adb_read(fd, p, len);
452 if(r > 0) {
453 len -= r;
454 p += r;
455 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700456 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800457 return -1;
458 }
459 }
460 return 0;
461}
462
463static int
464transport_write_action(int fd, struct tmsg* m)
465{
466 char *p = (char*)m;
467 int len = sizeof(*m);
468 int r;
469
470 while(len > 0) {
471 r = adb_write(fd, p, len);
472 if(r > 0) {
473 len -= r;
474 p += r;
475 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700476 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800477 return -1;
478 }
479 }
480 return 0;
481}
482
483static void transport_registration_func(int _fd, unsigned ev, void *data)
484{
485 tmsg m;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800486 int s[2];
487 atransport *t;
488
489 if(!(ev & FDE_READ)) {
490 return;
491 }
492
493 if(transport_read_action(_fd, &m)) {
494 fatal_errno("cannot read transport registration socket");
495 }
496
497 t = m.transport;
498
Dan Albertbe8e54b2015-05-18 13:06:53 -0700499 if (m.action == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700500 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800501
502 /* IMPORTANT: the remove closes one half of the
503 ** socket pair. The close closes the other half.
504 */
505 fdevent_remove(&(t->transport_fde));
506 adb_close(t->fd);
507
508 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700509 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800510 adb_mutex_unlock(&transport_lock);
511
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800512 if (t->product)
513 free(t->product);
514 if (t->serial)
515 free(t->serial);
Scott Andersonfa020922012-05-25 14:10:02 -0700516 if (t->model)
517 free(t->model);
518 if (t->device)
519 free(t->device);
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700520 if (t->devpath)
521 free(t->devpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800522
Dan Albertecce5032015-05-18 16:46:31 -0700523 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800524
525 update_transports();
526 return;
527 }
528
Mike Lockwoode45583f2009-08-08 12:37:44 -0400529 /* don't create transport threads for inaccessible devices */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700530 if (t->connection_state != kCsNoPerm) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800531 /* initial references are the two threads */
Mike Lockwoode45583f2009-08-08 12:37:44 -0400532 t->ref_count = 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800533
Dan Albertecce5032015-05-18 16:46:31 -0700534 if (adb_socketpair(s)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400535 fatal_errno("cannot open transport socketpair");
536 }
537
Yabin Cui815ad882015-09-02 17:44:28 -0700538 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwoode45583f2009-08-08 12:37:44 -0400539
540 t->transport_socket = s[0];
541 t->fd = s[1];
542
Mike Lockwoode45583f2009-08-08 12:37:44 -0400543 fdevent_install(&(t->transport_fde),
544 t->transport_socket,
545 transport_socket_events,
546 t);
547
548 fdevent_set(&(t->transport_fde), FDE_READ);
549
Yabin Cui4e222292015-08-31 11:50:24 -0700550 if (!adb_thread_create(write_transport_thread, t)) {
551 fatal_errno("cannot create write_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400552 }
553
Yabin Cui4e222292015-08-31 11:50:24 -0700554 if (!adb_thread_create(read_transport_thread, t)) {
555 fatal_errno("cannot create read_transport thread");
Mike Lockwoode45583f2009-08-08 12:37:44 -0400556 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800557 }
558
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800559 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700560 pending_list.remove(t);
561 transport_list.push_front(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800562 adb_mutex_unlock(&transport_lock);
563
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800564 update_transports();
565}
566
567void init_transport_registration(void)
568{
569 int s[2];
570
571 if(adb_socketpair(s)){
572 fatal_errno("cannot open transport registration socketpair");
573 }
Yabin Cui815ad882015-09-02 17:44:28 -0700574 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800575
576 transport_registration_send = s[0];
577 transport_registration_recv = s[1];
578
579 fdevent_install(&transport_registration_fde,
580 transport_registration_recv,
581 transport_registration_func,
582 0);
583
584 fdevent_set(&transport_registration_fde, FDE_READ);
585}
586
587/* the fdevent select pump is single threaded */
588static void register_transport(atransport *transport)
589{
590 tmsg m;
591 m.transport = transport;
592 m.action = 1;
Yabin Cui815ad882015-09-02 17:44:28 -0700593 D("transport: %s registered", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800594 if(transport_write_action(transport_registration_send, &m)) {
595 fatal_errno("cannot write transport registration socket\n");
596 }
597}
598
599static void remove_transport(atransport *transport)
600{
601 tmsg m;
602 m.transport = transport;
603 m.action = 0;
Yabin Cui815ad882015-09-02 17:44:28 -0700604 D("transport: %s removed", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800605 if(transport_write_action(transport_registration_send, &m)) {
606 fatal_errno("cannot write transport registration socket\n");
607 }
608}
609
610
Yabin Cui4d64fd82015-08-27 12:03:11 -0700611static void transport_unref(atransport* t) {
612 CHECK(t != nullptr);
613 adb_mutex_lock(&transport_lock);
614 CHECK_GT(t->ref_count, 0u);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400615 t->ref_count--;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400616 if (t->ref_count == 0) {
Yabin Cui815ad882015-09-02 17:44:28 -0700617 D("transport: %s unref (kicking and closing)", t->serial);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700618 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400619 t->close(t);
620 remove_transport(t);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100621 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700622 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400623 }
Yabin Cui4d64fd82015-08-27 12:03:11 -0700624 adb_mutex_unlock(&transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800625}
626
Scott Anderson27042382012-05-30 18:11:27 -0700627static int qual_match(const char *to_test,
Elliott Hughesabfa7202015-04-03 16:12:15 -0700628 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson27042382012-05-30 18:11:27 -0700629{
630 if (!to_test || !*to_test)
631 /* Return true if both the qual and to_test are null strings. */
632 return !qual || !*qual;
633
634 if (!qual)
635 return 0;
636
637 if (prefix) {
638 while (*prefix) {
639 if (*prefix++ != *to_test++)
640 return 0;
641 }
642 }
643
644 while (*qual) {
645 char ch = *qual++;
Elliott Hughesabfa7202015-04-03 16:12:15 -0700646 if (sanitize_qual && !isalnum(ch))
Scott Anderson27042382012-05-30 18:11:27 -0700647 ch = '_';
648 if (ch != *to_test++)
649 return 0;
650 }
651
652 /* Everything matched so far. Return true if *to_test is a NUL. */
653 return !*to_test;
654}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800655
Elliott Hughes67943d12015-10-07 14:55:10 -0700656atransport* acquire_one_transport(TransportType type, const char* serial,
657 bool* is_ambiguous, std::string* error_out) {
658 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659
Elliott Hughes67943d12015-10-07 14:55:10 -0700660 if (serial) {
661 *error_out = android::base::StringPrintf("device '%s' not found", serial);
662 } else if (type == kTransportLocal) {
663 *error_out = "no emulators found";
664 } else if (type == kTransportAny) {
665 *error_out = "no devices/emulators found";
666 } else {
667 *error_out = "no devices found";
668 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800669
670 adb_mutex_lock(&transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -0700671 for (const auto& t : transport_list) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700672 if (t->connection_state == kCsNoPerm) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700673 *error_out = "insufficient permissions for device";
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400674 continue;
675 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400676
Elliott Hughes67943d12015-10-07 14:55:10 -0700677 // Check for matching serial number.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800678 if (serial) {
Scott Anderson27042382012-05-30 18:11:27 -0700679 if ((t->serial && !strcmp(serial, t->serial)) ||
680 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughesabfa7202015-04-03 16:12:15 -0700681 qual_match(serial, "product:", t->product, false) ||
682 qual_match(serial, "model:", t->model, true) ||
683 qual_match(serial, "device:", t->device, false)) {
Scott Anderson27042382012-05-30 18:11:27 -0700684 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700685 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700686 if (is_ambiguous) *is_ambiguous = true;
687 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -0700688 break;
689 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800690 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700691 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800692 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700693 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800694 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700695 *error_out = "more than one device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700696 if (is_ambiguous) *is_ambiguous = true;
697 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800698 break;
699 }
700 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700701 } else if (type == kTransportLocal && t->type == kTransportLocal) {
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 emulator";
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 == kTransportAny) {
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 device/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;
717 }
718 }
719 }
720 adb_mutex_unlock(&transport_lock);
721
Elliott Hughes67943d12015-10-07 14:55:10 -0700722 // Don't return unauthorized devices; the caller can't do anything with them.
723 if (result && result->connection_state == kCsUnauthorized) {
724 *error_out = "device unauthorized.\n";
725 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
726 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
727 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
728 *error_out += "\n";
729 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
730 *error_out += "Otherwise check for a confirmation dialog on your device.";
731 result = nullptr;
732 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700733
Elliott Hughes67943d12015-10-07 14:55:10 -0700734 // Don't return offline devices; the caller can't do anything with them.
735 if (result && result->connection_state == kCsOffline) {
736 *error_out = "device offline";
737 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800738 }
739
740 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700741 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800742 }
743
744 return result;
745}
746
Elliott Hughes88b4c852015-04-30 17:32:03 -0700747const char* atransport::connection_state_name() const {
748 switch (connection_state) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700749 case kCsOffline: return "offline";
750 case kCsBootloader: return "bootloader";
751 case kCsDevice: return "device";
752 case kCsHost: return "host";
753 case kCsRecovery: return "recovery";
754 case kCsNoPerm: return "no permissions";
755 case kCsSideload: return "sideload";
756 case kCsUnauthorized: return "unauthorized";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800757 default: return "unknown";
758 }
759}
760
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100761void atransport::update_version(int version, size_t payload) {
762 protocol_version = std::min(version, A_VERSION);
763 max_payload = std::min(payload, MAX_PAYLOAD);
764}
765
766int atransport::get_protocol_version() const {
767 return protocol_version;
768}
769
770size_t atransport::get_max_payload() const {
771 return max_payload;
772}
773
David Pursella07dbad2015-09-22 10:43:08 -0700774namespace {
David Pursell8da19a42015-08-31 10:42:13 -0700775
David Pursella07dbad2015-09-22 10:43:08 -0700776constexpr char kFeatureStringDelimiter = ',';
777
778} // namespace
Dan Albertbe8e54b2015-05-18 13:06:53 -0700779
780const FeatureSet& supported_features() {
David Pursella07dbad2015-09-22 10:43:08 -0700781 // Local static allocation to avoid global non-POD variables.
782 static const FeatureSet* features = new FeatureSet{
783 kFeatureShell2
David Pursell6d5fad32015-09-25 08:37:13 -0700784 // Increment ADB_SERVER_VERSION whenever the feature list changes to
785 // make sure that the adb client and server features stay in sync
786 // (http://b/24370690).
David Pursella07dbad2015-09-22 10:43:08 -0700787 };
788
789 return *features;
790}
791
792std::string FeatureSetToString(const FeatureSet& features) {
793 return android::base::Join(features, kFeatureStringDelimiter);
794}
795
796FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -0700797 if (features_string.empty()) {
798 return FeatureSet();
799 }
800
David Pursella07dbad2015-09-22 10:43:08 -0700801 auto names = android::base::Split(features_string,
802 {kFeatureStringDelimiter});
803 return FeatureSet(names.begin(), names.end());
Dan Albertbe8e54b2015-05-18 13:06:53 -0700804}
805
David Pursell22fc5e92015-09-30 13:35:42 -0700806bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
807 return feature_set.count(feature) > 0 &&
808 supported_features().count(feature) > 0;
809}
810
Dan Albertbe8e54b2015-05-18 13:06:53 -0700811bool atransport::has_feature(const std::string& feature) const {
812 return features_.count(feature) > 0;
813}
814
David Pursella07dbad2015-09-22 10:43:08 -0700815void atransport::SetFeatures(const std::string& features_string) {
816 features_ = StringToFeatureSet(features_string);
Dan Albertbe8e54b2015-05-18 13:06:53 -0700817}
818
Yabin Cui2d4c1982015-08-28 15:09:44 -0700819void atransport::AddDisconnect(adisconnect* disconnect) {
820 disconnects_.push_back(disconnect);
821}
822
823void atransport::RemoveDisconnect(adisconnect* disconnect) {
824 disconnects_.remove(disconnect);
825}
826
827void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -0700828 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -0700829 disconnect->func(disconnect->opaque, this);
830 }
831 disconnects_.clear();
832}
833
Elliott Hughes88b4c852015-04-30 17:32:03 -0700834#if ADB_HOST
835
Dan Alberta8c34142015-05-06 16:48:52 -0700836static void append_transport_info(std::string* result, const char* key,
837 const char* value, bool sanitize) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700838 if (value == nullptr || *value == '\0') {
Scott Anderson27042382012-05-30 18:11:27 -0700839 return;
Scott Anderson27042382012-05-30 18:11:27 -0700840 }
841
Elliott Hughes88b4c852015-04-30 17:32:03 -0700842 *result += ' ';
843 *result += key;
844
845 for (const char* p = value; *p; ++p) {
846 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
847 }
Scott Anderson27042382012-05-30 18:11:27 -0700848}
849
Dan Albertecce5032015-05-18 16:46:31 -0700850static void append_transport(const atransport* t, std::string* result,
851 bool long_listing) {
Scott Anderson27042382012-05-30 18:11:27 -0700852 const char* serial = t->serial;
Elliott Hughes88b4c852015-04-30 17:32:03 -0700853 if (!serial || !serial[0]) {
Dan Alberta8c34142015-05-06 16:48:52 -0700854 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -0700855 }
Scott Anderson27042382012-05-30 18:11:27 -0700856
857 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700858 *result += serial;
859 *result += '\t';
860 *result += t->connection_state_name();
Scott Anderson27042382012-05-30 18:11:27 -0700861 } else {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700862 android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
Scott Anderson27042382012-05-30 18:11:27 -0700863
Elliott Hughes88b4c852015-04-30 17:32:03 -0700864 append_transport_info(result, "", t->devpath, false);
865 append_transport_info(result, "product:", t->product, false);
866 append_transport_info(result, "model:", t->model, true);
867 append_transport_info(result, "device:", t->device, false);
Scott Anderson27042382012-05-30 18:11:27 -0700868 }
Elliott Hughes88b4c852015-04-30 17:32:03 -0700869 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -0700870}
871
Elliott Hughes88b4c852015-04-30 17:32:03 -0700872std::string list_transports(bool long_listing) {
873 std::string result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800874 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700875 for (const auto& t : transport_list) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700876 append_transport(t, &result, long_listing);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800877 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800878 adb_mutex_unlock(&transport_lock);
Elliott Hughes88b4c852015-04-30 17:32:03 -0700879 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800880}
881
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800882/* hack for osx */
Dan Albertecce5032015-05-18 16:46:31 -0700883void close_usb_devices() {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800884 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700885 for (const auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700886 if (!t->kicked) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800887 t->kicked = 1;
888 t->kick(t);
889 }
890 }
891 adb_mutex_unlock(&transport_lock);
892}
893#endif // ADB_HOST
894
Dan Albertecce5032015-05-18 16:46:31 -0700895int register_socket_transport(int s, const char *serial, int port, int local) {
896 atransport* t = new atransport();
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100897
898 if (!serial) {
Dan Albertecce5032015-05-18 16:46:31 -0700899 char buf[32];
900 snprintf(buf, sizeof(buf), "T-%p", t);
901 serial = buf;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100902 }
Dan Albertecce5032015-05-18 16:46:31 -0700903
Yabin Cui815ad882015-09-02 17:44:28 -0700904 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700905 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -0700906 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700907 return -1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800908 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700909
910 adb_mutex_lock(&transport_lock);
Elliott Hughes85952832015-10-07 15:59:35 -0700911 for (const auto& transport : pending_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700912 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700913 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700914 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700915 return -1;
916 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800917 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700918
Elliott Hughes85952832015-10-07 15:59:35 -0700919 for (const auto& transport : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700920 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700921 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700922 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700923 return -1;
924 }
925 }
926
Dan Albertecce5032015-05-18 16:46:31 -0700927 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700928 t->serial = strdup(serial);
929 adb_mutex_unlock(&transport_lock);
930
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800931 register_transport(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700932 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800933}
934
Mike Lockwood81ffe172009-10-11 23:04:18 -0400935#if ADB_HOST
Dan Albertecce5032015-05-18 16:46:31 -0700936atransport *find_transport(const char *serial) {
937 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400938
939 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700940 for (auto& t : transport_list) {
Dan Albertecce5032015-05-18 16:46:31 -0700941 if (t->serial && strcmp(serial, t->serial) == 0) {
942 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400943 break;
944 }
Dan Albertecce5032015-05-18 16:46:31 -0700945 }
Mike Lockwood81ffe172009-10-11 23:04:18 -0400946 adb_mutex_unlock(&transport_lock);
947
Dan Albertecce5032015-05-18 16:46:31 -0700948 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400949}
950
Yabin Cui4d64fd82015-08-27 12:03:11 -0700951void kick_all_tcp_devices() {
Mike Lockwood81ffe172009-10-11 23:04:18 -0400952 adb_mutex_lock(&transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -0700953 for (auto& t : transport_list) {
954 // TCP/IP devices have adb_port == 0.
Mike Lockwood01c2c302010-05-24 10:44:35 -0400955 if (t->type == kTransportLocal && t->adb_port == 0) {
Yabin Cui4e222292015-08-31 11:50:24 -0700956 // Kicking breaks the read_transport thread of this transport out of any read, then
957 // the read_transport thread will notify the main thread to make this transport
958 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -0700959 // Finally, this transport will be closed and freed in the main thread.
960 kick_transport_locked(t);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400961 }
Dan Albertecce5032015-05-18 16:46:31 -0700962 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400963 adb_mutex_unlock(&transport_lock);
964}
965
Mike Lockwood81ffe172009-10-11 23:04:18 -0400966#endif
967
Dan Albertecce5032015-05-18 16:46:31 -0700968void register_usb_transport(usb_handle* usb, const char* serial,
969 const char* devpath, unsigned writeable) {
970 atransport* t = new atransport();
971
Yabin Cui815ad882015-09-02 17:44:28 -0700972 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800973 serial ? serial : "");
Dan Albert9a50f4c2015-05-18 16:43:57 -0700974 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800975 if(serial) {
976 t->serial = strdup(serial);
977 }
Dan Albertecce5032015-05-18 16:46:31 -0700978
979 if (devpath) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700980 t->devpath = strdup(devpath);
981 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700982
983 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700984 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700985 adb_mutex_unlock(&transport_lock);
986
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800987 register_transport(t);
988}
989
Dan Albert9a50f4c2015-05-18 16:43:57 -0700990// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertecce5032015-05-18 16:46:31 -0700991void unregister_usb_transport(usb_handle *usb) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400992 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700993 transport_list.remove_if([usb](atransport* t) {
994 return t->usb == usb && t->connection_state == kCsNoPerm;
995 });
Mike Lockwoode45583f2009-08-08 12:37:44 -0400996 adb_mutex_unlock(&transport_lock);
997}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800998
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100999int check_header(apacket *p, atransport *t)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001000{
1001 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001002 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001003 return -1;
1004 }
1005
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001006 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cui19bec5b2015-09-22 15:52:57 -07001007 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1008 << t->get_max_payload();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001009 return -1;
1010 }
1011
1012 return 0;
1013}
1014
1015int check_data(apacket *p)
1016{
1017 unsigned count, sum;
1018 unsigned char *x;
1019
1020 count = p->msg.data_length;
1021 x = p->data;
1022 sum = 0;
1023 while(count-- > 0) {
1024 sum += *x++;
1025 }
1026
1027 if(sum != p->msg.data_check) {
1028 return -1;
1029 } else {
1030 return 0;
1031 }
1032}