1 /*
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
17 // #define DEBUG 1
18 #if DEBUG
19
20 #ifdef USE_LIBLOG
21 #define LOG_TAG "usbhost"
22 #include "utils/Log.h"
23 #define D ALOGD
24 #else
25 #define D printf
26 #endif
27
28 #else
29 #define D(...)
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <stddef.h>
37
38 #include <sys/ioctl.h>
39 #include <sys/types.h>
40 #include <sys/time.h>
41 #include <sys/inotify.h>
42 #include <dirent.h>
43 #include <fcntl.h>
44 #include <errno.h>
45 #include <ctype.h>
46 #include <pthread.h>
47
48 #include <linux/usbdevice_fs.h>
49 #include <asm/byteorder.h>
50
51 #include "usbhost/usbhost.h"
52
53 #define DEV_DIR "/dev"
54 #define DEV_BUS_DIR DEV_DIR "/bus"
55 #define USB_FS_DIR DEV_BUS_DIR "/usb"
56 #define USB_FS_ID_SCANNER USB_FS_DIR "/%d/%d"
57 #define USB_FS_ID_FORMAT USB_FS_DIR "/%03d/%03d"
58
59 // Some devices fail to send string descriptors if we attempt reading > 255 bytes
60 #define MAX_STRING_DESCRIPTOR_LENGTH 255
61
62 // From drivers/usb/core/devio.c
63 // I don't know why this isn't in a kernel header
64 #define MAX_USBFS_BUFFER_SIZE 16384
65
66 #define MAX_USBFS_WD_COUNT 10
67
68 struct usb_host_context {
69 int fd;
70 usb_device_added_cb cb_added;
71 usb_device_removed_cb cb_removed;
72 void *data;
73 int wds[MAX_USBFS_WD_COUNT];
74 int wdd;
75 int wddbus;
76 };
77
78 struct usb_device {
79 char dev_name[64];
80 unsigned char desc[4096];
81 int desc_length;
82 int fd;
83 int writeable;
84 };
85
badname(const char * name)86 static inline int badname(const char *name)
87 {
88 while(*name) {
89 if(!isdigit(*name++)) return 1;
90 }
91 return 0;
92 }
93
find_existing_devices_bus(char * busname,usb_device_added_cb added_cb,void * client_data)94 static int find_existing_devices_bus(char *busname,
95 usb_device_added_cb added_cb,
96 void *client_data)
97 {
98 char devname[32];
99 DIR *devdir;
100 struct dirent *de;
101 int done = 0;
102
103 devdir = opendir(busname);
104 if(devdir == 0) return 0;
105
106 while ((de = readdir(devdir)) && !done) {
107 if(badname(de->d_name)) continue;
108
109 snprintf(devname, sizeof(devname), "%s/%s", busname, de->d_name);
110 done = added_cb(devname, client_data);
111 } // end of devdir while
112 closedir(devdir);
113
114 return done;
115 }
116
117 /* returns true if one of the callbacks indicates we are done */
find_existing_devices(usb_device_added_cb added_cb,void * client_data)118 static int find_existing_devices(usb_device_added_cb added_cb,
119 void *client_data)
120 {
121 char busname[32];
122 DIR *busdir;
123 struct dirent *de;
124 int done = 0;
125
126 busdir = opendir(USB_FS_DIR);
127 if(busdir == 0) return 0;
128
129 while ((de = readdir(busdir)) != 0 && !done) {
130 if(badname(de->d_name)) continue;
131
132 snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name);
133 done = find_existing_devices_bus(busname, added_cb,
134 client_data);
135 } //end of busdir while
136 closedir(busdir);
137
138 return done;
139 }
140
watch_existing_subdirs(struct usb_host_context * context,int * wds,int wd_count)141 static void watch_existing_subdirs(struct usb_host_context *context,
142 int *wds, int wd_count)
143 {
144 char path[100];
145 int i, ret;
146
147 wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
148 if (wds[0] < 0)
149 return;
150
151 /* watch existing subdirectories of USB_FS_DIR */
152 for (i = 1; i < wd_count; i++) {
153 snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i);
154 ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);
155 if (ret >= 0)
156 wds[i] = ret;
157 }
158 }
159
usb_host_init()160 struct usb_host_context *usb_host_init()
161 {
162 struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));
163 if (!context) {
164 fprintf(stderr, "out of memory in usb_host_context\n");
165 return NULL;
166 }
167 context->fd = inotify_init();
168 if (context->fd < 0) {
169 fprintf(stderr, "inotify_init failed\n");
170 free(context);
171 return NULL;
172 }
173 return context;
174 }
175
usb_host_cleanup(struct usb_host_context * context)176 void usb_host_cleanup(struct usb_host_context *context)
177 {
178 close(context->fd);
179 free(context);
180 }
181
usb_host_get_fd(struct usb_host_context * context)182 int usb_host_get_fd(struct usb_host_context *context)
183 {
184 return context->fd;
185 } /* usb_host_get_fd() */
186
usb_host_load(struct usb_host_context * context,usb_device_added_cb added_cb,usb_device_removed_cb removed_cb,usb_discovery_done_cb discovery_done_cb,void * client_data)187 int usb_host_load(struct usb_host_context *context,
188 usb_device_added_cb added_cb,
189 usb_device_removed_cb removed_cb,
190 usb_discovery_done_cb discovery_done_cb,
191 void *client_data)
192 {
193 int done = 0;
194 int i;
195
196 context->cb_added = added_cb;
197 context->cb_removed = removed_cb;
198 context->data = client_data;
199
200 D("Created device discovery thread\n");
201
202 /* watch for files added and deleted within USB_FS_DIR */
203 context->wddbus = -1;
204 for (i = 0; i < MAX_USBFS_WD_COUNT; i++)
205 context->wds[i] = -1;
206
207 /* watch the root for new subdirectories */
208 context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);
209 if (context->wdd < 0) {
210 fprintf(stderr, "inotify_add_watch failed\n");
211 if (discovery_done_cb)
212 discovery_done_cb(client_data);
213 return done;
214 }
215
216 watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
217
218 /* check for existing devices first, after we have inotify set up */
219 done = find_existing_devices(added_cb, client_data);
220 if (discovery_done_cb)
221 done |= discovery_done_cb(client_data);
222
223 return done;
224 } /* usb_host_load() */
225
usb_host_read_event(struct usb_host_context * context)226 int usb_host_read_event(struct usb_host_context *context)
227 {
228 struct inotify_event* event;
229 char event_buf[512];
230 char path[100];
231 int i, ret, done = 0;
232 int offset = 0;
233 int wd;
234
235 ret = read(context->fd, event_buf, sizeof(event_buf));
236 if (ret >= (int)sizeof(struct inotify_event)) {
237 while (offset < ret && !done) {
238 event = (struct inotify_event*)&event_buf[offset];
239 done = 0;
240 wd = event->wd;
241 if (wd == context->wdd) {
242 if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
243 context->wddbus = inotify_add_watch(context->fd, DEV_BUS_DIR, IN_CREATE | IN_DELETE);
244 if (context->wddbus < 0) {
245 done = 1;
246 } else {
247 watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
248 done = find_existing_devices(context->cb_added, context->data);
249 }
250 }
251 } else if (wd == context->wddbus) {
252 if ((event->mask & IN_CREATE) && !strcmp(event->name, "usb")) {
253 watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
254 done = find_existing_devices(context->cb_added, context->data);
255 } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "usb")) {
256 for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
257 if (context->wds[i] >= 0) {
258 inotify_rm_watch(context->fd, context->wds[i]);
259 context->wds[i] = -1;
260 }
261 }
262 }
263 } else if (wd == context->wds[0]) {
264 i = atoi(event->name);
265 snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
266 D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
267 "new" : "gone", path, i);
268 if (i > 0 && i < MAX_USBFS_WD_COUNT) {
269 int local_ret = 0;
270 if (event->mask & IN_CREATE) {
271 local_ret = inotify_add_watch(context->fd, path,
272 IN_CREATE | IN_DELETE);
273 if (local_ret >= 0)
274 context->wds[i] = local_ret;
275 done = find_existing_devices_bus(path, context->cb_added,
276 context->data);
277 } else if (event->mask & IN_DELETE) {
278 inotify_rm_watch(context->fd, context->wds[i]);
279 context->wds[i] = -1;
280 }
281 }
282 } else {
283 for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
284 if (wd == context->wds[i]) {
285 snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
286 if (event->mask == IN_CREATE) {
287 D("new device %s\n", path);
288 done = context->cb_added(path, context->data);
289 } else if (event->mask == IN_DELETE) {
290 D("gone device %s\n", path);
291 done = context->cb_removed(path, context->data);
292 }
293 }
294 }
295 }
296
297 offset += sizeof(struct inotify_event) + event->len;
298 }
299 }
300
301 return done;
302 } /* usb_host_read_event() */
303
usb_host_run(struct usb_host_context * context,usb_device_added_cb added_cb,usb_device_removed_cb removed_cb,usb_discovery_done_cb discovery_done_cb,void * client_data)304 void usb_host_run(struct usb_host_context *context,
305 usb_device_added_cb added_cb,
306 usb_device_removed_cb removed_cb,
307 usb_discovery_done_cb discovery_done_cb,
308 void *client_data)
309 {
310 int done;
311
312 done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data);
313
314 while (!done) {
315
316 done = usb_host_read_event(context);
317 }
318 } /* usb_host_run() */
319
usb_device_open(const char * dev_name)320 struct usb_device *usb_device_open(const char *dev_name)
321 {
322 int fd, did_retry = 0, writeable = 1;
323
324 D("usb_device_open %s\n", dev_name);
325
326 retry:
327 fd = open(dev_name, O_RDWR);
328 if (fd < 0) {
329 /* if we fail, see if have read-only access */
330 fd = open(dev_name, O_RDONLY);
331 D("usb_device_open open returned %d errno %d\n", fd, errno);
332 if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) {
333 /* work around race condition between inotify and permissions management */
334 sleep(1);
335 did_retry = 1;
336 goto retry;
337 }
338
339 if (fd < 0)
340 return NULL;
341 writeable = 0;
342 D("[ usb open read-only %s fd = %d]\n", dev_name, fd);
343 }
344
345 struct usb_device* result = usb_device_new(dev_name, fd);
346 if (result)
347 result->writeable = writeable;
348 return result;
349 }
350
usb_device_close(struct usb_device * device)351 void usb_device_close(struct usb_device *device)
352 {
353 close(device->fd);
354 free(device);
355 }
356
usb_device_new(const char * dev_name,int fd)357 struct usb_device *usb_device_new(const char *dev_name, int fd)
358 {
359 struct usb_device *device = calloc(1, sizeof(struct usb_device));
360 int length;
361
362 D("usb_device_new %s fd: %d\n", dev_name, fd);
363
364 if (lseek(fd, 0, SEEK_SET) != 0)
365 goto failed;
366 length = read(fd, device->desc, sizeof(device->desc));
367 D("usb_device_new read returned %d errno %d\n", length, errno);
368 if (length < 0)
369 goto failed;
370
371 strncpy(device->dev_name, dev_name, sizeof(device->dev_name) - 1);
372 device->fd = fd;
373 device->desc_length = length;
374 // assume we are writeable, since usb_device_get_fd will only return writeable fds
375 device->writeable = 1;
376 return device;
377
378 failed:
379 close(fd);
380 free(device);
381 return NULL;
382 }
383
usb_device_reopen_writeable(struct usb_device * device)384 static int usb_device_reopen_writeable(struct usb_device *device)
385 {
386 if (device->writeable)
387 return 1;
388
389 int fd = open(device->dev_name, O_RDWR);
390 if (fd >= 0) {
391 close(device->fd);
392 device->fd = fd;
393 device->writeable = 1;
394 return 1;
395 }
396 D("usb_device_reopen_writeable failed errno %d\n", errno);
397 return 0;
398 }
399
usb_device_get_fd(struct usb_device * device)400 int usb_device_get_fd(struct usb_device *device)
401 {
402 if (!usb_device_reopen_writeable(device))
403 return -1;
404 return device->fd;
405 }
406
usb_device_get_name(struct usb_device * device)407 const char* usb_device_get_name(struct usb_device *device)
408 {
409 return device->dev_name;
410 }
411
usb_device_get_unique_id(struct usb_device * device)412 int usb_device_get_unique_id(struct usb_device *device)
413 {
414 int bus = 0, dev = 0;
415 sscanf(device->dev_name, USB_FS_ID_SCANNER, &bus, &dev);
416 return bus * 1000 + dev;
417 }
418
usb_device_get_unique_id_from_name(const char * name)419 int usb_device_get_unique_id_from_name(const char* name)
420 {
421 int bus = 0, dev = 0;
422 sscanf(name, USB_FS_ID_SCANNER, &bus, &dev);
423 return bus * 1000 + dev;
424 }
425
usb_device_get_name_from_unique_id(int id)426 char* usb_device_get_name_from_unique_id(int id)
427 {
428 int bus = id / 1000;
429 int dev = id % 1000;
430 char* result = (char *)calloc(1, strlen(USB_FS_ID_FORMAT));
431 snprintf(result, strlen(USB_FS_ID_FORMAT) - 1, USB_FS_ID_FORMAT, bus, dev);
432 return result;
433 }
434
usb_device_get_vendor_id(struct usb_device * device)435 uint16_t usb_device_get_vendor_id(struct usb_device *device)
436 {
437 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
438 return __le16_to_cpu(desc->idVendor);
439 }
440
usb_device_get_product_id(struct usb_device * device)441 uint16_t usb_device_get_product_id(struct usb_device *device)
442 {
443 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
444 return __le16_to_cpu(desc->idProduct);
445 }
446
usb_device_get_device_descriptor(struct usb_device * device)447 const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device)
448 {
449 return (struct usb_device_descriptor*)device->desc;
450 }
451
usb_device_get_string(struct usb_device * device,int id)452 char* usb_device_get_string(struct usb_device *device, int id)
453 {
454 char string[256];
455 __u16 buffer[MAX_STRING_DESCRIPTOR_LENGTH / sizeof(__u16)];
456 __u16 languages[MAX_STRING_DESCRIPTOR_LENGTH / sizeof(__u16)];
457 int i, result;
458 int languageCount = 0;
459
460 if (id == 0) return NULL;
461
462 string[0] = 0;
463 memset(languages, 0, sizeof(languages));
464
465 // read list of supported languages
466 result = usb_device_control_transfer(device,
467 USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
468 (USB_DT_STRING << 8) | 0, 0, languages, sizeof(languages), 0);
469 if (result > 0)
470 languageCount = (result - 2) / 2;
471
472 for (i = 1; i <= languageCount; i++) {
473 memset(buffer, 0, sizeof(buffer));
474
475 result = usb_device_control_transfer(device,
476 USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
477 (USB_DT_STRING << 8) | id, languages[i], buffer, sizeof(buffer), 0);
478 if (result > 0) {
479 int i;
480 // skip first word, and copy the rest to the string, changing shorts to bytes.
481 result /= 2;
482 for (i = 1; i < result; i++)
483 string[i - 1] = buffer[i];
484 string[i - 1] = 0;
485 return strdup(string);
486 }
487 }
488
489 return NULL;
490 }
491
usb_device_get_manufacturer_name(struct usb_device * device)492 char* usb_device_get_manufacturer_name(struct usb_device *device)
493 {
494 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
495 return usb_device_get_string(device, desc->iManufacturer);
496 }
497
usb_device_get_product_name(struct usb_device * device)498 char* usb_device_get_product_name(struct usb_device *device)
499 {
500 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
501 return usb_device_get_string(device, desc->iProduct);
502 }
503
usb_device_get_version(struct usb_device * device)504 int usb_device_get_version(struct usb_device *device)
505 {
506 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
507 return desc->bcdUSB;
508 }
509
usb_device_get_serial(struct usb_device * device)510 char* usb_device_get_serial(struct usb_device *device)
511 {
512 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
513 return usb_device_get_string(device, desc->iSerialNumber);
514 }
515
usb_device_is_writeable(struct usb_device * device)516 int usb_device_is_writeable(struct usb_device *device)
517 {
518 return device->writeable;
519 }
520
usb_descriptor_iter_init(struct usb_device * device,struct usb_descriptor_iter * iter)521 void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)
522 {
523 iter->config = device->desc;
524 iter->config_end = device->desc + device->desc_length;
525 iter->curr_desc = device->desc;
526 }
527
usb_descriptor_iter_next(struct usb_descriptor_iter * iter)528 struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter)
529 {
530 struct usb_descriptor_header* next;
531 if (iter->curr_desc >= iter->config_end)
532 return NULL;
533 next = (struct usb_descriptor_header*)iter->curr_desc;
534 iter->curr_desc += next->bLength;
535 return next;
536 }
537
usb_device_claim_interface(struct usb_device * device,unsigned int interface)538 int usb_device_claim_interface(struct usb_device *device, unsigned int interface)
539 {
540 return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface);
541 }
542
usb_device_release_interface(struct usb_device * device,unsigned int interface)543 int usb_device_release_interface(struct usb_device *device, unsigned int interface)
544 {
545 return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
546 }
547
usb_device_connect_kernel_driver(struct usb_device * device,unsigned int interface,int connect)548 int usb_device_connect_kernel_driver(struct usb_device *device,
549 unsigned int interface, int connect)
550 {
551 struct usbdevfs_ioctl ctl;
552
553 ctl.ifno = interface;
554 ctl.ioctl_code = (connect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT);
555 ctl.data = NULL;
556 return ioctl(device->fd, USBDEVFS_IOCTL, &ctl);
557 }
558
usb_device_set_configuration(struct usb_device * device,int configuration)559 int usb_device_set_configuration(struct usb_device *device, int configuration)
560 {
561 return ioctl(device->fd, USBDEVFS_SETCONFIGURATION, &configuration);
562 }
563
usb_device_set_interface(struct usb_device * device,unsigned int interface,unsigned int alt_setting)564 int usb_device_set_interface(struct usb_device *device, unsigned int interface,
565 unsigned int alt_setting)
566 {
567 struct usbdevfs_setinterface ctl;
568
569 ctl.interface = interface;
570 ctl.altsetting = alt_setting;
571 return ioctl(device->fd, USBDEVFS_SETINTERFACE, &ctl);
572 }
573
usb_device_control_transfer(struct usb_device * device,int requestType,int request,int value,int index,void * buffer,int length,unsigned int timeout)574 int usb_device_control_transfer(struct usb_device *device,
575 int requestType,
576 int request,
577 int value,
578 int index,
579 void* buffer,
580 int length,
581 unsigned int timeout)
582 {
583 struct usbdevfs_ctrltransfer ctrl;
584
585 // this usually requires read/write permission
586 if (!usb_device_reopen_writeable(device))
587 return -1;
588
589 memset(&ctrl, 0, sizeof(ctrl));
590 ctrl.bRequestType = requestType;
591 ctrl.bRequest = request;
592 ctrl.wValue = value;
593 ctrl.wIndex = index;
594 ctrl.wLength = length;
595 ctrl.data = buffer;
596 ctrl.timeout = timeout;
597 return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
598 }
599
usb_device_bulk_transfer(struct usb_device * device,int endpoint,void * buffer,int length,unsigned int timeout)600 int usb_device_bulk_transfer(struct usb_device *device,
601 int endpoint,
602 void* buffer,
603 int length,
604 unsigned int timeout)
605 {
606 struct usbdevfs_bulktransfer ctrl;
607
608 // need to limit request size to avoid EINVAL
609 if (length > MAX_USBFS_BUFFER_SIZE)
610 length = MAX_USBFS_BUFFER_SIZE;
611
612 memset(&ctrl, 0, sizeof(ctrl));
613 ctrl.ep = endpoint;
614 ctrl.len = length;
615 ctrl.data = buffer;
616 ctrl.timeout = timeout;
617 return ioctl(device->fd, USBDEVFS_BULK, &ctrl);
618 }
619
usb_device_reset(struct usb_device * device)620 int usb_device_reset(struct usb_device *device)
621 {
622 return ioctl(device->fd, USBDEVFS_RESET);
623 }
624
usb_request_new(struct usb_device * dev,const struct usb_endpoint_descriptor * ep_desc)625 struct usb_request *usb_request_new(struct usb_device *dev,
626 const struct usb_endpoint_descriptor *ep_desc)
627 {
628 struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
629 if (!urb)
630 return NULL;
631
632 if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
633 urb->type = USBDEVFS_URB_TYPE_BULK;
634 else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
635 urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
636 else {
637 D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
638 free(urb);
639 return NULL;
640 }
641 urb->endpoint = ep_desc->bEndpointAddress;
642
643 struct usb_request *req = calloc(1, sizeof(struct usb_request));
644 if (!req) {
645 free(urb);
646 return NULL;
647 }
648
649 req->dev = dev;
650 req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize);
651 req->private_data = urb;
652 req->endpoint = urb->endpoint;
653 urb->usercontext = req;
654
655 return req;
656 }
657
usb_request_free(struct usb_request * req)658 void usb_request_free(struct usb_request *req)
659 {
660 free(req->private_data);
661 free(req);
662 }
663
usb_request_queue(struct usb_request * req)664 int usb_request_queue(struct usb_request *req)
665 {
666 struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data;
667 int res;
668
669 urb->status = -1;
670 urb->buffer = req->buffer;
671 // need to limit request size to avoid EINVAL
672 if (req->buffer_length > MAX_USBFS_BUFFER_SIZE)
673 urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
674 else
675 urb->buffer_length = req->buffer_length;
676
677 do {
678 res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
679 } while((res < 0) && (errno == EINTR));
680
681 return res;
682 }
683
usb_request_wait(struct usb_device * dev)684 struct usb_request *usb_request_wait(struct usb_device *dev)
685 {
686 struct usbdevfs_urb *urb = NULL;
687 struct usb_request *req = NULL;
688
689 while (1) {
690 int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb);
691 D("USBDEVFS_REAPURB returned %d\n", res);
692 if (res < 0) {
693 if(errno == EINTR) {
694 continue;
695 }
696 D("[ reap urb - error ]\n");
697 return NULL;
698 } else {
699 D("[ urb @%p status = %d, actual = %d ]\n",
700 urb, urb->status, urb->actual_length);
701 req = (struct usb_request*)urb->usercontext;
702 req->actual_length = urb->actual_length;
703 }
704 break;
705 }
706 return req;
707 }
708
usb_request_cancel(struct usb_request * req)709 int usb_request_cancel(struct usb_request *req)
710 {
711 struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data);
712 return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, urb);
713 }
714
715