blob: 439826a0241447bc422159d3ed3e8ab8e4ff78e2 [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_USB
18
19#include "sysdeps.h"
20
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080022#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <linux/usbdevice_fs.h>
26#include <linux/version.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <sys/time.h>
32#include <sys/types.h>
33#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080034#include <linux/usb/ch9.h>
Elliott Hughes9309ecb2015-04-27 14:20:17 -070035
36#include <base/file.h>
37#include <base/stringprintf.h>
38#include <base/strings.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040#include "adb.h"
Dan Albert76649012015-02-24 15:51:19 -080041#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042
43/* usb scan debugging is waaaay too verbose */
44#define DBGX(x...)
45
JP Abgrall408fa572011-03-16 15:57:42 -070046ADB_MUTEX_DEFINE( usb_lock );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080047
48struct usb_handle
49{
50 usb_handle *prev;
51 usb_handle *next;
52
53 char fname[64];
54 int desc;
55 unsigned char ep_in;
56 unsigned char ep_out;
57
58 unsigned zero_mask;
Mike Lockwood0927bf92009-08-08 12:37:44 -040059 unsigned writeable;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
61 struct usbdevfs_urb urb_in;
62 struct usbdevfs_urb urb_out;
63
64 int urb_in_busy;
65 int urb_out_busy;
66 int dead;
67
68 adb_cond_t notify;
69 adb_mutex_t lock;
70
71 // for garbage collecting disconnected devices
72 int mark;
73
74 // ID of thread currently in REAPURB
75 pthread_t reaper_thread;
76};
77
78static usb_handle handle_list = {
79 .prev = &handle_list,
80 .next = &handle_list,
81};
82
83static int known_device(const char *dev_name)
84{
85 usb_handle *usb;
86
87 adb_mutex_lock(&usb_lock);
88 for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
89 if(!strcmp(usb->fname, dev_name)) {
90 // set mark flag to indicate this device is still alive
91 usb->mark = 1;
92 adb_mutex_unlock(&usb_lock);
93 return 1;
94 }
95 }
96 adb_mutex_unlock(&usb_lock);
97 return 0;
98}
99
100static void kick_disconnected_devices()
101{
102 usb_handle *usb;
103
104 adb_mutex_lock(&usb_lock);
105 // kick any devices in the device list that were not found in the device scan
106 for(usb = handle_list.next; usb != &handle_list; usb = usb->next){
107 if (usb->mark == 0) {
108 usb_kick(usb);
109 } else {
110 usb->mark = 0;
111 }
112 }
113 adb_mutex_unlock(&usb_lock);
114
115}
116
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800117static inline int badname(const char *name)
118{
119 while(*name) {
120 if(!isdigit(*name++)) return 1;
121 }
122 return 0;
123}
124
Mike Lockwood0927bf92009-08-08 12:37:44 -0400125static void find_usb_device(const char *base,
126 void (*register_device_callback)
Scott Andersone109d262012-04-20 11:21:14 -0700127 (const char *, const char *, unsigned char, unsigned char, int, int, unsigned))
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800128{
129 char busname[32], devname[32];
130 unsigned char local_ep_in, local_ep_out;
131 DIR *busdir , *devdir ;
132 struct dirent *de;
133 int fd ;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800134
135 busdir = opendir(base);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400136 if(busdir == 0) return;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800137
138 while((de = readdir(busdir)) != 0) {
139 if(badname(de->d_name)) continue;
140
141 snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
142 devdir = opendir(busname);
143 if(devdir == 0) continue;
144
145// DBGX("[ scanning %s ]\n", busname);
146 while((de = readdir(devdir))) {
Mike Lockwoodb5966082011-01-07 23:18:14 -0500147 unsigned char devdesc[4096];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800148 unsigned char* bufptr = devdesc;
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500149 unsigned char* bufend;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 struct usb_device_descriptor* device;
151 struct usb_config_descriptor* config;
152 struct usb_interface_descriptor* interface;
153 struct usb_endpoint_descriptor *ep1, *ep2;
154 unsigned zero_mask = 0;
155 unsigned vid, pid;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800156 size_t desclength;
157
158 if(badname(de->d_name)) continue;
159 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
160
161 if(known_device(devname)) {
162 DBGX("skipping %s\n", devname);
163 continue;
164 }
165
166// DBGX("[ scanning %s ]\n", devname);
Nick Kralevich9866a662014-07-18 20:57:35 -0700167 if((fd = unix_open(devname, O_RDONLY | O_CLOEXEC)) < 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168 continue;
169 }
170
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700171 desclength = unix_read(fd, devdesc, sizeof(devdesc));
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500172 bufend = bufptr + desclength;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800173
174 // should have device and configuration descriptors, and atleast two endpoints
175 if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
Elliott Hughesccecf142014-01-16 10:53:11 -0800176 D("desclength %zu is too small\n", desclength);
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700177 unix_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800178 continue;
179 }
180
181 device = (struct usb_device_descriptor*)bufptr;
182 bufptr += USB_DT_DEVICE_SIZE;
183
184 if((device->bLength != USB_DT_DEVICE_SIZE) || (device->bDescriptorType != USB_DT_DEVICE)) {
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700185 unix_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800186 continue;
187 }
188
Marcus Comstedt6f703a22010-09-22 20:09:44 +0200189 vid = device->idVendor;
190 pid = device->idProduct;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800191 DBGX("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
192
193 // should have config descriptor next
194 config = (struct usb_config_descriptor *)bufptr;
195 bufptr += USB_DT_CONFIG_SIZE;
196 if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
197 D("usb_config_descriptor not found\n");
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700198 unix_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800199 continue;
200 }
201
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500202 // loop through all the descriptors and look for the ADB interface
203 while (bufptr < bufend) {
204 unsigned char length = bufptr[0];
205 unsigned char type = bufptr[1];
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500207 if (type == USB_DT_INTERFACE) {
208 interface = (struct usb_interface_descriptor *)bufptr;
209 bufptr += length;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800210
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500211 if (length != USB_DT_INTERFACE_SIZE) {
212 D("interface descriptor has wrong size\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800213 break;
214 }
215
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500216 DBGX("bInterfaceClass: %d, bInterfaceSubClass: %d,"
217 "bInterfaceProtocol: %d, bNumEndpoints: %d\n",
218 interface->bInterfaceClass, interface->bInterfaceSubClass,
219 interface->bInterfaceProtocol, interface->bNumEndpoints);
220
221 if (interface->bNumEndpoints == 2 &&
222 is_adb_interface(vid, pid, interface->bInterfaceClass,
223 interface->bInterfaceSubClass, interface->bInterfaceProtocol)) {
224
Scott Andersone109d262012-04-20 11:21:14 -0700225 struct stat st;
226 char pathbuf[128];
227 char link[256];
228 char *devpath = NULL;
229
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500230 DBGX("looking for bulk endpoints\n");
231 // looks like ADB...
232 ep1 = (struct usb_endpoint_descriptor *)bufptr;
233 bufptr += USB_DT_ENDPOINT_SIZE;
Ingo Rohloff58b01e02014-05-16 21:51:41 +0200234 // For USB 3.0 SuperSpeed devices, skip potential
235 // USB 3.0 SuperSpeed Endpoint Companion descriptor
236 if (bufptr+2 <= devdesc + desclength &&
237 bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
238 bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
239 bufptr += USB_DT_SS_EP_COMP_SIZE;
240 }
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500241 ep2 = (struct usb_endpoint_descriptor *)bufptr;
242 bufptr += USB_DT_ENDPOINT_SIZE;
Ingo Rohloff58b01e02014-05-16 21:51:41 +0200243 if (bufptr+2 <= devdesc + desclength &&
244 bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
245 bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
246 bufptr += USB_DT_SS_EP_COMP_SIZE;
247 }
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500248
249 if (bufptr > devdesc + desclength ||
250 ep1->bLength != USB_DT_ENDPOINT_SIZE ||
251 ep1->bDescriptorType != USB_DT_ENDPOINT ||
252 ep2->bLength != USB_DT_ENDPOINT_SIZE ||
253 ep2->bDescriptorType != USB_DT_ENDPOINT) {
254 D("endpoints not found\n");
255 break;
256 }
257
258 // both endpoints should be bulk
259 if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
260 ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
261 D("bulk endpoints not found\n");
262 continue;
263 }
264 /* aproto 01 needs 0 termination */
265 if(interface->bInterfaceProtocol == 0x01) {
266 zero_mask = ep1->wMaxPacketSize - 1;
267 }
268
269 // we have a match. now we just need to figure out which is in and which is out.
270 if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
271 local_ep_in = ep1->bEndpointAddress;
272 local_ep_out = ep2->bEndpointAddress;
273 } else {
274 local_ep_in = ep2->bEndpointAddress;
275 local_ep_out = ep1->bEndpointAddress;
276 }
277
Scott Andersone109d262012-04-20 11:21:14 -0700278 // Determine the device path
279 if (!fstat(fd, &st) && S_ISCHR(st.st_mode)) {
280 char *slash;
281 ssize_t link_len;
282 snprintf(pathbuf, sizeof(pathbuf), "/sys/dev/char/%d:%d",
283 major(st.st_rdev), minor(st.st_rdev));
284 link_len = readlink(pathbuf, link, sizeof(link) - 1);
285 if (link_len > 0) {
286 link[link_len] = '\0';
287 slash = strrchr(link, '/');
288 if (slash) {
289 snprintf(pathbuf, sizeof(pathbuf),
290 "usb:%s", slash + 1);
291 devpath = pathbuf;
292 }
293 }
294 }
295
296 register_device_callback(devname, devpath,
297 local_ep_in, local_ep_out,
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500298 interface->bInterfaceNumber, device->iSerialNumber, zero_mask);
299 break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301 } else {
Mike Lockwood07e8f7e2010-01-17 00:52:27 -0500302 bufptr += length;
303 }
304 } // end of while
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800305
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700306 unix_close(fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307 } // end of devdir while
308 closedir(devdir);
309 } //end of busdir while
310 closedir(busdir);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800311}
312
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313static int usb_bulk_write(usb_handle *h, const void *data, int len)
314{
315 struct usbdevfs_urb *urb = &h->urb_out;
316 int res;
Mike Lockwoodfe582b52010-02-19 17:45:57 -0500317 struct timeval tv;
318 struct timespec ts;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800319
320 memset(urb, 0, sizeof(*urb));
321 urb->type = USBDEVFS_URB_TYPE_BULK;
322 urb->endpoint = h->ep_out;
323 urb->status = -1;
324 urb->buffer = (void*) data;
325 urb->buffer_length = len;
326
327 D("++ write ++\n");
328
329 adb_mutex_lock(&h->lock);
330 if(h->dead) {
331 res = -1;
332 goto fail;
333 }
334 do {
335 res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
336 } while((res < 0) && (errno == EINTR));
337
338 if(res < 0) {
339 goto fail;
340 }
341
342 res = -1;
343 h->urb_out_busy = 1;
344 for(;;) {
Mike Lockwoodfe582b52010-02-19 17:45:57 -0500345 /* time out after five seconds */
346 gettimeofday(&tv, NULL);
347 ts.tv_sec = tv.tv_sec + 5;
348 ts.tv_nsec = tv.tv_usec * 1000L;
349 res = pthread_cond_timedwait(&h->notify, &h->lock, &ts);
350 if(res < 0 || h->dead) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800351 break;
352 }
353 if(h->urb_out_busy == 0) {
354 if(urb->status == 0) {
355 res = urb->actual_length;
356 }
357 break;
358 }
359 }
360fail:
361 adb_mutex_unlock(&h->lock);
362 D("-- write --\n");
363 return res;
364}
365
366static int usb_bulk_read(usb_handle *h, void *data, int len)
367{
368 struct usbdevfs_urb *urb = &h->urb_in;
369 struct usbdevfs_urb *out = NULL;
370 int res;
371
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100372 D("++ usb_bulk_read ++\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 memset(urb, 0, sizeof(*urb));
374 urb->type = USBDEVFS_URB_TYPE_BULK;
375 urb->endpoint = h->ep_in;
376 urb->status = -1;
377 urb->buffer = data;
378 urb->buffer_length = len;
379
380
381 adb_mutex_lock(&h->lock);
382 if(h->dead) {
383 res = -1;
384 goto fail;
385 }
386 do {
387 res = ioctl(h->desc, USBDEVFS_SUBMITURB, urb);
388 } while((res < 0) && (errno == EINTR));
389
390 if(res < 0) {
391 goto fail;
392 }
393
394 h->urb_in_busy = 1;
395 for(;;) {
396 D("[ reap urb - wait ]\n");
397 h->reaper_thread = pthread_self();
398 adb_mutex_unlock(&h->lock);
399 res = ioctl(h->desc, USBDEVFS_REAPURB, &out);
JP Abgrall408fa572011-03-16 15:57:42 -0700400 int saved_errno = errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 adb_mutex_lock(&h->lock);
402 h->reaper_thread = 0;
403 if(h->dead) {
404 res = -1;
405 break;
406 }
407 if(res < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700408 if(saved_errno == EINTR) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 continue;
410 }
411 D("[ reap urb - error ]\n");
412 break;
413 }
414 D("[ urb @%p status = %d, actual = %d ]\n",
415 out, out->status, out->actual_length);
416
417 if(out == &h->urb_in) {
418 D("[ reap urb - IN complete ]\n");
419 h->urb_in_busy = 0;
420 if(urb->status == 0) {
421 res = urb->actual_length;
422 } else {
423 res = -1;
424 }
425 break;
426 }
427 if(out == &h->urb_out) {
428 D("[ reap urb - OUT compelete ]\n");
429 h->urb_out_busy = 0;
430 adb_cond_broadcast(&h->notify);
431 }
432 }
433fail:
434 adb_mutex_unlock(&h->lock);
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100435 D("-- usb_bulk_read --\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 return res;
437}
438
439
440int usb_write(usb_handle *h, const void *_data, int len)
441{
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100442 D("++ usb_write ++\n");
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100443
444 unsigned char *data = (unsigned char*) _data;
445 int n = usb_bulk_write(h, data, len);
446 if(n != len) {
447 D("ERROR: n = %d, errno = %d (%s)\n",
448 n, errno, strerror(errno));
449 return -1;
450 }
451
452 if(h->zero_mask && !(len & h->zero_mask)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800453 /* if we need 0-markers and our transfer
454 ** is an even multiple of the packet size,
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100455 ** then send the zero markers.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800456 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800457 n = usb_bulk_write(h, _data, 0);
458 return n;
459 }
460
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100461 D("-- usb_write --\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800462 return 0;
463}
464
465int usb_read(usb_handle *h, void *_data, int len)
466{
467 unsigned char *data = (unsigned char*) _data;
468 int n;
469
470 D("++ usb_read ++\n");
471 while(len > 0) {
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100472 int xfer = len;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800473
474 D("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
475 n = usb_bulk_read(h, data, xfer);
476 D("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
477 if(n != xfer) {
478 if((errno == ETIMEDOUT) && (h->desc != -1)) {
479 D("[ timeout ]\n");
480 if(n > 0){
481 data += n;
482 len -= n;
483 }
484 continue;
485 }
486 D("ERROR: n = %d, errno = %d (%s)\n",
487 n, errno, strerror(errno));
488 return -1;
489 }
490
491 len -= xfer;
492 data += xfer;
493 }
494
495 D("-- usb_read --\n");
496 return 0;
497}
498
499void usb_kick(usb_handle *h)
500{
501 D("[ kicking %p (fd = %d) ]\n", h, h->desc);
502 adb_mutex_lock(&h->lock);
503 if(h->dead == 0) {
504 h->dead = 1;
505
Mike Lockwood0927bf92009-08-08 12:37:44 -0400506 if (h->writeable) {
507 /* HACK ALERT!
508 ** Sometimes we get stuck in ioctl(USBDEVFS_REAPURB).
509 ** This is a workaround for that problem.
510 */
511 if (h->reaper_thread) {
512 pthread_kill(h->reaper_thread, SIGALRM);
513 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800514
Mike Lockwood0927bf92009-08-08 12:37:44 -0400515 /* cancel any pending transactions
516 ** these will quietly fail if the txns are not active,
517 ** but this ensures that a reader blocked on REAPURB
518 ** will get unblocked
519 */
520 ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_in);
521 ioctl(h->desc, USBDEVFS_DISCARDURB, &h->urb_out);
522 h->urb_in.status = -ENODEV;
523 h->urb_out.status = -ENODEV;
524 h->urb_in_busy = 0;
525 h->urb_out_busy = 0;
526 adb_cond_broadcast(&h->notify);
527 } else {
528 unregister_usb_transport(h);
529 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800530 }
531 adb_mutex_unlock(&h->lock);
532}
533
534int usb_close(usb_handle *h)
535{
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100536 D("++ usb close ++\n");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800537 adb_mutex_lock(&usb_lock);
538 h->next->prev = h->prev;
539 h->prev->next = h->next;
540 h->prev = 0;
541 h->next = 0;
542
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700543 unix_close(h->desc);
Nanik Tolaramb627a0e2015-02-18 22:53:37 +1100544 D("-- usb closed %p (fd = %d) --\n", h, h->desc);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800545 adb_mutex_unlock(&usb_lock);
546
547 free(h);
548 return 0;
549}
550
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700551static void register_device(const char* dev_name, const char* dev_path,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800552 unsigned char ep_in, unsigned char ep_out,
Dan Albertd99d9022015-05-06 16:48:52 -0700553 int interface, int serial_index,
554 unsigned zero_mask) {
555 // Since Linux will not reassign the device ID (and dev_name) as long as the
556 // device is open, we can add to the list here once we open it and remove
557 // from the list when we're finally closed and everything will work out
558 // fine.
559 //
560 // If we have a usb_handle on the list 'o handles with a matching name, we
561 // have no further work to do.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800562 adb_mutex_lock(&usb_lock);
Elliott Hughesce6363b2015-04-25 14:44:23 -0700563 for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
Dan Albertbac34742015-02-25 17:51:28 -0800564 if (!strcmp(usb->fname, dev_name)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 adb_mutex_unlock(&usb_lock);
566 return;
567 }
568 }
569 adb_mutex_unlock(&usb_lock);
570
Elliott Hughesce6363b2015-04-25 14:44:23 -0700571 D("[ usb located new device %s (%d/%d/%d) ]\n", dev_name, ep_in, ep_out, interface);
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700572 usb_handle* usb = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
573 if (usb == nullptr) fatal("couldn't allocate usb_handle");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800574 strcpy(usb->fname, dev_name);
575 usb->ep_in = ep_in;
576 usb->ep_out = ep_out;
577 usb->zero_mask = zero_mask;
Mike Lockwood0927bf92009-08-08 12:37:44 -0400578 usb->writeable = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800579
580 adb_cond_init(&usb->notify, 0);
581 adb_mutex_init(&usb->lock, 0);
Dan Albertd99d9022015-05-06 16:48:52 -0700582 // Initialize mark to 1 so we don't get garbage collected after the device
583 // scan.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800584 usb->mark = 1;
585 usb->reaper_thread = 0;
586
Nick Kralevich9866a662014-07-18 20:57:35 -0700587 usb->desc = unix_open(usb->fname, O_RDWR | O_CLOEXEC);
Elliott Hughesce6363b2015-04-25 14:44:23 -0700588 if (usb->desc == -1) {
589 // Opening RW failed, so see if we have RO access.
Nick Kralevich9866a662014-07-18 20:57:35 -0700590 usb->desc = unix_open(usb->fname, O_RDONLY | O_CLOEXEC);
Elliott Hughesce6363b2015-04-25 14:44:23 -0700591 if (usb->desc == -1) {
592 D("[ usb open %s failed: %s]\n", usb->fname, strerror(errno));
593 free(usb);
594 return;
595 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400596 usb->writeable = 0;
Elliott Hughesce6363b2015-04-25 14:44:23 -0700597 }
598
Dan Albertd99d9022015-05-06 16:48:52 -0700599 D("[ usb opened %s%s, fd=%d]\n", usb->fname,
600 (usb->writeable ? "" : " (read-only)"), usb->desc);
Elliott Hughesce6363b2015-04-25 14:44:23 -0700601
602 if (usb->writeable) {
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700603 if (ioctl(usb->desc, USBDEVFS_CLAIMINTERFACE, &interface) != 0) {
Dan Albertd99d9022015-05-06 16:48:52 -0700604 D("[ usb ioctl(%d, USBDEVFS_CLAIMINTERFACE) failed: %s]\n",
605 usb->desc, strerror(errno));
Spencer Low6ac5d7d2015-05-22 20:09:06 -0700606 unix_close(usb->desc);
Elliott Hughesce6363b2015-04-25 14:44:23 -0700607 free(usb);
608 return;
609 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400610 }
611
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700612 // Read the device's serial number.
Dan Albertd99d9022015-05-06 16:48:52 -0700613 std::string serial_path = android::base::StringPrintf(
614 "/sys/bus/usb/devices/%s/serial", dev_path + 4);
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700615 std::string serial;
616 if (!android::base::ReadFileToString(serial_path, &serial)) {
617 D("[ usb read %s failed: %s ]\n", serial_path.c_str(), strerror(errno));
Dan Albertd99d9022015-05-06 16:48:52 -0700618 // We don't actually want to treat an unknown serial as an error because
619 // devices aren't able to communicate a serial number in early bringup.
620 // http://b/20883914
621 serial = "";
Mike Lockwood0927bf92009-08-08 12:37:44 -0400622 }
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700623 serial = android::base::Trim(serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800624
Dan Albertd99d9022015-05-06 16:48:52 -0700625 // Add to the end of the active handles.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800626 adb_mutex_lock(&usb_lock);
627 usb->next = &handle_list;
628 usb->prev = handle_list.prev;
629 usb->prev->next = usb;
630 usb->next->prev = usb;
631 adb_mutex_unlock(&usb_lock);
632
Elliott Hughes9309ecb2015-04-27 14:20:17 -0700633 register_usb_transport(usb, serial.c_str(), dev_path, usb->writeable);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800634}
635
Dan Albertd99d9022015-05-06 16:48:52 -0700636static void* device_poll_thread(void* unused) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637 D("Created device thread\n");
Dan Albertd99d9022015-05-06 16:48:52 -0700638 while (true) {
639 // TODO: Use inotify.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800640 find_usb_device("/dev/bus/usb", register_device);
641 kick_disconnected_devices();
642 sleep(1);
643 }
Dan Albertd99d9022015-05-06 16:48:52 -0700644 return nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800645}
646
Dan Albertd99d9022015-05-06 16:48:52 -0700647static void sigalrm_handler(int signo) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800648 // don't need to do anything here
649}
650
651void usb_init()
652{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800653 struct sigaction actions;
654
655 memset(&actions, 0, sizeof(actions));
656 sigemptyset(&actions.sa_mask);
657 actions.sa_flags = 0;
658 actions.sa_handler = sigalrm_handler;
659 sigaction(SIGALRM,& actions, NULL);
660
Elliott Hughes9b0f3542015-05-05 13:41:21 -0700661 if (!adb_thread_create(device_poll_thread, nullptr)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800662 fatal_errno("cannot create input thread");
663 }
664}