blob: 4904cd04c948544fcb5bde635de34988d131c517 [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 Albert76649012015-02-24 15:51:19 -080017#include "sysdeps.h"
18
19#include "transport.h"
20
21#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080022#include <stdio.h>
23#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080025#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026
27#define TRACE_TAG TRACE_TRANSPORT
28#include "adb.h"
29
30static void transport_unref(atransport *t);
31
32static atransport transport_list = {
33 .next = &transport_list,
34 .prev = &transport_list,
35};
36
Benoit Goby1c45ee92013-03-29 18:22:36 -070037static atransport pending_list = {
38 .next = &pending_list,
39 .prev = &pending_list,
40};
41
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042ADB_MUTEX_DEFINE( transport_lock );
43
44#if ADB_TRACE
JP Abgrall408fa572011-03-16 15:57:42 -070045#define MAX_DUMP_HEX_LEN 16
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046static void dump_hex( const unsigned char* ptr, size_t len )
47{
48 int nn, len2 = len;
JP Abgrall408fa572011-03-16 15:57:42 -070049 // Build a string instead of logging each character.
50 // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
51 char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052
JP Abgrall408fa572011-03-16 15:57:42 -070053 if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054
JP Abgrall408fa572011-03-16 15:57:42 -070055 for (nn = 0; nn < len2; nn++) {
56 sprintf(pb, "%02x", ptr[nn]);
57 pb += 2;
58 }
59 sprintf(pb++, " ");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
61 for (nn = 0; nn < len2; nn++) {
62 int c = ptr[nn];
63 if (c < 32 || c > 127)
64 c = '.';
JP Abgrall408fa572011-03-16 15:57:42 -070065 *pb++ = c;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080066 }
JP Abgrall408fa572011-03-16 15:57:42 -070067 *pb++ = '\0';
68 DR("%s\n", buffer);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080069}
70#endif
71
72void
73kick_transport(atransport* t)
74{
75 if (t && !t->kicked)
76 {
77 int kicked;
78
79 adb_mutex_lock(&transport_lock);
80 kicked = t->kicked;
81 if (!kicked)
82 t->kicked = 1;
83 adb_mutex_unlock(&transport_lock);
84
85 if (!kicked)
86 t->kick(t);
87 }
88}
89
90void
91run_transport_disconnects(atransport* t)
92{
93 adisconnect* dis = t->disconnects.next;
94
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010095 D("%s: run_transport_disconnects\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080096 while (dis != &t->disconnects) {
97 adisconnect* next = dis->next;
98 dis->func( dis->opaque, t );
99 dis = next;
100 }
101}
102
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100103#if ADB_TRACE
104static void
105dump_packet(const char* name, const char* func, apacket* p)
106{
107 unsigned command = p->msg.command;
108 int len = p->msg.data_length;
109 char cmd[9];
110 char arg0[12], arg1[12];
111 int n;
112
113 for (n = 0; n < 4; n++) {
114 int b = (command >> (n*8)) & 255;
115 if (b < 32 || b >= 127)
116 break;
117 cmd[n] = (char)b;
118 }
119 if (n == 4) {
120 cmd[4] = 0;
121 } else {
122 /* There is some non-ASCII name in the command, so dump
123 * the hexadecimal value instead */
124 snprintf(cmd, sizeof cmd, "%08x", command);
125 }
126
127 if (p->msg.arg0 < 256U)
128 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
129 else
130 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
131
132 if (p->msg.arg1 < 256U)
133 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
134 else
135 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
136
137 D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
138 name, func, cmd, arg0, arg1, len);
139 dump_hex(p->data, len);
140}
141#endif /* ADB_TRACE */
142
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800143static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100144read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800145{
146 char *p = (char*)ppacket; /* really read a packet address */
147 int r;
148 int len = sizeof(*ppacket);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100149 char buff[8];
150 if (!name) {
151 snprintf(buff, sizeof buff, "fd=%d", fd);
152 name = buff;
153 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800154 while(len > 0) {
155 r = adb_read(fd, p, len);
156 if(r > 0) {
157 len -= r;
158 p += r;
159 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100160 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 -0800161 if((r < 0) && (errno == EINTR)) continue;
162 return -1;
163 }
164 }
165
166#if ADB_TRACE
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100167 if (ADB_TRACING) {
168 dump_packet(name, "from remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169 }
170#endif
171 return 0;
172}
173
174static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100175write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800176{
177 char *p = (char*) ppacket; /* we really write the packet address */
178 int r, len = sizeof(ppacket);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100179 char buff[8];
180 if (!name) {
181 snprintf(buff, sizeof buff, "fd=%d", fd);
182 name = buff;
183 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800184
185#if ADB_TRACE
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100186 if (ADB_TRACING) {
187 dump_packet(name, "to remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800188 }
189#endif
190 len = sizeof(ppacket);
191 while(len > 0) {
192 r = adb_write(fd, p, len);
193 if(r > 0) {
194 len -= r;
195 p += r;
196 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100197 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 -0800198 if((r < 0) && (errno == EINTR)) continue;
199 return -1;
200 }
201 }
202 return 0;
203}
204
205static void transport_socket_events(int fd, unsigned events, void *_t)
206{
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100207 atransport *t = _t;
JP Abgrall408fa572011-03-16 15:57:42 -0700208 D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 if(events & FDE_READ){
210 apacket *p = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100211 if(read_packet(fd, t->serial, &p)){
212 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 -0800213 } else {
214 handle_packet(p, (atransport *) _t);
215 }
216 }
217}
218
219void send_packet(apacket *p, atransport *t)
220{
221 unsigned char *x;
222 unsigned sum;
223 unsigned count;
224
225 p->msg.magic = p->msg.command ^ 0xffffffff;
226
227 count = p->msg.data_length;
228 x = (unsigned char *) p->data;
229 sum = 0;
230 while(count-- > 0){
231 sum += *x++;
232 }
233 p->msg.data_check = sum;
234
235 print_packet("send", p);
236
237 if (t == NULL) {
JP Abgrall0e7c4272011-02-23 18:44:39 -0800238 D("Transport is null \n");
JP Abgrall408fa572011-03-16 15:57:42 -0700239 // Zap errno because print_packet() and other stuff have errno effect.
240 errno = 0;
241 fatal_errno("Transport is null");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800242 }
243
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100244 if(write_packet(t->transport_socket, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800245 fatal_errno("cannot enqueue packet on transport socket");
246 }
247}
248
249/* The transport is opened by transport_register_func before
250** the input and output threads are started.
251**
252** The output thread issues a SYNC(1, token) message to let
253** the input thread know to start things up. In the event
254** of transport IO failure, the output thread will post a
255** SYNC(0,0) message to ensure shutdown.
256**
257** The transport will not actually be closed until both
258** threads exit, but the input thread will kick the transport
259** on its way out to disconnect the underlying device.
260*/
261
262static void *output_thread(void *_t)
263{
264 atransport *t = _t;
265 apacket *p;
266
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100267 D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
268 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269 p = get_apacket();
270 p->msg.command = A_SYNC;
271 p->msg.arg0 = 1;
272 p->msg.arg1 = ++(t->sync_token);
273 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100274 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275 put_apacket(p);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100276 D("%s: failed to write SYNC packet\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800277 goto oops;
278 }
279
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100280 D("%s: data pump started\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800281 for(;;) {
282 p = get_apacket();
283
284 if(t->read_from_remote(p, t) == 0){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100285 D("%s: received remote packet, sending to transport\n",
286 t->serial);
287 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288 put_apacket(p);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100289 D("%s: failed to write apacket to transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 goto oops;
291 }
292 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100293 D("%s: remote read failed for transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800294 put_apacket(p);
295 break;
296 }
297 }
298
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100299 D("%s: SYNC offline for transport\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 p = get_apacket();
301 p->msg.command = A_SYNC;
302 p->msg.arg0 = 0;
303 p->msg.arg1 = 0;
304 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100305 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800306 put_apacket(p);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100307 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 }
309
310oops:
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100311 D("%s: transport output thread is exiting\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800312 kick_transport(t);
313 transport_unref(t);
314 return 0;
315}
316
317static void *input_thread(void *_t)
318{
319 atransport *t = _t;
320 apacket *p;
321 int active = 0;
322
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100323 D("%s: starting transport input thread, reading from fd %d\n",
324 t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800325
326 for(;;){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100327 if(read_packet(t->fd, t->serial, &p)) {
328 D("%s: failed to read apacket from transport on fd %d\n",
329 t->serial, t->fd );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800330 break;
331 }
332 if(p->msg.command == A_SYNC){
333 if(p->msg.arg0 == 0) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100334 D("%s: transport SYNC offline\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800335 put_apacket(p);
336 break;
337 } else {
338 if(p->msg.arg1 == t->sync_token) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100339 D("%s: transport SYNC online\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800340 active = 1;
341 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100342 D("%s: transport ignoring SYNC %d != %d\n",
343 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800344 }
345 }
346 } else {
347 if(active) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100348 D("%s: transport got packet, sending to remote\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800349 t->write_to_remote(p, t);
350 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100351 D("%s: transport ignoring packet while offline\n", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800352 }
353 }
354
355 put_apacket(p);
356 }
357
358 // this is necessary to avoid a race condition that occured when a transport closes
359 // while a client socket is still active.
360 close_all_sockets(t);
361
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100362 D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800363 kick_transport(t);
364 transport_unref(t);
365 return 0;
366}
367
368
369static int transport_registration_send = -1;
370static int transport_registration_recv = -1;
371static fdevent transport_registration_fde;
372
373
374#if ADB_HOST
375static int list_transports_msg(char* buffer, size_t bufferlen)
376{
377 char head[5];
378 int len;
379
Scott Andersone109d262012-04-20 11:21:14 -0700380 len = list_transports(buffer+4, bufferlen-4, 0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800381 snprintf(head, sizeof(head), "%04x", len);
382 memcpy(buffer, head, 4);
383 len += 4;
384 return len;
385}
386
387/* this adds support required by the 'track-devices' service.
388 * this is used to send the content of "list_transport" to any
389 * number of client connections that want it through a single
390 * live TCP connection
391 */
392typedef struct device_tracker device_tracker;
393struct device_tracker {
394 asocket socket;
395 int update_needed;
396 device_tracker* next;
397};
398
399/* linked list of all device trackers */
400static device_tracker* device_tracker_list;
401
402static void
403device_tracker_remove( device_tracker* tracker )
404{
405 device_tracker** pnode = &device_tracker_list;
406 device_tracker* node = *pnode;
407
408 adb_mutex_lock( &transport_lock );
409 while (node) {
410 if (node == tracker) {
411 *pnode = node->next;
412 break;
413 }
414 pnode = &node->next;
415 node = *pnode;
416 }
417 adb_mutex_unlock( &transport_lock );
418}
419
420static void
421device_tracker_close( asocket* socket )
422{
423 device_tracker* tracker = (device_tracker*) socket;
424 asocket* peer = socket->peer;
425
426 D( "device tracker %p removed\n", tracker);
427 if (peer) {
428 peer->peer = NULL;
429 peer->close(peer);
430 }
431 device_tracker_remove(tracker);
432 free(tracker);
433}
434
435static int
436device_tracker_enqueue( asocket* socket, apacket* p )
437{
438 /* you can't read from a device tracker, close immediately */
439 put_apacket(p);
440 device_tracker_close(socket);
441 return -1;
442}
443
444static int
445device_tracker_send( device_tracker* tracker,
446 const char* buffer,
447 int len )
448{
449 apacket* p = get_apacket();
450 asocket* peer = tracker->socket.peer;
451
452 memcpy(p->data, buffer, len);
453 p->len = len;
454 return peer->enqueue( peer, p );
455}
456
457
458static void
459device_tracker_ready( asocket* socket )
460{
461 device_tracker* tracker = (device_tracker*) socket;
462
463 /* we want to send the device list when the tracker connects
464 * for the first time, even if no update occured */
465 if (tracker->update_needed > 0) {
466 char buffer[1024];
467 int len;
468
469 tracker->update_needed = 0;
470
471 len = list_transports_msg(buffer, sizeof(buffer));
472 device_tracker_send(tracker, buffer, len);
473 }
474}
475
476
477asocket*
478create_device_tracker(void)
479{
480 device_tracker* tracker = calloc(1,sizeof(*tracker));
481
482 if(tracker == 0) fatal("cannot allocate device tracker");
483
484 D( "device tracker %p created\n", tracker);
485
486 tracker->socket.enqueue = device_tracker_enqueue;
487 tracker->socket.ready = device_tracker_ready;
488 tracker->socket.close = device_tracker_close;
489 tracker->update_needed = 1;
490
491 tracker->next = device_tracker_list;
492 device_tracker_list = tracker;
493
494 return &tracker->socket;
495}
496
497
498/* call this function each time the transport list has changed */
Dan Albert76649012015-02-24 15:51:19 -0800499void update_transports(void) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800500 char buffer[1024];
501 int len;
502 device_tracker* tracker;
503
504 len = list_transports_msg(buffer, sizeof(buffer));
505
506 tracker = device_tracker_list;
507 while (tracker != NULL) {
508 device_tracker* next = tracker->next;
509 /* note: this may destroy the tracker if the connection is closed */
510 device_tracker_send(tracker, buffer, len);
511 tracker = next;
512 }
513}
514#else
515void update_transports(void)
516{
517 // nothing to do on the device side
518}
519#endif // ADB_HOST
520
521typedef struct tmsg tmsg;
522struct tmsg
523{
524 atransport *transport;
525 int action;
526};
527
528static int
529transport_read_action(int fd, struct tmsg* m)
530{
531 char *p = (char*)m;
532 int len = sizeof(*m);
533 int r;
534
535 while(len > 0) {
536 r = adb_read(fd, p, len);
537 if(r > 0) {
538 len -= r;
539 p += r;
540 } else {
541 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100542 D("transport_read_action: on fd %d, error %d: %s\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800543 fd, errno, strerror(errno));
544 return -1;
545 }
546 }
547 return 0;
548}
549
550static int
551transport_write_action(int fd, struct tmsg* m)
552{
553 char *p = (char*)m;
554 int len = sizeof(*m);
555 int r;
556
557 while(len > 0) {
558 r = adb_write(fd, p, len);
559 if(r > 0) {
560 len -= r;
561 p += r;
562 } else {
563 if((r < 0) && (errno == EINTR)) continue;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100564 D("transport_write_action: on fd %d, error %d: %s\n",
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 fd, errno, strerror(errno));
566 return -1;
567 }
568 }
569 return 0;
570}
571
572static void transport_registration_func(int _fd, unsigned ev, void *data)
573{
574 tmsg m;
575 adb_thread_t output_thread_ptr;
576 adb_thread_t input_thread_ptr;
577 int s[2];
578 atransport *t;
579
580 if(!(ev & FDE_READ)) {
581 return;
582 }
583
584 if(transport_read_action(_fd, &m)) {
585 fatal_errno("cannot read transport registration socket");
586 }
587
588 t = m.transport;
589
590 if(m.action == 0){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100591 D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592
593 /* IMPORTANT: the remove closes one half of the
594 ** socket pair. The close closes the other half.
595 */
596 fdevent_remove(&(t->transport_fde));
597 adb_close(t->fd);
598
599 adb_mutex_lock(&transport_lock);
600 t->next->prev = t->prev;
601 t->prev->next = t->next;
602 adb_mutex_unlock(&transport_lock);
603
604 run_transport_disconnects(t);
605
606 if (t->product)
607 free(t->product);
608 if (t->serial)
609 free(t->serial);
Scott Andersone82c2db2012-05-25 14:10:02 -0700610 if (t->model)
611 free(t->model);
612 if (t->device)
613 free(t->device);
Scott Andersone109d262012-04-20 11:21:14 -0700614 if (t->devpath)
615 free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800616
617 memset(t,0xee,sizeof(atransport));
618 free(t);
619
620 update_transports();
621 return;
622 }
623
Mike Lockwood0927bf92009-08-08 12:37:44 -0400624 /* don't create transport threads for inaccessible devices */
625 if (t->connection_state != CS_NOPERM) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800626 /* initial references are the two threads */
Mike Lockwood0927bf92009-08-08 12:37:44 -0400627 t->ref_count = 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800628
Mike Lockwood0927bf92009-08-08 12:37:44 -0400629 if(adb_socketpair(s)) {
630 fatal_errno("cannot open transport socketpair");
631 }
632
leozwangcbf02672014-08-15 09:51:27 -0700633 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400634
635 t->transport_socket = s[0];
636 t->fd = s[1];
637
Mike Lockwood0927bf92009-08-08 12:37:44 -0400638 fdevent_install(&(t->transport_fde),
639 t->transport_socket,
640 transport_socket_events,
641 t);
642
643 fdevent_set(&(t->transport_fde), FDE_READ);
644
645 if(adb_thread_create(&input_thread_ptr, input_thread, t)){
646 fatal_errno("cannot create input thread");
647 }
648
649 if(adb_thread_create(&output_thread_ptr, output_thread, t)){
650 fatal_errno("cannot create output thread");
651 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652 }
653
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800654 adb_mutex_lock(&transport_lock);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700655 /* remove from pending list */
656 t->next->prev = t->prev;
657 t->prev->next = t->next;
658 /* put us on the master device list */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800659 t->next = &transport_list;
660 t->prev = transport_list.prev;
661 t->next->prev = t;
662 t->prev->next = t;
663 adb_mutex_unlock(&transport_lock);
664
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800665 t->disconnects.next = t->disconnects.prev = &t->disconnects;
666
667 update_transports();
668}
669
670void init_transport_registration(void)
671{
672 int s[2];
673
674 if(adb_socketpair(s)){
675 fatal_errno("cannot open transport registration socketpair");
676 }
leozwangcbf02672014-08-15 09:51:27 -0700677 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800678
679 transport_registration_send = s[0];
680 transport_registration_recv = s[1];
681
682 fdevent_install(&transport_registration_fde,
683 transport_registration_recv,
684 transport_registration_func,
685 0);
686
687 fdevent_set(&transport_registration_fde, FDE_READ);
688}
689
690/* the fdevent select pump is single threaded */
691static void register_transport(atransport *transport)
692{
693 tmsg m;
694 m.transport = transport;
695 m.action = 1;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100696 D("transport: %s registered\n", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697 if(transport_write_action(transport_registration_send, &m)) {
698 fatal_errno("cannot write transport registration socket\n");
699 }
700}
701
702static void remove_transport(atransport *transport)
703{
704 tmsg m;
705 m.transport = transport;
706 m.action = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100707 D("transport: %s removed\n", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800708 if(transport_write_action(transport_registration_send, &m)) {
709 fatal_errno("cannot write transport registration socket\n");
710 }
711}
712
713
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400714static void transport_unref_locked(atransport *t)
715{
716 t->ref_count--;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400717 if (t->ref_count == 0) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100718 D("transport: %s unref (kicking and closing)\n", t->serial);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400719 if (!t->kicked) {
720 t->kicked = 1;
721 t->kick(t);
722 }
723 t->close(t);
724 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100725 } else {
726 D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400727 }
728}
729
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800730static void transport_unref(atransport *t)
731{
732 if (t) {
733 adb_mutex_lock(&transport_lock);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400734 transport_unref_locked(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735 adb_mutex_unlock(&transport_lock);
736 }
737}
738
739void add_transport_disconnect(atransport* t, adisconnect* dis)
740{
741 adb_mutex_lock(&transport_lock);
742 dis->next = &t->disconnects;
743 dis->prev = dis->next->prev;
744 dis->prev->next = dis;
745 dis->next->prev = dis;
746 adb_mutex_unlock(&transport_lock);
747}
748
749void remove_transport_disconnect(atransport* t, adisconnect* dis)
750{
751 dis->prev->next = dis->next;
752 dis->next->prev = dis->prev;
753 dis->next = dis->prev = dis;
754}
755
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700756static int qual_char_is_invalid(char ch)
757{
758 if ('A' <= ch && ch <= 'Z')
759 return 0;
760 if ('a' <= ch && ch <= 'z')
761 return 0;
762 if ('0' <= ch && ch <= '9')
763 return 0;
764 return 1;
765}
766
767static int qual_match(const char *to_test,
768 const char *prefix, const char *qual, int sanitize_qual)
769{
770 if (!to_test || !*to_test)
771 /* Return true if both the qual and to_test are null strings. */
772 return !qual || !*qual;
773
774 if (!qual)
775 return 0;
776
777 if (prefix) {
778 while (*prefix) {
779 if (*prefix++ != *to_test++)
780 return 0;
781 }
782 }
783
784 while (*qual) {
785 char ch = *qual++;
786 if (sanitize_qual && qual_char_is_invalid(ch))
787 ch = '_';
788 if (ch != *to_test++)
789 return 0;
790 }
791
792 /* Everything matched so far. Return true if *to_test is a NUL. */
793 return !*to_test;
794}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800795
796atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
797{
798 atransport *t;
799 atransport *result = NULL;
800 int ambiguous = 0;
801
802retry:
803 if (error_out)
804 *error_out = "device not found";
805
806 adb_mutex_lock(&transport_lock);
807 for (t = transport_list.next; t != &transport_list; t = t->next) {
Mike Lockwood37d31112009-08-08 13:53:16 -0400808 if (t->connection_state == CS_NOPERM) {
809 if (error_out)
810 *error_out = "insufficient permissions for device";
811 continue;
812 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400813
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800814 /* check for matching serial number */
815 if (serial) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700816 if ((t->serial && !strcmp(serial, t->serial)) ||
817 (t->devpath && !strcmp(serial, t->devpath)) ||
818 qual_match(serial, "product:", t->product, 0) ||
819 qual_match(serial, "model:", t->model, 1) ||
820 qual_match(serial, "device:", t->device, 0)) {
821 if (result) {
822 if (error_out)
823 *error_out = "more than one device";
824 ambiguous = 1;
825 result = NULL;
826 break;
827 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800828 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700829 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830 } else {
831 if (ttype == kTransportUsb && t->type == kTransportUsb) {
832 if (result) {
833 if (error_out)
834 *error_out = "more than one device";
835 ambiguous = 1;
836 result = NULL;
837 break;
838 }
839 result = t;
840 } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
841 if (result) {
842 if (error_out)
843 *error_out = "more than one emulator";
844 ambiguous = 1;
845 result = NULL;
846 break;
847 }
848 result = t;
849 } else if (ttype == kTransportAny) {
850 if (result) {
851 if (error_out)
852 *error_out = "more than one device and emulator";
853 ambiguous = 1;
854 result = NULL;
855 break;
856 }
857 result = t;
858 }
859 }
860 }
861 adb_mutex_unlock(&transport_lock);
862
863 if (result) {
Benoit Goby77e8e582013-01-15 12:36:47 -0800864 if (result->connection_state == CS_UNAUTHORIZED) {
865 if (error_out)
866 *error_out = "device unauthorized. Please check the confirmation dialog on your device.";
867 result = NULL;
868 }
869
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800870 /* offline devices are ignored -- they are either being born or dying */
871 if (result && result->connection_state == CS_OFFLINE) {
872 if (error_out)
873 *error_out = "device offline";
874 result = NULL;
875 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800876 /* check for required connection state */
877 if (result && state != CS_ANY && result->connection_state != state) {
878 if (error_out)
879 *error_out = "invalid device state";
880 result = NULL;
881 }
882 }
883
884 if (result) {
885 /* found one that we can take */
886 if (error_out)
887 *error_out = NULL;
888 } else if (state != CS_ANY && (serial || !ambiguous)) {
889 adb_sleep_ms(1000);
890 goto retry;
891 }
892
893 return result;
894}
895
896#if ADB_HOST
897static const char *statename(atransport *t)
898{
899 switch(t->connection_state){
900 case CS_OFFLINE: return "offline";
901 case CS_BOOTLOADER: return "bootloader";
902 case CS_DEVICE: return "device";
903 case CS_HOST: return "host";
904 case CS_RECOVERY: return "recovery";
Doug Zongker447f0612012-01-09 14:54:53 -0800905 case CS_SIDELOAD: return "sideload";
Mike Lockwood0927bf92009-08-08 12:37:44 -0400906 case CS_NOPERM: return "no permissions";
Benoit Goby77e8e582013-01-15 12:36:47 -0800907 case CS_UNAUTHORIZED: return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800908 default: return "unknown";
909 }
910}
911
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700912static void add_qual(char **buf, size_t *buf_size,
913 const char *prefix, const char *qual, int sanitize_qual)
914{
915 size_t len;
916 int prefix_len;
917
918 if (!buf || !*buf || !buf_size || !*buf_size || !qual || !*qual)
919 return;
920
921 len = snprintf(*buf, *buf_size, "%s%n%s", prefix, &prefix_len, qual);
922
923 if (sanitize_qual) {
924 char *cp;
925 for (cp = *buf + prefix_len; cp < *buf + len; cp++) {
926 if (qual_char_is_invalid(*cp))
927 *cp = '_';
928 }
929 }
930
931 *buf_size -= len;
932 *buf += len;
933}
934
935static size_t format_transport(atransport *t, char *buf, size_t bufsize,
936 int long_listing)
937{
938 const char* serial = t->serial;
939 if (!serial || !serial[0])
940 serial = "????????????";
941
942 if (!long_listing) {
943 return snprintf(buf, bufsize, "%s\t%s\n", serial, statename(t));
944 } else {
945 size_t len, remaining = bufsize;
946
947 len = snprintf(buf, remaining, "%-22s %s", serial, statename(t));
948 remaining -= len;
949 buf += len;
950
951 add_qual(&buf, &remaining, " ", t->devpath, 0);
952 add_qual(&buf, &remaining, " product:", t->product, 0);
953 add_qual(&buf, &remaining, " model:", t->model, 1);
954 add_qual(&buf, &remaining, " device:", t->device, 0);
955
956 len = snprintf(buf, remaining, "\n");
957 remaining -= len;
958
959 return bufsize - remaining;
960 }
961}
962
963int list_transports(char *buf, size_t bufsize, int long_listing)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964{
965 char* p = buf;
966 char* end = buf + bufsize;
967 int len;
968 atransport *t;
969
970 /* XXX OVERRUN PROBLEMS XXX */
971 adb_mutex_lock(&transport_lock);
972 for(t = transport_list.next; t != &transport_list; t = t->next) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700973 len = format_transport(t, p, end - p, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800974 if (p + len >= end) {
975 /* discard last line if buffer is too short */
976 break;
977 }
978 p += len;
979 }
980 p[0] = 0;
981 adb_mutex_unlock(&transport_lock);
982 return p - buf;
983}
984
985
986/* hack for osx */
987void close_usb_devices()
988{
989 atransport *t;
990
991 adb_mutex_lock(&transport_lock);
992 for(t = transport_list.next; t != &transport_list; t = t->next) {
993 if ( !t->kicked ) {
994 t->kicked = 1;
995 t->kick(t);
996 }
997 }
998 adb_mutex_unlock(&transport_lock);
999}
1000#endif // ADB_HOST
1001
Benoit Goby1c45ee92013-03-29 18:22:36 -07001002int register_socket_transport(int s, const char *serial, int port, int local)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001003{
1004 atransport *t = calloc(1, sizeof(atransport));
Benoit Goby1c45ee92013-03-29 18:22:36 -07001005 atransport *n;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001006 char buff[32];
1007
1008 if (!serial) {
1009 snprintf(buff, sizeof buff, "T-%p", t);
1010 serial = buff;
1011 }
1012 D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -07001013 if (init_socket_transport(t, s, port, local) < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001014 free(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -07001015 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001016 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001017
1018 adb_mutex_lock(&transport_lock);
1019 for (n = pending_list.next; n != &pending_list; n = n->next) {
1020 if (n->serial && !strcmp(serial, n->serial)) {
1021 adb_mutex_unlock(&transport_lock);
1022 free(t);
1023 return -1;
1024 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001025 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001026
1027 for (n = transport_list.next; n != &transport_list; n = n->next) {
1028 if (n->serial && !strcmp(serial, n->serial)) {
1029 adb_mutex_unlock(&transport_lock);
1030 free(t);
1031 return -1;
1032 }
1033 }
1034
1035 t->next = &pending_list;
1036 t->prev = pending_list.prev;
1037 t->next->prev = t;
1038 t->prev->next = t;
1039 t->serial = strdup(serial);
1040 adb_mutex_unlock(&transport_lock);
1041
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001042 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -07001043 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001044}
1045
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001046#if ADB_HOST
1047atransport *find_transport(const char *serial)
1048{
1049 atransport *t;
1050
1051 adb_mutex_lock(&transport_lock);
1052 for(t = transport_list.next; t != &transport_list; t = t->next) {
1053 if (t->serial && !strcmp(serial, t->serial)) {
1054 break;
1055 }
1056 }
1057 adb_mutex_unlock(&transport_lock);
1058
1059 if (t != &transport_list)
1060 return t;
1061 else
1062 return 0;
1063}
1064
1065void unregister_transport(atransport *t)
1066{
1067 adb_mutex_lock(&transport_lock);
1068 t->next->prev = t->prev;
1069 t->prev->next = t->next;
1070 adb_mutex_unlock(&transport_lock);
1071
1072 kick_transport(t);
1073 transport_unref(t);
1074}
1075
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001076// unregisters all non-emulator TCP transports
1077void unregister_all_tcp_transports()
1078{
1079 atransport *t, *next;
1080 adb_mutex_lock(&transport_lock);
1081 for (t = transport_list.next; t != &transport_list; t = next) {
1082 next = t->next;
1083 if (t->type == kTransportLocal && t->adb_port == 0) {
1084 t->next->prev = t->prev;
1085 t->prev->next = next;
1086 // we cannot call kick_transport when holding transport_lock
1087 if (!t->kicked)
1088 {
1089 t->kicked = 1;
1090 t->kick(t);
1091 }
1092 transport_unref_locked(t);
1093 }
1094 }
1095
1096 adb_mutex_unlock(&transport_lock);
1097}
1098
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001099#endif
1100
Scott Andersone109d262012-04-20 11:21:14 -07001101void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001102{
1103 atransport *t = calloc(1, sizeof(atransport));
1104 D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
1105 serial ? serial : "");
Mike Lockwood0927bf92009-08-08 12:37:44 -04001106 init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001107 if(serial) {
1108 t->serial = strdup(serial);
1109 }
Scott Andersone109d262012-04-20 11:21:14 -07001110 if(devpath) {
1111 t->devpath = strdup(devpath);
1112 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001113
1114 adb_mutex_lock(&transport_lock);
1115 t->next = &pending_list;
1116 t->prev = pending_list.prev;
1117 t->next->prev = t;
1118 t->prev->next = t;
1119 adb_mutex_unlock(&transport_lock);
1120
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001121 register_transport(t);
1122}
1123
Mike Lockwood0927bf92009-08-08 12:37:44 -04001124/* this should only be used for transports with connection_state == CS_NOPERM */
1125void unregister_usb_transport(usb_handle *usb)
1126{
1127 atransport *t;
1128 adb_mutex_lock(&transport_lock);
1129 for(t = transport_list.next; t != &transport_list; t = t->next) {
1130 if (t->usb == usb && t->connection_state == CS_NOPERM) {
1131 t->next->prev = t->prev;
1132 t->prev->next = t->next;
1133 break;
1134 }
1135 }
1136 adb_mutex_unlock(&transport_lock);
1137}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001138
1139#undef TRACE_TAG
1140#define TRACE_TAG TRACE_RWX
1141
1142int readx(int fd, void *ptr, size_t len)
1143{
1144 char *p = ptr;
1145 int r;
1146#if ADB_TRACE
Elliott Hughesccecf142014-01-16 10:53:11 -08001147 size_t len0 = len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001148#endif
Elliott Hughesccecf142014-01-16 10:53:11 -08001149 D("readx: fd=%d wanted=%zu\n", fd, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001150 while(len > 0) {
1151 r = adb_read(fd, p, len);
1152 if(r > 0) {
1153 len -= r;
1154 p += r;
1155 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001156 if (r < 0) {
1157 D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
1158 if (errno == EINTR)
1159 continue;
1160 } else {
1161 D("readx: fd=%d disconnected\n", fd);
1162 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001163 return -1;
1164 }
1165 }
1166
1167#if ADB_TRACE
Elliott Hughesccecf142014-01-16 10:53:11 -08001168 D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
Spencer Low0de77ff2015-01-25 16:57:16 -08001169 if (ADB_TRACING) {
1170 dump_hex( ptr, len0 );
1171 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001172#endif
1173 return 0;
1174}
1175
1176int writex(int fd, const void *ptr, size_t len)
1177{
1178 char *p = (char*) ptr;
1179 int r;
1180
1181#if ADB_TRACE
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001182 D("writex: fd=%d len=%d: ", fd, (int)len);
Spencer Low0de77ff2015-01-25 16:57:16 -08001183 if (ADB_TRACING) {
1184 dump_hex( ptr, len );
1185 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001186#endif
1187 while(len > 0) {
1188 r = adb_write(fd, p, len);
1189 if(r > 0) {
1190 len -= r;
1191 p += r;
1192 } else {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001193 if (r < 0) {
1194 D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
1195 if (errno == EINTR)
1196 continue;
JP Abgrall5b0bb482014-03-06 19:40:45 -08001197 if (errno == EAGAIN) {
Snild Dolkow2264e7c2014-01-30 10:08:38 +01001198 adb_sleep_ms(1); // just yield some cpu time
1199 continue;
1200 }
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001201 } else {
1202 D("writex: fd=%d disconnected\n", fd);
1203 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001204 return -1;
1205 }
1206 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001207 return 0;
1208}
1209
1210int check_header(apacket *p)
1211{
1212 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
1213 D("check_header(): invalid magic\n");
1214 return -1;
1215 }
1216
1217 if(p->msg.data_length > MAX_PAYLOAD) {
1218 D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
1219 return -1;
1220 }
1221
1222 return 0;
1223}
1224
1225int check_data(apacket *p)
1226{
1227 unsigned count, sum;
1228 unsigned char *x;
1229
1230 count = p->msg.data_length;
1231 x = p->data;
1232 sum = 0;
1233 while(count-- > 0) {
1234 sum += *x++;
1235 }
1236
1237 if(sum != p->msg.data_check) {
1238 return -1;
1239 } else {
1240 return 0;
1241 }
1242}