blob: 379c702e8570af4008f732f95a498cc4cac2531d [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
Dan Albertdb6fe642015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_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
Elliott Hughes88b4c852015-04-30 17:32:03 -070031#include <base/stringprintf.h>
32
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080033#include "adb.h"
Elliott Hughes88b4c852015-04-30 17:32:03 -070034#include "adb_utils.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080035
36static void transport_unref(atransport *t);
37
Dan Albertecce5032015-05-18 16:46:31 -070038static std::list<atransport*> transport_list;
39static std::list<atransport*> pending_list;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070040
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080041ADB_MUTEX_DEFINE( transport_lock );
42
Dan Albert4895c522015-02-20 17:24:58 -080043void kick_transport(atransport* t)
The Android Open Source Project9ca14dc2009-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 Albert4895c522015-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 Project9ca14dc2009-03-03 19:32:55 -080079{
80 adisconnect* dis = t->disconnects.next;
81
David 'Digit' Turner58f59682011-01-06 14:11:07 +010082 D("%s: run_transport_disconnects\n", t->serial);
The Android Open Source Project9ca14dc2009-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 Hughes88b4c852015-04-30 17:32:03 -070090static void dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner58f59682011-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' Turner58f59682011-01-06 14:11:07 +0100125
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800126static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100127read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800128{
129 char *p = (char*)ppacket; /* really read a packet address */
130 int r;
131 int len = sizeof(*ppacket);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100132 char buff[8];
133 if (!name) {
134 snprintf(buff, sizeof buff, "fd=%d", fd);
135 name = buff;
136 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800137 while(len > 0) {
138 r = adb_read(fd, p, len);
139 if(r > 0) {
140 len -= r;
141 p += r;
142 } else {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100143 D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800144 if((r < 0) && (errno == EINTR)) continue;
145 return -1;
146 }
147 }
148
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100149 if (ADB_TRACING) {
150 dump_packet(name, "from remote", *ppacket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800151 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800152 return 0;
153}
154
155static int
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100156write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800157{
158 char *p = (char*) ppacket; /* we really write the packet address */
159 int r, len = sizeof(ppacket);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100160 char buff[8];
161 if (!name) {
162 snprintf(buff, sizeof buff, "fd=%d", fd);
163 name = buff;
164 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800165
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100166 if (ADB_TRACING) {
167 dump_packet(name, "to remote", *ppacket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800168 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800169 len = sizeof(ppacket);
170 while(len > 0) {
171 r = adb_write(fd, p, len);
172 if(r > 0) {
173 len -= r;
174 p += r;
175 } else {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100176 D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800177 if((r < 0) && (errno == EINTR)) continue;
178 return -1;
179 }
180 }
181 return 0;
182}
183
184static void transport_socket_events(int fd, unsigned events, void *_t)
185{
Dan Albertf30d73c2015-02-25 17:51:28 -0800186 atransport *t = reinterpret_cast<atransport*>(_t);
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700187 D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800188 if(events & FDE_READ){
189 apacket *p = 0;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100190 if(read_packet(fd, t->serial, &p)){
191 D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800192 } else {
193 handle_packet(p, (atransport *) _t);
194 }
195 }
196}
197
198void send_packet(apacket *p, atransport *t)
199{
200 unsigned char *x;
201 unsigned sum;
202 unsigned count;
203
204 p->msg.magic = p->msg.command ^ 0xffffffff;
205
206 count = p->msg.data_length;
207 x = (unsigned char *) p->data;
208 sum = 0;
209 while(count-- > 0){
210 sum += *x++;
211 }
212 p->msg.data_check = sum;
213
214 print_packet("send", p);
215
216 if (t == NULL) {
JP Abgrall1f501f32011-02-23 18:44:39 -0800217 D("Transport is null \n");
JP Abgrall2e5dd6e2011-03-16 15:57:42 -0700218 // Zap errno because print_packet() and other stuff have errno effect.
219 errno = 0;
220 fatal_errno("Transport is null");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800221 }
222
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100223 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800224 fatal_errno("cannot enqueue packet on transport socket");
225 }
226}
227
228/* The transport is opened by transport_register_func before
229** the input and output threads are started.
230**
231** The output thread issues a SYNC(1, token) message to let
232** the input thread know to start things up. In the event
233** of transport IO failure, the output thread will post a
234** SYNC(0,0) message to ensure shutdown.
235**
236** The transport will not actually be closed until both
237** threads exit, but the input thread will kick the transport
238** on its way out to disconnect the underlying device.
239*/
240
241static void *output_thread(void *_t)
242{
Dan Albertf30d73c2015-02-25 17:51:28 -0800243 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800244 apacket *p;
245
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100246 D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
247 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800248 p = get_apacket();
249 p->msg.command = A_SYNC;
250 p->msg.arg0 = 1;
251 p->msg.arg1 = ++(t->sync_token);
252 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100253 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800254 put_apacket(p);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100255 D("%s: failed to write SYNC packet\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800256 goto oops;
257 }
258
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100259 D("%s: data pump started\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800260 for(;;) {
261 p = get_apacket();
262
263 if(t->read_from_remote(p, t) == 0){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100264 D("%s: received remote packet, sending to transport\n",
265 t->serial);
266 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800267 put_apacket(p);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100268 D("%s: failed to write apacket to transport\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800269 goto oops;
270 }
271 } else {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100272 D("%s: remote read failed for transport\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800273 put_apacket(p);
274 break;
275 }
276 }
277
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100278 D("%s: SYNC offline for transport\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800279 p = get_apacket();
280 p->msg.command = A_SYNC;
281 p->msg.arg0 = 0;
282 p->msg.arg1 = 0;
283 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100284 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800285 put_apacket(p);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100286 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800287 }
288
289oops:
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100290 D("%s: transport output thread is exiting\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800291 kick_transport(t);
292 transport_unref(t);
293 return 0;
294}
295
296static void *input_thread(void *_t)
297{
Dan Albertf30d73c2015-02-25 17:51:28 -0800298 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800299 apacket *p;
300 int active = 0;
301
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100302 D("%s: starting transport input thread, reading from fd %d\n",
303 t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800304
305 for(;;){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100306 if(read_packet(t->fd, t->serial, &p)) {
307 D("%s: failed to read apacket from transport on fd %d\n",
308 t->serial, t->fd );
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800309 break;
310 }
311 if(p->msg.command == A_SYNC){
312 if(p->msg.arg0 == 0) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100313 D("%s: transport SYNC offline\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800314 put_apacket(p);
315 break;
316 } else {
317 if(p->msg.arg1 == t->sync_token) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100318 D("%s: transport SYNC online\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800319 active = 1;
320 } else {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100321 D("%s: transport ignoring SYNC %d != %d\n",
322 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800323 }
324 }
325 } else {
326 if(active) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100327 D("%s: transport got packet, sending to remote\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800328 t->write_to_remote(p, t);
329 } else {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100330 D("%s: transport ignoring packet while offline\n", t->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800331 }
332 }
333
334 put_apacket(p);
335 }
336
337 // this is necessary to avoid a race condition that occured when a transport closes
338 // while a client socket is still active.
339 close_all_sockets(t);
340
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100341 D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800342 kick_transport(t);
343 transport_unref(t);
344 return 0;
345}
346
347
348static int transport_registration_send = -1;
349static int transport_registration_recv = -1;
350static fdevent transport_registration_fde;
351
352
353#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800354
355/* this adds support required by the 'track-devices' service.
356 * this is used to send the content of "list_transport" to any
357 * number of client connections that want it through a single
358 * live TCP connection
359 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800360struct device_tracker {
361 asocket socket;
362 int update_needed;
363 device_tracker* next;
364};
365
366/* linked list of all device trackers */
367static device_tracker* device_tracker_list;
368
369static void
370device_tracker_remove( device_tracker* tracker )
371{
372 device_tracker** pnode = &device_tracker_list;
373 device_tracker* node = *pnode;
374
375 adb_mutex_lock( &transport_lock );
376 while (node) {
377 if (node == tracker) {
378 *pnode = node->next;
379 break;
380 }
381 pnode = &node->next;
382 node = *pnode;
383 }
384 adb_mutex_unlock( &transport_lock );
385}
386
387static void
388device_tracker_close( asocket* socket )
389{
390 device_tracker* tracker = (device_tracker*) socket;
391 asocket* peer = socket->peer;
392
393 D( "device tracker %p removed\n", tracker);
394 if (peer) {
395 peer->peer = NULL;
396 peer->close(peer);
397 }
398 device_tracker_remove(tracker);
399 free(tracker);
400}
401
402static int
403device_tracker_enqueue( asocket* socket, apacket* p )
404{
405 /* you can't read from a device tracker, close immediately */
406 put_apacket(p);
407 device_tracker_close(socket);
408 return -1;
409}
410
Elliott Hughes88b4c852015-04-30 17:32:03 -0700411static int device_tracker_send(device_tracker* tracker, const std::string& string) {
412 apacket* p = get_apacket();
413 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800414
Elliott Hughes88b4c852015-04-30 17:32:03 -0700415 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
416 memcpy(&p->data[4], string.data(), string.size());
417 p->len = 4 + string.size();
418 return peer->enqueue(peer, p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800419}
420
Elliott Hughes88b4c852015-04-30 17:32:03 -0700421static void device_tracker_ready(asocket* socket) {
422 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800423
Elliott Hughes88b4c852015-04-30 17:32:03 -0700424 // We want to send the device list when the tracker connects
425 // for the first time, even if no update occurred.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800426 if (tracker->update_needed > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800427 tracker->update_needed = 0;
428
Elliott Hughes88b4c852015-04-30 17:32:03 -0700429 std::string transports = list_transports(false);
430 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800431 }
432}
433
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800434asocket*
435create_device_tracker(void)
436{
Elliott Hughesd0269c92015-04-21 19:39:52 -0700437 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
438 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800439
440 D( "device tracker %p created\n", tracker);
441
442 tracker->socket.enqueue = device_tracker_enqueue;
443 tracker->socket.ready = device_tracker_ready;
444 tracker->socket.close = device_tracker_close;
445 tracker->update_needed = 1;
446
447 tracker->next = device_tracker_list;
448 device_tracker_list = tracker;
449
450 return &tracker->socket;
451}
452
453
Elliott Hughes88b4c852015-04-30 17:32:03 -0700454// Call this function each time the transport list has changed.
455void update_transports() {
456 std::string transports = list_transports(false);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800457
Elliott Hughes88b4c852015-04-30 17:32:03 -0700458 device_tracker* tracker = device_tracker_list;
459 while (tracker != nullptr) {
460 device_tracker* next = tracker->next;
461 // This may destroy the tracker if the connection is closed.
462 device_tracker_send(tracker, transports);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800463 tracker = next;
464 }
465}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700466
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800467#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700468
469void update_transports() {
470 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800471}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700472
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800473#endif // ADB_HOST
474
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800475struct tmsg
476{
477 atransport *transport;
478 int action;
479};
480
481static int
482transport_read_action(int fd, struct tmsg* m)
483{
484 char *p = (char*)m;
485 int len = sizeof(*m);
486 int r;
487
488 while(len > 0) {
489 r = adb_read(fd, p, len);
490 if(r > 0) {
491 len -= r;
492 p += r;
493 } else {
494 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100495 D("transport_read_action: on fd %d, error %d: %s\n",
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800496 fd, errno, strerror(errno));
497 return -1;
498 }
499 }
500 return 0;
501}
502
503static int
504transport_write_action(int fd, struct tmsg* m)
505{
506 char *p = (char*)m;
507 int len = sizeof(*m);
508 int r;
509
510 while(len > 0) {
511 r = adb_write(fd, p, len);
512 if(r > 0) {
513 len -= r;
514 p += r;
515 } else {
516 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100517 D("transport_write_action: on fd %d, error %d: %s\n",
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800518 fd, errno, strerror(errno));
519 return -1;
520 }
521 }
522 return 0;
523}
524
525static void transport_registration_func(int _fd, unsigned ev, void *data)
526{
527 tmsg m;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800528 int s[2];
529 atransport *t;
530
531 if(!(ev & FDE_READ)) {
532 return;
533 }
534
535 if(transport_read_action(_fd, &m)) {
536 fatal_errno("cannot read transport registration socket");
537 }
538
539 t = m.transport;
540
541 if(m.action == 0){
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100542 D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800543
544 /* IMPORTANT: the remove closes one half of the
545 ** socket pair. The close closes the other half.
546 */
547 fdevent_remove(&(t->transport_fde));
548 adb_close(t->fd);
549
550 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700551 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800552 adb_mutex_unlock(&transport_lock);
553
554 run_transport_disconnects(t);
555
556 if (t->product)
557 free(t->product);
558 if (t->serial)
559 free(t->serial);
Scott Andersonfa020922012-05-25 14:10:02 -0700560 if (t->model)
561 free(t->model);
562 if (t->device)
563 free(t->device);
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700564 if (t->devpath)
565 free(t->devpath);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800566
Dan Albertecce5032015-05-18 16:46:31 -0700567 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800568
569 update_transports();
570 return;
571 }
572
Mike Lockwoode45583f2009-08-08 12:37:44 -0400573 /* don't create transport threads for inaccessible devices */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700574 if (t->connection_state != kCsNoPerm) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800575 /* initial references are the two threads */
Mike Lockwoode45583f2009-08-08 12:37:44 -0400576 t->ref_count = 2;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800577
Dan Albertecce5032015-05-18 16:46:31 -0700578 if (adb_socketpair(s)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400579 fatal_errno("cannot open transport socketpair");
580 }
581
leozwang1be54622014-08-15 09:51:27 -0700582 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwoode45583f2009-08-08 12:37:44 -0400583
584 t->transport_socket = s[0];
585 t->fd = s[1];
586
Mike Lockwoode45583f2009-08-08 12:37:44 -0400587 fdevent_install(&(t->transport_fde),
588 t->transport_socket,
589 transport_socket_events,
590 t);
591
592 fdevent_set(&(t->transport_fde), FDE_READ);
593
Elliott Hughesf2517142015-05-05 13:41:21 -0700594 if (!adb_thread_create(input_thread, t)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400595 fatal_errno("cannot create input thread");
596 }
597
Elliott Hughesf2517142015-05-05 13:41:21 -0700598 if (!adb_thread_create(output_thread, t)) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400599 fatal_errno("cannot create output thread");
600 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800601 }
602
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800603 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700604 pending_list.remove(t);
605 transport_list.push_front(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800606 adb_mutex_unlock(&transport_lock);
607
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800608 t->disconnects.next = t->disconnects.prev = &t->disconnects;
609
610 update_transports();
611}
612
613void init_transport_registration(void)
614{
615 int s[2];
616
617 if(adb_socketpair(s)){
618 fatal_errno("cannot open transport registration socketpair");
619 }
leozwang1be54622014-08-15 09:51:27 -0700620 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800621
622 transport_registration_send = s[0];
623 transport_registration_recv = s[1];
624
625 fdevent_install(&transport_registration_fde,
626 transport_registration_recv,
627 transport_registration_func,
628 0);
629
630 fdevent_set(&transport_registration_fde, FDE_READ);
631}
632
633/* the fdevent select pump is single threaded */
634static void register_transport(atransport *transport)
635{
636 tmsg m;
637 m.transport = transport;
638 m.action = 1;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100639 D("transport: %s registered\n", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800640 if(transport_write_action(transport_registration_send, &m)) {
641 fatal_errno("cannot write transport registration socket\n");
642 }
643}
644
645static void remove_transport(atransport *transport)
646{
647 tmsg m;
648 m.transport = transport;
649 m.action = 0;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100650 D("transport: %s removed\n", transport->serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800651 if(transport_write_action(transport_registration_send, &m)) {
652 fatal_errno("cannot write transport registration socket\n");
653 }
654}
655
656
Mike Lockwood01c2c302010-05-24 10:44:35 -0400657static void transport_unref_locked(atransport *t)
658{
659 t->ref_count--;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400660 if (t->ref_count == 0) {
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100661 D("transport: %s unref (kicking and closing)\n", t->serial);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400662 if (!t->kicked) {
663 t->kicked = 1;
664 t->kick(t);
665 }
666 t->close(t);
667 remove_transport(t);
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100668 } else {
669 D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400670 }
671}
672
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800673static void transport_unref(atransport *t)
674{
675 if (t) {
676 adb_mutex_lock(&transport_lock);
Mike Lockwood01c2c302010-05-24 10:44:35 -0400677 transport_unref_locked(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800678 adb_mutex_unlock(&transport_lock);
679 }
680}
681
682void add_transport_disconnect(atransport* t, adisconnect* dis)
683{
684 adb_mutex_lock(&transport_lock);
685 dis->next = &t->disconnects;
686 dis->prev = dis->next->prev;
687 dis->prev->next = dis;
688 dis->next->prev = dis;
689 adb_mutex_unlock(&transport_lock);
690}
691
692void remove_transport_disconnect(atransport* t, adisconnect* dis)
693{
694 dis->prev->next = dis->next;
695 dis->next->prev = dis->prev;
696 dis->next = dis->prev = dis;
697}
698
Scott Anderson27042382012-05-30 18:11:27 -0700699static int qual_match(const char *to_test,
Elliott Hughesabfa7202015-04-03 16:12:15 -0700700 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson27042382012-05-30 18:11:27 -0700701{
702 if (!to_test || !*to_test)
703 /* Return true if both the qual and to_test are null strings. */
704 return !qual || !*qual;
705
706 if (!qual)
707 return 0;
708
709 if (prefix) {
710 while (*prefix) {
711 if (*prefix++ != *to_test++)
712 return 0;
713 }
714 }
715
716 while (*qual) {
717 char ch = *qual++;
Elliott Hughesabfa7202015-04-03 16:12:15 -0700718 if (sanitize_qual && !isalnum(ch))
Scott Anderson27042382012-05-30 18:11:27 -0700719 ch = '_';
720 if (ch != *to_test++)
721 return 0;
722 }
723
724 /* Everything matched so far. Return true if *to_test is a NUL. */
725 return !*to_test;
726}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800727
Dan Albert9a50f4c2015-05-18 16:43:57 -0700728atransport* acquire_one_transport(ConnectionState state, TransportType type,
729 const char* serial, std::string* error_out) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800730 atransport *result = NULL;
731 int ambiguous = 0;
732
733retry:
Elliott Hughesfb596842015-05-01 17:04:38 -0700734 if (error_out) *error_out = android::base::StringPrintf("device '%s' not found", serial);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800735
736 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700737 for (auto t : transport_list) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700738 if (t->connection_state == kCsNoPerm) {
Elliott Hughesab882422015-04-16 22:54:44 -0700739 if (error_out) *error_out = "insufficient permissions for device";
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400740 continue;
741 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400742
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800743 /* check for matching serial number */
744 if (serial) {
Scott Anderson27042382012-05-30 18:11:27 -0700745 if ((t->serial && !strcmp(serial, t->serial)) ||
746 (t->devpath && !strcmp(serial, t->devpath)) ||
Elliott Hughesabfa7202015-04-03 16:12:15 -0700747 qual_match(serial, "product:", t->product, false) ||
748 qual_match(serial, "model:", t->model, true) ||
749 qual_match(serial, "device:", t->device, false)) {
Scott Anderson27042382012-05-30 18:11:27 -0700750 if (result) {
Elliott Hughesab882422015-04-16 22:54:44 -0700751 if (error_out) *error_out = "more than one device";
Scott Anderson27042382012-05-30 18:11:27 -0700752 ambiguous = 1;
753 result = NULL;
754 break;
755 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800756 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700757 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800758 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700759 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800760 if (result) {
Elliott Hughesab882422015-04-16 22:54:44 -0700761 if (error_out) *error_out = "more than one device";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800762 ambiguous = 1;
763 result = NULL;
764 break;
765 }
766 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700767 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800768 if (result) {
Elliott Hughesab882422015-04-16 22:54:44 -0700769 if (error_out) *error_out = "more than one emulator";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800770 ambiguous = 1;
771 result = NULL;
772 break;
773 }
774 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700775 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800776 if (result) {
Elliott Hughesda945812015-04-29 12:28:13 -0700777 if (error_out) *error_out = "more than one device/emulator";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800778 ambiguous = 1;
779 result = NULL;
780 break;
781 }
782 result = t;
783 }
784 }
785 }
786 adb_mutex_unlock(&transport_lock);
787
788 if (result) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700789 if (result->connection_state == kCsUnauthorized) {
Elliott Hughesab882422015-04-16 22:54:44 -0700790 if (error_out) {
791 *error_out = "device unauthorized.\n";
792 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
793 *error_out += "This adbd's $ADB_VENDOR_KEYS is ";
794 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
795 *error_out += "; try 'adb kill-server' if that seems wrong.\n";
796 *error_out += "Otherwise check for a confirmation dialog on your device.";
797 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700798 result = NULL;
799 }
800
Elliott Hughesab882422015-04-16 22:54:44 -0700801 /* offline devices are ignored -- they are either being born or dying */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700802 if (result && result->connection_state == kCsOffline) {
Elliott Hughesab882422015-04-16 22:54:44 -0700803 if (error_out) *error_out = "device offline";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800804 result = NULL;
805 }
Elliott Hughesab882422015-04-16 22:54:44 -0700806
807 /* check for required connection state */
Dan Albert9a50f4c2015-05-18 16:43:57 -0700808 if (result && state != kCsAny && result->connection_state != state) {
Elliott Hughesab882422015-04-16 22:54:44 -0700809 if (error_out) *error_out = "invalid device state";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800810 result = NULL;
811 }
812 }
813
814 if (result) {
815 /* found one that we can take */
Elliott Hughesab882422015-04-16 22:54:44 -0700816 if (error_out) *error_out = "success";
Dan Albert9a50f4c2015-05-18 16:43:57 -0700817 } else if (state != kCsAny && (serial || !ambiguous)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800818 adb_sleep_ms(1000);
819 goto retry;
820 }
821
822 return result;
823}
824
Elliott Hughes88b4c852015-04-30 17:32:03 -0700825const char* atransport::connection_state_name() const {
826 switch (connection_state) {
Dan Albert9a50f4c2015-05-18 16:43:57 -0700827 case kCsOffline: return "offline";
828 case kCsBootloader: return "bootloader";
829 case kCsDevice: return "device";
830 case kCsHost: return "host";
831 case kCsRecovery: return "recovery";
832 case kCsNoPerm: return "no permissions";
833 case kCsSideload: return "sideload";
834 case kCsUnauthorized: return "unauthorized";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800835 default: return "unknown";
836 }
837}
838
Elliott Hughes88b4c852015-04-30 17:32:03 -0700839#if ADB_HOST
840
Dan Alberta8c34142015-05-06 16:48:52 -0700841static void append_transport_info(std::string* result, const char* key,
842 const char* value, bool sanitize) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700843 if (value == nullptr || *value == '\0') {
Scott Anderson27042382012-05-30 18:11:27 -0700844 return;
Scott Anderson27042382012-05-30 18:11:27 -0700845 }
846
Elliott Hughes88b4c852015-04-30 17:32:03 -0700847 *result += ' ';
848 *result += key;
849
850 for (const char* p = value; *p; ++p) {
851 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
852 }
Scott Anderson27042382012-05-30 18:11:27 -0700853}
854
Dan Albertecce5032015-05-18 16:46:31 -0700855static void append_transport(const atransport* t, std::string* result,
856 bool long_listing) {
Scott Anderson27042382012-05-30 18:11:27 -0700857 const char* serial = t->serial;
Elliott Hughes88b4c852015-04-30 17:32:03 -0700858 if (!serial || !serial[0]) {
Dan Alberta8c34142015-05-06 16:48:52 -0700859 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -0700860 }
Scott Anderson27042382012-05-30 18:11:27 -0700861
862 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700863 *result += serial;
864 *result += '\t';
865 *result += t->connection_state_name();
Scott Anderson27042382012-05-30 18:11:27 -0700866 } else {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700867 android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name());
Scott Anderson27042382012-05-30 18:11:27 -0700868
Elliott Hughes88b4c852015-04-30 17:32:03 -0700869 append_transport_info(result, "", t->devpath, false);
870 append_transport_info(result, "product:", t->product, false);
871 append_transport_info(result, "model:", t->model, true);
872 append_transport_info(result, "device:", t->device, false);
Scott Anderson27042382012-05-30 18:11:27 -0700873 }
Elliott Hughes88b4c852015-04-30 17:32:03 -0700874 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -0700875}
876
Elliott Hughes88b4c852015-04-30 17:32:03 -0700877std::string list_transports(bool long_listing) {
878 std::string result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800879 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700880 for (const auto t : transport_list) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700881 append_transport(t, &result, long_listing);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800882 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800883 adb_mutex_unlock(&transport_lock);
Elliott Hughes88b4c852015-04-30 17:32:03 -0700884 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800885}
886
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800887/* hack for osx */
Dan Albertecce5032015-05-18 16:46:31 -0700888void close_usb_devices() {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800889 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700890 for (auto t : transport_list) {
891 if (!t->kicked) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800892 t->kicked = 1;
893 t->kick(t);
894 }
895 }
896 adb_mutex_unlock(&transport_lock);
897}
898#endif // ADB_HOST
899
Dan Albertecce5032015-05-18 16:46:31 -0700900int register_socket_transport(int s, const char *serial, int port, int local) {
901 atransport* t = new atransport();
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100902
903 if (!serial) {
Dan Albertecce5032015-05-18 16:46:31 -0700904 char buf[32];
905 snprintf(buf, sizeof(buf), "T-%p", t);
906 serial = buf;
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100907 }
Dan Albertecce5032015-05-18 16:46:31 -0700908
David 'Digit' Turner58f59682011-01-06 14:11:07 +0100909 D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700910 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -0700911 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700912 return -1;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800913 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700914
915 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700916 for (auto transport : pending_list) {
917 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700918 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700919 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700920 return -1;
921 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800922 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700923
Dan Albertecce5032015-05-18 16:46:31 -0700924 for (auto transport : transport_list) {
925 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700926 adb_mutex_unlock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700927 delete t;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700928 return -1;
929 }
930 }
931
Dan Albertecce5032015-05-18 16:46:31 -0700932 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700933 t->serial = strdup(serial);
934 adb_mutex_unlock(&transport_lock);
935
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800936 register_transport(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700937 return 0;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800938}
939
Mike Lockwood81ffe172009-10-11 23:04:18 -0400940#if ADB_HOST
Dan Albertecce5032015-05-18 16:46:31 -0700941atransport *find_transport(const char *serial) {
942 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400943
944 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700945 for (auto t : transport_list) {
946 if (t->serial && strcmp(serial, t->serial) == 0) {
947 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400948 break;
949 }
Dan Albertecce5032015-05-18 16:46:31 -0700950 }
Mike Lockwood81ffe172009-10-11 23:04:18 -0400951 adb_mutex_unlock(&transport_lock);
952
Dan Albertecce5032015-05-18 16:46:31 -0700953 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -0400954}
955
956void unregister_transport(atransport *t)
957{
958 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700959 transport_list.remove(t);
Mike Lockwood81ffe172009-10-11 23:04:18 -0400960 adb_mutex_unlock(&transport_lock);
961
962 kick_transport(t);
963 transport_unref(t);
964}
965
Dan Albertecce5032015-05-18 16:46:31 -0700966// Unregisters all non-emulator TCP transports.
967void unregister_all_tcp_transports() {
Mike Lockwood01c2c302010-05-24 10:44:35 -0400968 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -0700969 for (auto it = transport_list.begin(); it != transport_list.end(); ) {
970 atransport* t = *it;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400971 if (t->type == kTransportLocal && t->adb_port == 0) {
Dan Albertecce5032015-05-18 16:46:31 -0700972 // We cannot call kick_transport when holding transport_lock.
973 if (!t->kicked) {
Mike Lockwood01c2c302010-05-24 10:44:35 -0400974 t->kicked = 1;
975 t->kick(t);
976 }
977 transport_unref_locked(t);
Dan Albertecce5032015-05-18 16:46:31 -0700978
979 it = transport_list.erase(it);
980 } else {
981 ++it;
Mike Lockwood01c2c302010-05-24 10:44:35 -0400982 }
Dan Albertecce5032015-05-18 16:46:31 -0700983 }
Mike Lockwood01c2c302010-05-24 10:44:35 -0400984
985 adb_mutex_unlock(&transport_lock);
986}
987
Mike Lockwood81ffe172009-10-11 23:04:18 -0400988#endif
989
Dan Albertecce5032015-05-18 16:46:31 -0700990void register_usb_transport(usb_handle* usb, const char* serial,
991 const char* devpath, unsigned writeable) {
992 atransport* t = new atransport();
993
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800994 D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
995 serial ? serial : "");
Dan Albert9a50f4c2015-05-18 16:43:57 -0700996 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800997 if(serial) {
998 t->serial = strdup(serial);
999 }
Dan Albertecce5032015-05-18 16:46:31 -07001000
1001 if (devpath) {
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001002 t->devpath = strdup(devpath);
1003 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001004
1005 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -07001006 pending_list.push_front(t);
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001007 adb_mutex_unlock(&transport_lock);
1008
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001009 register_transport(t);
1010}
1011
Dan Albert9a50f4c2015-05-18 16:43:57 -07001012// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertecce5032015-05-18 16:46:31 -07001013void unregister_usb_transport(usb_handle *usb) {
Mike Lockwoode45583f2009-08-08 12:37:44 -04001014 adb_mutex_lock(&transport_lock);
Dan Albertecce5032015-05-18 16:46:31 -07001015 transport_list.remove_if([usb](atransport* t) {
1016 return t->usb == usb && t->connection_state == kCsNoPerm;
1017 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001018 adb_mutex_unlock(&transport_lock);
1019}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001020
1021#undef TRACE_TAG
1022#define TRACE_TAG TRACE_RWX
1023
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001024int check_header(apacket *p)
1025{
1026 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
1027 D("check_header(): invalid magic\n");
1028 return -1;
1029 }
1030
1031 if(p->msg.data_length > MAX_PAYLOAD) {
1032 D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
1033 return -1;
1034 }
1035
1036 return 0;
1037}
1038
1039int check_data(apacket *p)
1040{
1041 unsigned count, sum;
1042 unsigned char *x;
1043
1044 count = p->msg.data_length;
1045 x = p->data;
1046 sum = 0;
1047 while(count-- > 0) {
1048 sum += *x++;
1049 }
1050
1051 if(sum != p->msg.data_check) {
1052 return -1;
1053 } else {
1054 return 0;
1055 }
1056}