blob: 4a273c482c7d8d93f901414c3ea2aeff2c4faf1c [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
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_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
Dan Albertc7915a32015-05-18 16:46:31 -070029#include <list>
30
Elliott Hughese67f1f82015-04-30 17:32:03 -070031#include <base/stringprintf.h>
32
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080033#include "adb.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070034#include "adb_utils.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080035
36static void transport_unref(atransport *t);
37
Dan Albertc7915a32015-05-18 16:46:31 -070038static std::list<atransport*> transport_list;
39static std::list<atransport*> pending_list;
Benoit Goby1c45ee92013-03-29 18:22:36 -070040
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041ADB_MUTEX_DEFINE( transport_lock );
42
Dan Albert055f1aa2015-02-20 17:24:58 -080043void kick_transport(atransport* t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044{
45 if (t && !t->kicked)
46 {
47 int kicked;
48
49 adb_mutex_lock(&transport_lock);
50 kicked = t->kicked;
51 if (!kicked)
52 t->kicked = 1;
53 adb_mutex_unlock(&transport_lock);
54
55 if (!kicked)
56 t->kick(t);
57 }
58}
59
Dan Albert055f1aa2015-02-20 17:24:58 -080060// Each atransport contains a list of adisconnects (t->disconnects).
61// An adisconnect contains a link to the next/prev adisconnect, a function
62// pointer to a disconnect callback which takes a void* piece of user data and
63// the atransport, and some user data for the callback (helpfully named
64// "opaque").
65//
66// The list is circular. New items are added to the entry member of the list
67// (t->disconnects) by add_transport_disconnect.
68//
69// run_transport_disconnects invokes each function in the list.
70//
71// Gotchas:
72// * run_transport_disconnects assumes that t->disconnects is non-null, so
73// this can't be run on a zeroed atransport.
74// * The callbacks in this list are not removed when called, and this function
75// is not guarded against running more than once. As such, ensure that this
76// function is not called multiple times on the same atransport.
77// TODO(danalbert): Just fix this so that it is guarded once you have tests.
78void run_transport_disconnects(atransport* t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080079{
80 adisconnect* dis = t->disconnects.next;
81
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010082 D("%s: run_transport_disconnects\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080083 while (dis != &t->disconnects) {
84 adisconnect* next = dis->next;
85 dis->func( dis->opaque, t );
86 dis = next;
87 }
88}
89
Elliott Hughese67f1f82015-04-30 17:32:03 -070090static void dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010091 unsigned command = p->msg.command;
92 int len = p->msg.data_length;
93 char cmd[9];
94 char arg0[12], arg1[12];
95 int n;
96
97 for (n = 0; n < 4; n++) {
98 int b = (command >> (n*8)) & 255;
99 if (b < 32 || b >= 127)
100 break;
101 cmd[n] = (char)b;
102 }
103 if (n == 4) {
104 cmd[4] = 0;
105 } else {
106 /* There is some non-ASCII name in the command, so dump
107 * the hexadecimal value instead */
108 snprintf(cmd, sizeof cmd, "%08x", command);
109 }
110
111 if (p->msg.arg0 < 256U)
112 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
113 else
114 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
115
116 if (p->msg.arg1 < 256U)
117 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
118 else
119 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
120
121 D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
122 name, func, cmd, arg0, arg1, len);
123 dump_hex(p->data, len);
124}
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100125
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800126static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100127read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800128{
Yabin Cui62641292015-07-30 19:58:10 -0700129 char buff[8];
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100130 if (!name) {
131 snprintf(buff, sizeof buff, "fd=%d", fd);
132 name = buff;
133 }
Yabin Cui62641292015-07-30 19:58:10 -0700134 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
135 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800136 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700137 int r = adb_read(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800138 if(r > 0) {
139 len -= r;
Yabin Cui62641292015-07-30 19:58:10 -0700140 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800141 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100142 D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800143 if((r < 0) && (errno == EINTR)) continue;
144 return -1;
145 }
146 }
147
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100148 if (ADB_TRACING) {
149 dump_packet(name, "from remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800151 return 0;
152}
153
154static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100155write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156{
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100157 char buff[8];
158 if (!name) {
159 snprintf(buff, sizeof buff, "fd=%d", fd);
160 name = buff;
161 }
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100162 if (ADB_TRACING) {
163 dump_packet(name, "to remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164 }
Yabin Cui62641292015-07-30 19:58:10 -0700165 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
166 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700168 int r = adb_write(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 if(r > 0) {
170 len -= r;
171 p += r;
172 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100173 D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800174 if((r < 0) && (errno == EINTR)) continue;
175 return -1;
176 }
177 }
178 return 0;
179}
180
181static void transport_socket_events(int fd, unsigned events, void *_t)
182{
Dan Albertbac34742015-02-25 17:51:28 -0800183 atransport *t = reinterpret_cast<atransport*>(_t);
JP Abgrall408fa572011-03-16 15:57:42 -0700184 D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800185 if(events & FDE_READ){
186 apacket *p = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100187 if(read_packet(fd, t->serial, &p)){
188 D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189 } else {
190 handle_packet(p, (atransport *) _t);
191 }
192 }
193}
194
195void send_packet(apacket *p, atransport *t)
196{
197 unsigned char *x;
198 unsigned sum;
199 unsigned count;
200
201 p->msg.magic = p->msg.command ^ 0xffffffff;
202
203 count = p->msg.data_length;
204 x = (unsigned char *) p->data;
205 sum = 0;
206 while(count-- > 0){
207 sum += *x++;
208 }
209 p->msg.data_check = sum;
210
211 print_packet("send", p);
212
213 if (t == NULL) {
JP Abgrall0e7c4272011-02-23 18:44:39 -0800214 D("Transport is null \n");
JP Abgrall408fa572011-03-16 15:57:42 -0700215 // Zap errno because print_packet() and other stuff have errno effect.
216 errno = 0;
217 fatal_errno("Transport is null");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800218 }
219
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100220 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 fatal_errno("cannot enqueue packet on transport socket");
222 }
223}
224
225/* The transport is opened by transport_register_func before
226** the input and output threads are started.
227**
228** The output thread issues a SYNC(1, token) message to let
229** the input thread know to start things up. In the event
230** of transport IO failure, the output thread will post a
231** SYNC(0,0) message to ensure shutdown.
232**
233** The transport will not actually be closed until both
234** threads exit, but the input thread will kick the transport
235** on its way out to disconnect the underlying device.
236*/
237
238static void *output_thread(void *_t)
239{
Dan Albertbac34742015-02-25 17:51:28 -0800240 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 apacket *p;
242
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100243 D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
244 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 p = get_apacket();
246 p->msg.command = A_SYNC;
247 p->msg.arg0 = 1;
248 p->msg.arg1 = ++(t->sync_token);
249 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100250 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800251 put_apacket(p);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100252 D("%s: failed to write SYNC packet\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 goto oops;
254 }
255
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100256 D("%s: data pump started\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257 for(;;) {
258 p = get_apacket();
259
260 if(t->read_from_remote(p, t) == 0){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100261 D("%s: received remote packet, sending to transport\n",
262 t->serial);
263 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800264 put_apacket(p);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100265 D("%s: failed to write apacket to transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800266 goto oops;
267 }
268 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100269 D("%s: remote read failed for transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800270 put_apacket(p);
271 break;
272 }
273 }
274
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100275 D("%s: SYNC offline for transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800276 p = get_apacket();
277 p->msg.command = A_SYNC;
278 p->msg.arg0 = 0;
279 p->msg.arg1 = 0;
280 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100281 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 put_apacket(p);
Spencer Low8d8126a2015-07-21 02:06:26 -0700283 D("%s: failed to write SYNC apacket to transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284 }
285
286oops:
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100287 D("%s: transport output thread is exiting\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 kick_transport(t);
289 transport_unref(t);
290 return 0;
291}
292
293static void *input_thread(void *_t)
294{
Dan Albertbac34742015-02-25 17:51:28 -0800295 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296 apacket *p;
297 int active = 0;
298
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100299 D("%s: starting transport input thread, reading from fd %d\n",
300 t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301
302 for(;;){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100303 if(read_packet(t->fd, t->serial, &p)) {
304 D("%s: failed to read apacket from transport on fd %d\n",
305 t->serial, t->fd );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800306 break;
307 }
308 if(p->msg.command == A_SYNC){
309 if(p->msg.arg0 == 0) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100310 D("%s: transport SYNC offline\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800311 put_apacket(p);
312 break;
313 } else {
314 if(p->msg.arg1 == t->sync_token) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100315 D("%s: transport SYNC online\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800316 active = 1;
317 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100318 D("%s: transport ignoring SYNC %d != %d\n",
319 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320 }
321 }
322 } else {
323 if(active) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100324 D("%s: transport got packet, sending to remote\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325 t->write_to_remote(p, t);
326 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100327 D("%s: transport ignoring packet while offline\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800328 }
329 }
330
331 put_apacket(p);
332 }
333
334 // this is necessary to avoid a race condition that occured when a transport closes
335 // while a client socket is still active.
336 close_all_sockets(t);
337
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100338 D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339 kick_transport(t);
340 transport_unref(t);
341 return 0;
342}
343
344
345static int transport_registration_send = -1;
346static int transport_registration_recv = -1;
347static fdevent transport_registration_fde;
348
349
350#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800351
352/* this adds support required by the 'track-devices' service.
353 * this is used to send the content of "list_transport" to any
354 * number of client connections that want it through a single
355 * live TCP connection
356 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800357struct device_tracker {
358 asocket socket;
359 int update_needed;
360 device_tracker* next;
361};
362
363/* linked list of all device trackers */
364static device_tracker* device_tracker_list;
365
366static void
367device_tracker_remove( device_tracker* tracker )
368{
369 device_tracker** pnode = &device_tracker_list;
370 device_tracker* node = *pnode;
371
372 adb_mutex_lock( &transport_lock );
373 while (node) {
374 if (node == tracker) {
375 *pnode = node->next;
376 break;
377 }
378 pnode = &node->next;
379 node = *pnode;
380 }
381 adb_mutex_unlock( &transport_lock );
382}
383
384static void
385device_tracker_close( asocket* socket )
386{
387 device_tracker* tracker = (device_tracker*) socket;
388 asocket* peer = socket->peer;
389
390 D( "device tracker %p removed\n", tracker);
391 if (peer) {
392 peer->peer = NULL;
393 peer->close(peer);
394 }
395 device_tracker_remove(tracker);
396 free(tracker);
397}
398
399static int
400device_tracker_enqueue( asocket* socket, apacket* p )
401{
402 /* you can't read from a device tracker, close immediately */
403 put_apacket(p);
404 device_tracker_close(socket);
405 return -1;
406}
407
Elliott Hughese67f1f82015-04-30 17:32:03 -0700408static int device_tracker_send(device_tracker* tracker, const std::string& string) {
409 apacket* p = get_apacket();
410 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411
Elliott Hughese67f1f82015-04-30 17:32:03 -0700412 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
413 memcpy(&p->data[4], string.data(), string.size());
414 p->len = 4 + string.size();
415 return peer->enqueue(peer, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416}
417
Elliott Hughese67f1f82015-04-30 17:32:03 -0700418static void device_tracker_ready(asocket* socket) {
419 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800420
Elliott Hughese67f1f82015-04-30 17:32:03 -0700421 // We want to send the device list when the tracker connects
422 // for the first time, even if no update occurred.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423 if (tracker->update_needed > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800424 tracker->update_needed = 0;
425
Elliott Hughese67f1f82015-04-30 17:32:03 -0700426 std::string transports = list_transports(false);
427 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800428 }
429}
430
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431asocket*
432create_device_tracker(void)
433{
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700434 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
435 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436
437 D( "device tracker %p created\n", tracker);
438
439 tracker->socket.enqueue = device_tracker_enqueue;
440 tracker->socket.ready = device_tracker_ready;
441 tracker->socket.close = device_tracker_close;
442 tracker->update_needed = 1;
443
444 tracker->next = device_tracker_list;
445 device_tracker_list = tracker;
446
447 return &tracker->socket;
448}
449
450
Elliott Hughese67f1f82015-04-30 17:32:03 -0700451// Call this function each time the transport list has changed.
452void update_transports() {
453 std::string transports = list_transports(false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800454
Elliott Hughese67f1f82015-04-30 17:32:03 -0700455 device_tracker* tracker = device_tracker_list;
456 while (tracker != nullptr) {
457 device_tracker* next = tracker->next;
458 // This may destroy the tracker if the connection is closed.
459 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800460 tracker = next;
461 }
462}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700463
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800464#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700465
466void update_transports() {
467 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800468}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700469
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800470#endif // ADB_HOST
471
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800472struct tmsg
473{
474 atransport *transport;
475 int action;
476};
477
478static int
479transport_read_action(int fd, struct tmsg* m)
480{
481 char *p = (char*)m;
482 int len = sizeof(*m);
483 int r;
484
485 while(len > 0) {
486 r = adb_read(fd, p, len);
487 if(r > 0) {
488 len -= r;
489 p += r;
490 } else {
491 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100492 D("transport_read_action: on fd %d, error %d: %s\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800493 fd, errno, strerror(errno));
494 return -1;
495 }
496 }
497 return 0;
498}
499
500static int
501transport_write_action(int fd, struct tmsg* m)
502{
503 char *p = (char*)m;
504 int len = sizeof(*m);
505 int r;
506
507 while(len > 0) {
508 r = adb_write(fd, p, len);
509 if(r > 0) {
510 len -= r;
511 p += r;
512 } else {
513 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100514 D("transport_write_action: on fd %d, error %d: %s\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800515 fd, errno, strerror(errno));
516 return -1;
517 }
518 }
519 return 0;
520}
521
522static void transport_registration_func(int _fd, unsigned ev, void *data)
523{
524 tmsg m;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800525 int s[2];
526 atransport *t;
527
528 if(!(ev & FDE_READ)) {
529 return;
530 }
531
532 if(transport_read_action(_fd, &m)) {
533 fatal_errno("cannot read transport registration socket");
534 }
535
536 t = m.transport;
537
538 if(m.action == 0){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100539 D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800540
541 /* IMPORTANT: the remove closes one half of the
542 ** socket pair. The close closes the other half.
543 */
544 fdevent_remove(&(t->transport_fde));
545 adb_close(t->fd);
546
547 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700548 transport_list.remove(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549 adb_mutex_unlock(&transport_lock);
550
551 run_transport_disconnects(t);
552
553 if (t->product)
554 free(t->product);
555 if (t->serial)
556 free(t->serial);
Scott Andersone82c2db2012-05-25 14:10:02 -0700557 if (t->model)
558 free(t->model);
559 if (t->device)
560 free(t->device);
Scott Andersone109d262012-04-20 11:21:14 -0700561 if (t->devpath)
562 free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800563
Dan Albertc7915a32015-05-18 16:46:31 -0700564 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565
566 update_transports();
567 return;
568 }
569
Mike Lockwood0927bf92009-08-08 12:37:44 -0400570 /* don't create transport threads for inaccessible devices */
Dan Albertdcd78a12015-05-18 16:43:57 -0700571 if (t->connection_state != kCsNoPerm) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800572 /* initial references are the two threads */
Mike Lockwood0927bf92009-08-08 12:37:44 -0400573 t->ref_count = 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574
Dan Albertc7915a32015-05-18 16:46:31 -0700575 if (adb_socketpair(s)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400576 fatal_errno("cannot open transport socketpair");
577 }
578
Spencer Low8d8126a2015-07-21 02:06:26 -0700579 D("transport: %s socketpair: (%d,%d) starting\n", t->serial, s[0], s[1]);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400580
581 t->transport_socket = s[0];
582 t->fd = s[1];
583
Mike Lockwood0927bf92009-08-08 12:37:44 -0400584 fdevent_install(&(t->transport_fde),
585 t->transport_socket,
586 transport_socket_events,
587 t);
588
589 fdevent_set(&(t->transport_fde), FDE_READ);
590
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700591 if (!adb_thread_create(input_thread, t)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400592 fatal_errno("cannot create input thread");
593 }
594
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700595 if (!adb_thread_create(output_thread, t)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400596 fatal_errno("cannot create output thread");
597 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800598 }
599
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800600 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700601 pending_list.remove(t);
602 transport_list.push_front(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800603 adb_mutex_unlock(&transport_lock);
604
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800605 t->disconnects.next = t->disconnects.prev = &t->disconnects;
606
607 update_transports();
608}
609
610void init_transport_registration(void)
611{
612 int s[2];
613
614 if(adb_socketpair(s)){
615 fatal_errno("cannot open transport registration socketpair");
616 }
Spencer Low8d8126a2015-07-21 02:06:26 -0700617 D("socketpair: (%d,%d)\n", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800618
619 transport_registration_send = s[0];
620 transport_registration_recv = s[1];
621
622 fdevent_install(&transport_registration_fde,
623 transport_registration_recv,
624 transport_registration_func,
625 0);
626
627 fdevent_set(&transport_registration_fde, FDE_READ);
628}
629
630/* the fdevent select pump is single threaded */
631static void register_transport(atransport *transport)
632{
633 tmsg m;
634 m.transport = transport;
635 m.action = 1;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100636 D("transport: %s registered\n", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637 if(transport_write_action(transport_registration_send, &m)) {
638 fatal_errno("cannot write transport registration socket\n");
639 }
640}
641
642static void remove_transport(atransport *transport)
643{
644 tmsg m;
645 m.transport = transport;
646 m.action = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100647 D("transport: %s removed\n", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800648 if(transport_write_action(transport_registration_send, &m)) {
649 fatal_errno("cannot write transport registration socket\n");
650 }
651}
652
653
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400654static void transport_unref_locked(atransport *t)
655{
656 t->ref_count--;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400657 if (t->ref_count == 0) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100658 D("transport: %s unref (kicking and closing)\n", t->serial);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400659 if (!t->kicked) {
660 t->kicked = 1;
661 t->kick(t);
662 }
663 t->close(t);
664 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100665 } else {
666 D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400667 }
668}
669
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800670static void transport_unref(atransport *t)
671{
672 if (t) {
673 adb_mutex_lock(&transport_lock);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400674 transport_unref_locked(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800675 adb_mutex_unlock(&transport_lock);
676 }
677}
678
679void add_transport_disconnect(atransport* t, adisconnect* dis)
680{
681 adb_mutex_lock(&transport_lock);
682 dis->next = &t->disconnects;
683 dis->prev = dis->next->prev;
684 dis->prev->next = dis;
685 dis->next->prev = dis;
686 adb_mutex_unlock(&transport_lock);
687}
688
689void remove_transport_disconnect(atransport* t, adisconnect* dis)
690{
691 dis->prev->next = dis->next;
692 dis->next->prev = dis->prev;
693 dis->next = dis->prev = dis;
694}
695
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700696static int qual_match(const char *to_test,
Elliott Hughes09a45a12015-04-03 16:12:15 -0700697 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700698{
699 if (!to_test || !*to_test)
700 /* Return true if both the qual and to_test are null strings. */
701 return !qual || !*qual;
702
703 if (!qual)
704 return 0;
705
706 if (prefix) {
707 while (*prefix) {
708 if (*prefix++ != *to_test++)
709 return 0;
710 }
711 }
712
713 while (*qual) {
714 char ch = *qual++;
Elliott Hughes09a45a12015-04-03 16:12:15 -0700715 if (sanitize_qual && !isalnum(ch))
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700716 ch = '_';
717 if (ch != *to_test++)
718 return 0;
719 }
720
721 /* Everything matched so far. Return true if *to_test is a NUL. */
722 return !*to_test;
723}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800724
Dan Albertdcd78a12015-05-18 16:43:57 -0700725atransport* acquire_one_transport(ConnectionState state, TransportType type,
726 const char* serial, std::string* error_out) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800727 atransport *result = NULL;
728 int ambiguous = 0;
729
730retry:
Elliott Hughese2d36772015-06-23 13:00:32 -0700731 *error_out = serial ? android::base::StringPrintf("device '%s' not found", serial) : "no devices found";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800732
733 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700734 for (auto t : transport_list) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700735 if (t->connection_state == kCsNoPerm) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700736 *error_out = "insufficient permissions for device";
Mike Lockwood37d31112009-08-08 13:53:16 -0400737 continue;
738 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400739
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800740 /* check for matching serial number */
741 if (serial) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700742 if ((t->serial && !strcmp(serial, t->serial)) ||
743 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughes09a45a12015-04-03 16:12:15 -0700744 qual_match(serial, "product:", t->product, false) ||
745 qual_match(serial, "model:", t->model, true) ||
746 qual_match(serial, "device:", t->device, false)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700747 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700748 *error_out = "more than one device";
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700749 ambiguous = 1;
750 result = NULL;
751 break;
752 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800753 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700754 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800755 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700756 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800757 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700758 *error_out = "more than one device";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800759 ambiguous = 1;
760 result = NULL;
761 break;
762 }
763 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700764 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800765 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700766 *error_out = "more than one emulator";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800767 ambiguous = 1;
768 result = NULL;
769 break;
770 }
771 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700772 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800773 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700774 *error_out = "more than one device/emulator";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800775 ambiguous = 1;
776 result = NULL;
777 break;
778 }
779 result = t;
780 }
781 }
782 }
783 adb_mutex_unlock(&transport_lock);
784
785 if (result) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700786 if (result->connection_state == kCsUnauthorized) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700787 *error_out = "device unauthorized.\n";
788 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
Elliott Hughes64d303a2015-07-18 13:57:46 -0700789 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
Elliott Hughese2d36772015-06-23 13:00:32 -0700790 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
Elliott Hughes64d303a2015-07-18 13:57:46 -0700791 *error_out += "\n";
792 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
Elliott Hughese2d36772015-06-23 13:00:32 -0700793 *error_out += "Otherwise check for a confirmation dialog on your device.";
Benoit Goby77e8e582013-01-15 12:36:47 -0800794 result = NULL;
795 }
796
Elliott Hughes7be29c82015-04-16 22:54:44 -0700797 /* offline devices are ignored -- they are either being born or dying */
Dan Albertdcd78a12015-05-18 16:43:57 -0700798 if (result && result->connection_state == kCsOffline) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700799 *error_out = "device offline";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800800 result = NULL;
801 }
Elliott Hughes7be29c82015-04-16 22:54:44 -0700802
803 /* check for required connection state */
Dan Albertdcd78a12015-05-18 16:43:57 -0700804 if (result && state != kCsAny && result->connection_state != state) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700805 *error_out = "invalid device state";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800806 result = NULL;
807 }
808 }
809
810 if (result) {
811 /* found one that we can take */
Elliott Hughese2d36772015-06-23 13:00:32 -0700812 *error_out = "success";
Dan Albertdcd78a12015-05-18 16:43:57 -0700813 } else if (state != kCsAny && (serial || !ambiguous)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800814 adb_sleep_ms(1000);
815 goto retry;
816 }
817
818 return result;
819}
820
Elliott Hughese67f1f82015-04-30 17:32:03 -0700821const char* atransport::connection_state_name() const {
822 switch (connection_state) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700823 case kCsOffline: return "offline";
824 case kCsBootloader: return "bootloader";
825 case kCsDevice: return "device";
826 case kCsHost: return "host";
827 case kCsRecovery: return "recovery";
828 case kCsNoPerm: return "no permissions";
829 case kCsSideload: return "sideload";
830 case kCsUnauthorized: return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831 default: return "unknown";
832 }
833}
834
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100835void atransport::update_version(int version, size_t payload) {
836 protocol_version = std::min(version, A_VERSION);
837 max_payload = std::min(payload, MAX_PAYLOAD);
838}
839
840int atransport::get_protocol_version() const {
841 return protocol_version;
842}
843
844size_t atransport::get_max_payload() const {
845 return max_payload;
846}
847
Elliott Hughese67f1f82015-04-30 17:32:03 -0700848#if ADB_HOST
849
Dan Albertd99d9022015-05-06 16:48:52 -0700850static void append_transport_info(std::string* result, const char* key,
851 const char* value, bool sanitize) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700852 if (value == nullptr || *value == '\0') {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700853 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700854 }
855
Elliott Hughese67f1f82015-04-30 17:32:03 -0700856 *result += ' ';
857 *result += key;
858
859 for (const char* p = value; *p; ++p) {
860 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
861 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700862}
863
Dan Albertc7915a32015-05-18 16:46:31 -0700864static void append_transport(const atransport* t, std::string* result,
865 bool long_listing) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700866 const char* serial = t->serial;
Elliott Hughese67f1f82015-04-30 17:32:03 -0700867 if (!serial || !serial[0]) {
Dan Albertd99d9022015-05-06 16:48:52 -0700868 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -0700869 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700870
871 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700872 *result += serial;
873 *result += '\t';
874 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700875 } else {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700876 android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700877
Elliott Hughese67f1f82015-04-30 17:32:03 -0700878 append_transport_info(result, "", t->devpath, false);
879 append_transport_info(result, "product:", t->product, false);
880 append_transport_info(result, "model:", t->model, true);
881 append_transport_info(result, "device:", t->device, false);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700882 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700883 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700884}
885
Elliott Hughese67f1f82015-04-30 17:32:03 -0700886std::string list_transports(bool long_listing) {
887 std::string result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700889 for (const auto t : transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700890 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800891 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800892 adb_mutex_unlock(&transport_lock);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700893 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800894}
895
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896/* hack for osx */
Dan Albertc7915a32015-05-18 16:46:31 -0700897void close_usb_devices() {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800898 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700899 for (auto t : transport_list) {
900 if (!t->kicked) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800901 t->kicked = 1;
902 t->kick(t);
903 }
904 }
905 adb_mutex_unlock(&transport_lock);
906}
907#endif // ADB_HOST
908
Dan Albertc7915a32015-05-18 16:46:31 -0700909int register_socket_transport(int s, const char *serial, int port, int local) {
910 atransport* t = new atransport();
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100911
912 if (!serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700913 char buf[32];
914 snprintf(buf, sizeof(buf), "T-%p", t);
915 serial = buf;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100916 }
Dan Albertc7915a32015-05-18 16:46:31 -0700917
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100918 D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700919 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700920 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700921 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800922 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700923
924 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700925 for (auto transport : pending_list) {
926 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700927 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700928 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700929 return -1;
930 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800931 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700932
Dan Albertc7915a32015-05-18 16:46:31 -0700933 for (auto transport : transport_list) {
934 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby1c45ee92013-03-29 18:22:36 -0700935 adb_mutex_unlock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700936 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700937 return -1;
938 }
939 }
940
Dan Albertc7915a32015-05-18 16:46:31 -0700941 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700942 t->serial = strdup(serial);
943 adb_mutex_unlock(&transport_lock);
944
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800945 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700946 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800947}
948
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400949#if ADB_HOST
Dan Albertc7915a32015-05-18 16:46:31 -0700950atransport *find_transport(const char *serial) {
951 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400952
953 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700954 for (auto t : transport_list) {
955 if (t->serial && strcmp(serial, t->serial) == 0) {
956 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400957 break;
958 }
Dan Albertc7915a32015-05-18 16:46:31 -0700959 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400960 adb_mutex_unlock(&transport_lock);
961
Dan Albertc7915a32015-05-18 16:46:31 -0700962 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400963}
964
965void unregister_transport(atransport *t)
966{
967 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700968 transport_list.remove(t);
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400969 adb_mutex_unlock(&transport_lock);
970
971 kick_transport(t);
972 transport_unref(t);
973}
974
Dan Albertc7915a32015-05-18 16:46:31 -0700975// Unregisters all non-emulator TCP transports.
976void unregister_all_tcp_transports() {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400977 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -0700978 for (auto it = transport_list.begin(); it != transport_list.end(); ) {
979 atransport* t = *it;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400980 if (t->type == kTransportLocal && t->adb_port == 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700981 // We cannot call kick_transport when holding transport_lock.
982 if (!t->kicked) {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400983 t->kicked = 1;
984 t->kick(t);
985 }
986 transport_unref_locked(t);
Dan Albertc7915a32015-05-18 16:46:31 -0700987
988 it = transport_list.erase(it);
989 } else {
990 ++it;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400991 }
Dan Albertc7915a32015-05-18 16:46:31 -0700992 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400993
994 adb_mutex_unlock(&transport_lock);
995}
996
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400997#endif
998
Dan Albertc7915a32015-05-18 16:46:31 -0700999void register_usb_transport(usb_handle* usb, const char* serial,
1000 const char* devpath, unsigned writeable) {
1001 atransport* t = new atransport();
1002
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001003 D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
1004 serial ? serial : "");
Dan Albertdcd78a12015-05-18 16:43:57 -07001005 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001006 if(serial) {
1007 t->serial = strdup(serial);
1008 }
Dan Albertc7915a32015-05-18 16:46:31 -07001009
1010 if (devpath) {
Scott Andersone109d262012-04-20 11:21:14 -07001011 t->devpath = strdup(devpath);
1012 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001013
1014 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -07001015 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -07001016 adb_mutex_unlock(&transport_lock);
1017
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001018 register_transport(t);
1019}
1020
Dan Albertdcd78a12015-05-18 16:43:57 -07001021// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertc7915a32015-05-18 16:46:31 -07001022void unregister_usb_transport(usb_handle *usb) {
Mike Lockwood0927bf92009-08-08 12:37:44 -04001023 adb_mutex_lock(&transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -07001024 transport_list.remove_if([usb](atransport* t) {
1025 return t->usb == usb && t->connection_state == kCsNoPerm;
1026 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001027 adb_mutex_unlock(&transport_lock);
1028}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001029
1030#undef TRACE_TAG
1031#define TRACE_TAG TRACE_RWX
1032
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001033int check_header(apacket *p, atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001034{
1035 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
1036 D("check_header(): invalid magic\n");
1037 return -1;
1038 }
1039
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001040 if(p->msg.data_length > t->get_max_payload()) {
1041 D("check_header(): %u > atransport::max_payload = %zu\n",
1042 p->msg.data_length, t->get_max_payload());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001043 return -1;
1044 }
1045
1046 return 0;
1047}
1048
1049int check_data(apacket *p)
1050{
1051 unsigned count, sum;
1052 unsigned char *x;
1053
1054 count = p->msg.data_length;
1055 x = p->data;
1056 sum = 0;
1057 while(count-- > 0) {
1058 sum += *x++;
1059 }
1060
1061 if(sum != p->msg.data_check) {
1062 return -1;
1063 } else {
1064 return 0;
1065 }
1066}