blob: dbc7962cb6ca88a1f2f66f52e2c4eb49e573680c [file] [log] [blame]
Mike Lockwood30ff2c72010-05-09 16:23:47 -04001/*
2 * Copyright (C) 2010 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
Mike Lockwoode15af092010-06-10 10:20:49 -040017// #define DEBUG 1
18#if DEBUG
19
20#ifdef USE_LIBLOG
21#define LOG_TAG "usbhost"
22#include "utils/Log.h"
23#define D LOGD
24#else
25#define D printf
26#endif
27
28#else
29#define D(...)
30#endif
31
Mike Lockwood30ff2c72010-05-09 16:23:47 -040032#include <stdio.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <string.h>
36
37#include <sys/ioctl.h>
38#include <sys/types.h>
39#include <sys/time.h>
40#include <sys/inotify.h>
41#include <dirent.h>
42#include <fcntl.h>
43#include <errno.h>
44#include <ctype.h>
45#include <pthread.h>
46
47#include <linux/usbdevice_fs.h>
48#include <linux/version.h>
49#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
50#include <linux/usb/ch9.h>
51#else
52#include <linux/usb_ch9.h>
53#endif
54#include <asm/byteorder.h>
55
56#include "usbhost/usbhost.h"
57
58#define USB_FS_DIR "/dev/bus/usb"
Mike Lockwood203f1022010-05-27 10:12:03 -040059#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d"
Mike Lockwood7d700f82010-12-29 08:47:29 -050060#define USB_FS_ID_FORMAT "/dev/bus/usb/%03d/%03d"
Mike Lockwood30ff2c72010-05-09 16:23:47 -040061
Mike Lockwood30ff2c72010-05-09 16:23:47 -040062
Mike Lockwood6ac3aa12010-05-25 08:10:02 -040063struct usb_host_context {
Mike Lockwood7a96ba42010-07-01 11:33:41 -040064 int fd;
Mike Lockwood6ac3aa12010-05-25 08:10:02 -040065};
66
Mike Lockwood30ff2c72010-05-09 16:23:47 -040067struct usb_device {
68 char dev_name[64];
69 unsigned char desc[256];
70 int desc_length;
71 int fd;
72 int writeable;
73};
74
75struct usb_endpoint
76{
77 struct usb_device *dev;
78 struct usb_endpoint_descriptor desc;
79 struct usbdevfs_urb urb;
80};
81
Mike Lockwood30ff2c72010-05-09 16:23:47 -040082static inline int badname(const char *name)
83{
84 while(*name) {
85 if(!isdigit(*name++)) return 1;
86 }
87 return 0;
88}
89
Mike Lockwood7a96ba42010-07-01 11:33:41 -040090/* returns true if one of the callbacks indicates we are done */
91static int find_existing_devices(usb_device_added_cb added_cb,
92 usb_device_removed_cb removed_cb,
93 void *client_data)
Mike Lockwood30ff2c72010-05-09 16:23:47 -040094{
95 char busname[32], devname[32];
96 DIR *busdir , *devdir ;
97 struct dirent *de;
Mike Lockwood7a96ba42010-07-01 11:33:41 -040098 int done = 0;
Mike Lockwood30ff2c72010-05-09 16:23:47 -040099
100 busdir = opendir(USB_FS_DIR);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400101 if(busdir == 0) return 1;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400102
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400103 while ((de = readdir(busdir)) != 0 && !done) {
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400104 if(badname(de->d_name)) continue;
105
106 snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name);
107 devdir = opendir(busname);
108 if(devdir == 0) continue;
109
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400110 while ((de = readdir(devdir)) && !done) {
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400111 if(badname(de->d_name)) continue;
112
113 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400114 done = added_cb(devname, client_data);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400115 } // end of devdir while
116 closedir(devdir);
117 } //end of busdir while
118 closedir(busdir);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400119
120 return done;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400121}
122
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400123struct usb_host_context *usb_host_init()
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400124{
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400125 struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));
126 if (!context) {
127 fprintf(stderr, "out of memory in usb_host_context\n");
128 return NULL;
129 }
130 context->fd = inotify_init();
131 if (context->fd < 0) {
132 fprintf(stderr, "inotify_init failed\n");
133 free(context);
134 return NULL;
135 }
136 return context;
137}
138
139void usb_host_cleanup(struct usb_host_context *context)
140{
141 close(context->fd);
142 free(context);
143}
144
145void usb_host_run(struct usb_host_context *context,
146 usb_device_added_cb added_cb,
147 usb_device_removed_cb removed_cb,
Mike Lockwooda8055192010-07-19 20:15:15 -0400148 usb_discovery_done_cb discovery_done_cb,
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400149 void *client_data)
150{
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400151 struct inotify_event* event;
152 char event_buf[512];
153 char path[100];
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400154 int i, ret, done = 0;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400155 int wd, wds[10];
156 int wd_count = sizeof(wds) / sizeof(wds[0]);
157
158 D("Created device discovery thread\n");
159
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400160 /* watch for files added and deleted within USB_FS_DIR */
161 memset(wds, 0, sizeof(wds));
162 /* watch the root for new subdirectories */
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400163 wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400164 if (wds[0] < 0) {
165 fprintf(stderr, "inotify_add_watch failed\n");
Mike Lockwoode8849d12010-07-20 16:31:42 -0400166 if (discovery_done_cb)
167 discovery_done_cb(client_data);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400168 return;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400169 }
170
171 /* watch existing subdirectories of USB_FS_DIR */
172 for (i = 1; i < wd_count; i++) {
173 snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400174 ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400175 if (ret > 0)
176 wds[i] = ret;
177 }
178
179 /* check for existing devices first, after we have inotify set up */
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400180 done = find_existing_devices(added_cb, removed_cb, client_data);
Mike Lockwooda8055192010-07-19 20:15:15 -0400181 if (discovery_done_cb)
182 done |= discovery_done_cb(client_data);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400183
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400184 while (!done) {
185 ret = read(context->fd, event_buf, sizeof(event_buf));
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400186 if (ret >= (int)sizeof(struct inotify_event)) {
187 event = (struct inotify_event *)event_buf;
188 wd = event->wd;
189 if (wd == wds[0]) {
190 i = atoi(event->name);
191 snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name);
192 D("new subdirectory %s: index: %d\n", path, i);
193 if (i > 0 && i < wd_count) {
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400194 ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400195 if (ret > 0)
196 wds[i] = ret;
197 }
198 } else {
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400199 for (i = 1; i < wd_count && !done; i++) {
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400200 if (wd == wds[i]) {
201 snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name);
202 if (event->mask == IN_CREATE) {
203 D("new device %s\n", path);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400204 done = added_cb(path, client_data);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400205 } else if (event->mask == IN_DELETE) {
206 D("gone device %s\n", path);
Mike Lockwood7a96ba42010-07-01 11:33:41 -0400207 done = removed_cb(path, client_data);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400208 }
209 }
210 }
211 }
212 }
213 }
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400214}
215
216struct usb_device *usb_device_open(const char *dev_name)
217{
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800218 int fd, did_retry = 0, writeable = 1;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400219
220retry:
221 fd = open(dev_name, O_RDWR);
222 if (fd < 0) {
223 /* if we fail, see if have read-only access */
224 fd = open(dev_name, O_RDONLY);
Mike Lockwoode15af092010-06-10 10:20:49 -0400225 D("usb_device_open open returned %d errno %d\n", fd, errno);
226 if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400227 /* work around race condition between inotify and permissions management */
228 sleep(1);
229 did_retry = 1;
230 goto retry;
231 }
232
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800233 if (fd < 0)
234 return NULL;
235 writeable = 0;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400236 D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
237 }
238
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800239 struct usb_device* result = usb_device_new(dev_name, fd);
240 if (result)
241 result->writeable = writeable;
242 return result;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400243}
244
245void usb_device_close(struct usb_device *device)
246{
247 close(device->fd);
248 free(device);
249}
250
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800251struct usb_device *usb_device_new(const char *dev_name, int fd)
252{
253 struct usb_device *device = calloc(1, sizeof(struct usb_device));
254 int length;
255
256 if (lseek(fd, 0, SEEK_SET) != 0)
257 goto failed;
258 length = read(fd, device->desc, sizeof(device->desc));
259 D("usb_device_new read returned %d errno %d\n", fd, errno);
260 if (length < 0)
261 goto failed;
262
Mike Lockwood93aff722010-12-15 12:58:04 -0800263 strncpy(device->dev_name, dev_name, sizeof(device->dev_name) - 1);
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800264 device->fd = fd;
265 device->desc_length = length;
266 // assume we are writeable, since usb_device_get_fd will only return writeable fds
267 device->writeable = 1;
268 return device;
269
270failed:
271 close(fd);
272 free(device);
273 return NULL;
274}
275
276static int usb_device_reopen_writeable(struct usb_device *device)
277{
278 if (device->writeable)
279 return 1;
280
281 int fd = open(device->dev_name, O_RDWR);
282 if (fd >= 0) {
283 close(device->fd);
284 device->fd = fd;
285 device->writeable = 1;
286 return 1;
287 }
288 D("usb_device_reopen_writeable failed errno %d\n", errno);
289 return 0;
290}
291
292int usb_device_get_fd(struct usb_device *device)
293{
294 if (!usb_device_reopen_writeable(device))
295 return -1;
296 return device->fd;
297}
298
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400299const char* usb_device_get_name(struct usb_device *device)
300{
301 return device->dev_name;
302}
303
Mike Lockwood203f1022010-05-27 10:12:03 -0400304int usb_device_get_unique_id(struct usb_device *device)
305{
306 int bus = 0, dev = 0;
307 sscanf(device->dev_name, USB_FS_ID_SCANNER, &bus, &dev);
308 return bus * 1000 + dev;
309}
310
Mike Lockwood07eb4af2010-07-27 19:05:33 -0400311int usb_device_get_unique_id_from_name(const char* name)
312{
313 int bus = 0, dev = 0;
314 sscanf(name, USB_FS_ID_SCANNER, &bus, &dev);
315 return bus * 1000 + dev;
316}
317
Mike Lockwood7d700f82010-12-29 08:47:29 -0500318char* usb_device_get_name_from_unique_id(int id)
319{
320 int bus = id / 1000;
321 int dev = id % 1000;
322 char* result = (char *)calloc(1, strlen(USB_FS_ID_FORMAT));
323 snprintf(result, strlen(USB_FS_ID_FORMAT) - 1, USB_FS_ID_FORMAT, bus, dev);
324 return result;
325}
326
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400327uint16_t usb_device_get_vendor_id(struct usb_device *device)
328{
329 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
330 return __le16_to_cpu(desc->idVendor);
331}
332
333uint16_t usb_device_get_product_id(struct usb_device *device)
334{
335 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
336 return __le16_to_cpu(desc->idProduct);
337}
338
Mike Lockwood50372072010-12-13 10:15:25 -0800339const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device)
340{
341 return (struct usb_device_descriptor*)device->desc;
342}
343
Mike Lockwood1b7d9912010-07-24 13:57:21 -0400344int usb_device_send_control(struct usb_device *device,
345 int requestType,
346 int request,
347 int value,
348 int index,
349 int length,
350 void* buffer)
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400351{
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400352 struct usbdevfs_ctrltransfer ctrl;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400353
Mike Lockwood1b7d9912010-07-24 13:57:21 -0400354 // this usually requires read/write permission
Mike Lockwoodcd185f22010-12-12 14:17:02 -0800355 if (!usb_device_reopen_writeable(device))
356 return -1;
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400357
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400358 memset(&ctrl, 0, sizeof(ctrl));
Mike Lockwood1b7d9912010-07-24 13:57:21 -0400359 ctrl.bRequestType = requestType;
360 ctrl.bRequest = request;
361 ctrl.wValue = value;
362 ctrl.wIndex = index;
363 ctrl.wLength = length;
364 ctrl.data = buffer;
365 return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
366}
367
368char* usb_device_get_string(struct usb_device *device, int id)
369{
370 char string[256];
371 __u16 buffer[128];
372 __u16 languages[128];
373 int i, result;
374 int languageCount = 0;
375
376 string[0] = 0;
377 memset(languages, 0, sizeof(languages));
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400378
379 // read list of supported languages
Mike Lockwood1b7d9912010-07-24 13:57:21 -0400380 result = usb_device_send_control(device,
381 USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
382 (USB_DT_STRING << 8) | 0, 0, sizeof(languages), languages);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400383 if (result > 0)
384 languageCount = (result - 2) / 2;
385
386 for (i = 1; i <= languageCount; i++) {
387 memset(buffer, 0, sizeof(buffer));
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400388
Mike Lockwood1b7d9912010-07-24 13:57:21 -0400389 result = usb_device_send_control(device,
390 USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
391 (USB_DT_STRING << 8) | id, languages[i], sizeof(buffer), buffer);
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400392 if (result > 0) {
393 int i;
394 // skip first word, and copy the rest to the string, changing shorts to bytes.
395 result /= 2;
396 for (i = 1; i < result; i++)
397 string[i - 1] = buffer[i];
398 string[i - 1] = 0;
399 return strdup(string);
400 }
401 }
402
403 return NULL;
404}
405
406char* usb_device_get_manufacturer_name(struct usb_device *device)
407{
408 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
409
410 if (desc->iManufacturer)
411 return usb_device_get_string(device, desc->iManufacturer);
412 else
413 return NULL;
414}
415
416char* usb_device_get_product_name(struct usb_device *device)
417{
418 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
419
420 if (desc->iProduct)
421 return usb_device_get_string(device, desc->iProduct);
422 else
423 return NULL;
424}
425
426char* usb_device_get_serial(struct usb_device *device)
427{
428 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
429
430 if (desc->iSerialNumber)
431 return usb_device_get_string(device, desc->iSerialNumber);
432 else
433 return NULL;
434}
435
436int usb_device_is_writeable(struct usb_device *device)
437{
438 return device->writeable;
439}
440
441void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)
442{
443 iter->config = device->desc;
444 iter->config_end = device->desc + device->desc_length;
445 iter->curr_desc = device->desc;
446}
447
448struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter)
449{
450 struct usb_descriptor_header* next;
451 if (iter->curr_desc >= iter->config_end)
452 return NULL;
453 next = (struct usb_descriptor_header*)iter->curr_desc;
454 iter->curr_desc += next->bLength;
455 return next;
456}
457
458int usb_device_claim_interface(struct usb_device *device, unsigned int interface)
459{
460 return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface);
461}
462
463int usb_device_release_interface(struct usb_device *device, unsigned int interface)
464{
465 return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
466}
467
468struct usb_endpoint *usb_endpoint_open(struct usb_device *dev,
469 const struct usb_endpoint_descriptor *desc)
470{
471 struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint));
472 memcpy(&ep->desc, desc, sizeof(ep->desc));
473 ep->dev = dev;
474 return ep;
475}
476
477void usb_endpoint_close(struct usb_endpoint *ep)
478{
479 // cancel IO here?
480 free(ep);
481}
482
483int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len)
484{
485 struct usbdevfs_urb *urb = &ep->urb;
486 int res;
487
488 D("usb_endpoint_queue\n");
489 memset(urb, 0, sizeof(*urb));
490 urb->type = USBDEVFS_URB_TYPE_BULK;
491 urb->endpoint = ep->desc.bEndpointAddress;
492 urb->status = -1;
493 urb->buffer = data;
494 urb->buffer_length = len;
495
496 do {
497 res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb);
498 } while((res < 0) && (errno == EINTR));
499
500 return res;
501}
502
503int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num)
504{
505 struct usbdevfs_urb *out = NULL;
506 int res;
507
508 while (1) {
509 res = ioctl(dev->fd, USBDEVFS_REAPURB, &out);
510 D("USBDEVFS_REAPURB returned %d\n", res);
511 if (res < 0) {
512 if(errno == EINTR) {
513 continue;
514 }
515 D("[ reap urb - error ]\n");
516 *out_ep_num = -1;
517 } else {
518 D("[ urb @%p status = %d, actual = %d ]\n",
519 out, out->status, out->actual_length);
520 res = out->actual_length;
521 *out_ep_num = out->endpoint;
522 }
523 break;
524 }
525 return res;
526}
527
528int usb_endpoint_cancel(struct usb_endpoint *ep)
529{
530 return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb);
531}
532
Mike Lockwood5e567cb2010-05-12 08:53:49 -0400533struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep)
534{
535 return ep->dev;
536}
537
Mike Lockwood30ff2c72010-05-09 16:23:47 -0400538int usb_endpoint_number(struct usb_endpoint *ep)
539{
540 return ep->desc.bEndpointAddress;
541}
542
543int usb_endpoint_max_packet(struct usb_endpoint *ep)
544{
545 return __le16_to_cpu(ep->desc.wMaxPacketSize);
546}
547