2 * I/O functions for libusb
3 * Copyright (C) 2007 Daniel Drake <dsd@gentoo.org>
4 * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/select.h>
33 /* signalfd() support is present in glibc-2.7 onwards, but glibc-2.7 contains
34 * a bug where the header is neither installed or compilable. This will be
35 * fixed for glibc-2.8. */
36 #if __GLIBC_PREREQ(2, 8)
37 #include <sys/signalfd.h>
47 /* this is a list of in-flight rb_handles, sorted by timeout expiration.
48 * URBs to timeout the soonest are placed at the beginning of the list, URBs
49 * that will time out later are placed after, and urbs with infinite timeout
50 * are always placed at the very end. */
51 static struct list_head flying_urbs;
53 static int setup_signalfd(int _signum)
58 usbi_dbg("signal %d", _signum);
61 sigaddset(&sigset, _signum);
62 sigfd = signalfd(-1, &sigset, 0);
64 usbi_err("signalfd failed, code=%d errno=%d", sigfd, errno);
67 usbi_dbg("got signalfd %d", sigfd);
71 sigaddset(&sigset, _signum);
72 return sigprocmask(SIG_BLOCK, &sigset, NULL);
75 int usbi_io_init(int _signum)
77 list_init(&flying_urbs);
78 return setup_signalfd(signum);
81 void usbi_io_exit(void)
86 static int calculate_timeout(struct libusb_urb_handle *urbh,
90 struct timespec current_time;
91 struct sigevent sigevt = {
92 .sigev_notify = SIGEV_SIGNAL,
93 .sigev_signo = signum,
95 struct itimerspec itspec;
96 struct timespec *it_value = &itspec.it_value;
101 r = clock_gettime(CLOCK_MONOTONIC, ¤t_time);
103 usbi_err("failed to read monotonic clock, errno=%d", errno);
107 r = timer_create(CLOCK_MONOTONIC, &sigevt, &urbh->timer);
109 usbi_err("failed to create monotonic timer");
113 memset(&itspec, 0, sizeof(itspec));
114 it_value->tv_sec = current_time.tv_sec + (timeout / 1000);
115 it_value->tv_nsec = current_time.tv_nsec +
116 ((timeout % 1000) * 1000000);
118 if (it_value->tv_nsec > 1000000000) {
119 it_value->tv_nsec -= 1000000000;
123 r = timer_settime(&urbh->timer, TIMER_ABSTIME, &itspec, NULL);
125 usbi_err("failed to arm monotonic timer");
129 urbh->timeout = itspec.it_value;
134 static void add_to_flying_list(struct libusb_urb_handle *urbh)
136 struct libusb_urb_handle *cur;
137 struct timespec *timeout = &urbh->timeout;
139 /* if we have no other flying urbs, start the list with this one */
140 if (list_empty(&flying_urbs)) {
141 list_add(&urbh->list, &flying_urbs);
145 /* if we have infinite timeout, append to end of list */
146 if (!TIMESPEC_IS_SET(timeout)) {
147 list_add_tail(&urbh->list, &flying_urbs);
151 /* otherwise, find appropriate place in list */
152 list_for_each_entry(cur, &flying_urbs, list) {
153 /* find first timeout that occurs after the urbh in question */
154 struct timespec *cur_ts = &cur->timeout;
156 if (!TIMESPEC_IS_SET(cur_ts) || (cur_ts->tv_sec > timeout->tv_sec) ||
157 (cur_ts->tv_sec == timeout->tv_sec &&
158 cur_ts->tv_nsec > timeout->tv_nsec)) {
159 list_add_tail(&urbh->list, &cur->list);
164 /* otherwise we need to be inserted at the end */
165 list_add_tail(&urbh->list, &flying_urbs);
168 static int submit_urb(struct libusb_dev_handle *devh,
169 struct libusb_urb_handle *urbh)
172 struct usb_urb *urb = &urbh->urb;
173 int to_be_transferred = urbh->transfer_len - urbh->transferred;
175 urb->type = urbh->urb_type;
176 urb->endpoint = urbh->endpoint;
177 urb->buffer = urbh->buffer + urbh->transferred;
178 urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
180 /* FIXME: for requests that we have to split into multiple URBs, we should
181 * submit all the URBs instantly: submit, submit, submit, reap, reap, reap
182 * rather than: submit, reap, submit, reap, submit, reap
183 * this will improve performance and fix bugs concerning behaviour when
184 * the user submits two similar multiple-urb requests */
185 usbi_dbg("transferring %d from %d bytes", urb->buffer_length,
188 r = ioctl(devh->fd, IOCTL_USB_SUBMITURB, &urbh->urb);
190 usbi_err("submiturb failed error %d errno=%d", r, errno);
194 add_to_flying_list(urbh);
198 API_EXPORTED struct libusb_urb_handle *libusb_async_control_transfer(
199 struct libusb_dev_handle *devh, struct libusb_control_transfer *transfer,
200 libusb_ctrl_cb_fn callback, void *user_data, unsigned int timeout)
202 struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
203 struct libusb_ctrl_setup *setup;
204 unsigned char *urbdata;
205 int urbdata_length = sizeof(struct libusb_ctrl_setup) + transfer->length;
210 memset(urbh, 0, sizeof(*urbh));
212 urbh->callback = callback;
213 urbh->user_data = user_data;
214 r = calculate_timeout(urbh, timeout);
220 urbdata = malloc(urbdata_length);
226 usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
227 transfer->requesttype, transfer->request, transfer->value,
228 transfer->index, transfer->length);
230 setup = (struct libusb_ctrl_setup *) urbdata;
231 setup->bRequestType = transfer->requesttype;
232 setup->bRequest = transfer->request;
233 setup->wValue = cpu_to_le16(transfer->value);
234 setup->wIndex = cpu_to_le16(transfer->index);
235 setup->wLength = cpu_to_le16(transfer->length);
237 if ((transfer->requesttype & 0x80) == LIBUSB_ENDPOINT_OUT)
238 memcpy(urbdata + sizeof(struct libusb_ctrl_setup), transfer->data,
241 urbh->urb_type = USB_URB_TYPE_CONTROL;
242 urbh->buffer = urbdata;
243 urbh->transfer_len = urbdata_length;
245 r = submit_urb(devh, urbh);
255 static struct libusb_urb_handle *submit_bulk_transfer(
256 struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
257 libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout,
258 unsigned char urbtype)
260 struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
263 usbi_dbg("length %d timeout %d", transfer->length, timeout);
267 memset(urbh, 0, sizeof(*urbh));
268 r = calculate_timeout(urbh, timeout);
274 urbh->callback = callback;
275 urbh->user_data = user_data;
276 urbh->flags |= LIBUSB_URBH_DATA_BELONGS_TO_USER;
277 urbh->endpoint = transfer->endpoint;
278 urbh->urb_type = urbtype;
279 urbh->buffer = transfer->data;
280 urbh->transfer_len = transfer->length;
282 r = submit_urb(devh, urbh);
291 API_EXPORTED struct libusb_urb_handle *libusb_async_bulk_transfer(
292 struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
293 libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
295 return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
299 API_EXPORTED struct libusb_urb_handle *libusb_async_interrupt_transfer(
300 struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
301 libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
303 return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
304 USB_URB_TYPE_INTERRUPT);
307 API_EXPORTED int libusb_urb_handle_cancel(struct libusb_dev_handle *devh,
308 struct libusb_urb_handle *urbh)
312 r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
314 usbi_err("cancel urb failed error %d", r);
318 API_EXPORTED int libusb_urb_handle_cancel_sync(struct libusb_dev_handle *devh,
319 struct libusb_urb_handle *urbh)
323 r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
325 usbi_err("cancel urb failed error %d", r);
329 urbh->flags |= LIBUSB_URBH_SYNC_CANCELLED;
330 while (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
339 int handle_transfer_completion(struct libusb_dev_handle *devh,
340 struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status)
342 struct usb_urb *urb = &urbh->urb;
344 if (TIMESPEC_IS_SET(&urbh->timeout))
345 timer_delete(urbh->timer);
347 if (status == FP_URB_SILENT_COMPLETION)
350 if (urb->type == USB_URB_TYPE_CONTROL) {
351 libusb_ctrl_cb_fn callback = urbh->callback;
353 callback(devh, urbh, status, urb->buffer,
354 urb->buffer + sizeof(struct libusb_ctrl_setup), urbh->transferred,
356 } else if (urb->type == USB_URB_TYPE_BULK ||
357 urb->type == USB_URB_TYPE_INTERRUPT) {
358 libusb_bulk_cb_fn callback = urbh->callback;
360 callback(devh, urbh, status, urbh->endpoint, urbh->transfer_len,
361 urbh->buffer, urbh->transferred, urbh->user_data);
366 static int handle_transfer_cancellation(struct libusb_dev_handle *devh,
367 struct libusb_urb_handle *urbh)
369 /* if the URB is being cancelled synchronously, raise cancellation
370 * completion event by unsetting flag, and ensure that user callback does
373 if (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
374 urbh->flags &= ~LIBUSB_URBH_SYNC_CANCELLED;
375 usbi_dbg("detected sync. cancel");
376 return handle_transfer_completion(devh, urbh, FP_URB_SILENT_COMPLETION);
379 /* if the URB was cancelled due to timeout, report timeout to the user */
380 if (urbh->flags & LIBUSB_URBH_TIMED_OUT) {
381 usbi_dbg("detected timeout cancellation");
382 return handle_transfer_completion(devh, urbh, FP_URB_TIMEOUT);
385 /* otherwise its a normal async cancel */
386 return handle_transfer_completion(devh, urbh, FP_URB_CANCELLED);
389 static int reap_for_devh(struct libusb_dev_handle *devh)
393 struct libusb_urb_handle *urbh;
396 r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
397 if (r == -1 && errno == EAGAIN)
400 usbi_err("reap failed error %d errno=%d", r, errno);
404 urbh = container_of(urb, struct libusb_urb_handle, urb);
406 usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
408 list_del(&urbh->list);
410 if (urb->status == -2)
411 return handle_transfer_cancellation(devh, urbh);
412 /* FIXME: research what other status codes may exist */
413 if (urb->status != 0)
414 usbi_warn("unrecognised urb status %d", urb->status);
416 /* determine how much data was asked for */
417 trf_requested = MIN(urbh->transfer_len - urbh->transferred,
418 MAX_URB_BUFFER_LENGTH);
420 urbh->transferred += urb->actual_length;
422 /* if we were provided less data than requested, then our transfer is
424 if (urb->actual_length < trf_requested) {
425 usbi_dbg("less data than requested (%d/%d) --> all done",
426 urb->actual_length, trf_requested);
427 return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
430 /* if we've transferred all data, we're done */
431 if (urbh->transferred == urbh->transfer_len) {
432 usbi_dbg("transfer complete --> all done");
433 return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
436 /* otherwise, we have more data to transfer */
437 usbi_dbg("more data to transfer...");
438 memset(urb, 0, sizeof(*urb));
439 return submit_urb(devh, urbh);
442 static void handle_timeout(struct libusb_urb_handle *urbh)
444 /* handling timeouts is tricky, as we may race with the kernel: we may
445 * detect a timeout racing with the condition that the urb has actually
446 * completed. we asynchronously cancel the URB and report timeout
447 * to the user when the URB cancellation completes (or not at all if the
448 * URB actually gets delivered as per this race) */
452 urbh->flags |= LIBUSB_URBH_TIMED_OUT;
453 r = libusb_urb_handle_cancel(urbh->devh, urbh);
455 usbi_warn("async cancel failed %d errno=%d", r, errno);
458 static int handle_timeouts(void)
460 struct timespec systime;
461 struct libusb_urb_handle *urbh;
464 if (list_empty(&flying_urbs))
467 /* get current time */
468 r = clock_gettime(CLOCK_MONOTONIC, &systime);
472 /* iterate through flying urbs list, finding all urbs that have expired
474 list_for_each_entry(urbh, &flying_urbs, list) {
475 struct timespec *cur_ts = &urbh->timeout;
477 /* if we've reached urbs of infinite timeout, we're all done */
478 if (!TIMESPEC_IS_SET(cur_ts))
481 /* if urb has non-expired timeout, nothing more to do */
482 if ((cur_ts->tv_sec > systime.tv_sec) ||
483 (cur_ts->tv_sec == systime.tv_sec &&
484 cur_ts->tv_nsec > systime.tv_nsec))
487 /* otherwise, we've got an expired timeout to handle */
488 handle_timeout(urbh);
494 static int flush_sigfd(void)
497 struct signalfd_siginfo siginfo;
498 r = read(sigfd, &siginfo, sizeof(siginfo));
500 usbi_err("sigfd read failed %d %d", r, errno);
503 if ((unsigned int) r < sizeof(siginfo)) {
504 usbi_err("sigfd short read (%d/%d)", r, sizeof(siginfo));
510 static int poll_io(struct timeval *tv)
512 struct libusb_dev_handle *devh;
519 FD_SET(sigfd, &readfds);
522 list_for_each_entry(devh, &open_devs, list) {
524 FD_SET(fd, &writefds);
529 r = select(maxfd + 1, &readfds, &writefds, NULL, tv);
530 if (r == 0 || (r == -1 && errno == EINTR)) {
533 usbi_err("select failed %d err=%d\n", r, errno);
537 if (FD_ISSET(sigfd, &readfds))
540 list_for_each_entry(devh, &open_devs, list) {
541 if (!FD_ISSET(devh->fd, &writefds))
543 r = reap_for_devh(devh);
544 if (r == -1 && errno == EAGAIN)
550 /* FIXME check return value? */
555 API_EXPORTED int libusb_poll_timeout(struct timeval *tv)
560 API_EXPORTED int libusb_poll(void)
568 struct sync_ctrl_handle {
569 enum libusb_urb_cb_status status;
574 static void ctrl_transfer_cb(struct libusb_dev_handle *devh,
575 struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
576 struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
579 struct sync_ctrl_handle *ctrlh = (struct sync_ctrl_handle *) user_data;
580 usbi_dbg("actual_length=%d", actual_length);
582 if (status == FP_URB_COMPLETED) {
583 /* copy results into user-defined buffer */
584 if (setup->bRequestType & LIBUSB_ENDPOINT_IN)
585 memcpy(ctrlh->data, data, actual_length);
588 ctrlh->status = status;
589 ctrlh->actual_length = actual_length;
590 /* caller frees urbh */
593 API_EXPORTED int libusb_control_transfer(struct libusb_dev_handle *devh,
594 struct libusb_control_transfer *transfer, unsigned int timeout)
596 struct libusb_urb_handle *urbh;
597 struct sync_ctrl_handle ctrlh;
599 memset(&ctrlh, 0, sizeof(ctrlh));
600 ctrlh.data = transfer->data;
602 urbh = libusb_async_control_transfer(devh, transfer, ctrl_transfer_cb,
607 while (!ctrlh.status) {
608 int r = libusb_poll();
610 libusb_urb_handle_cancel_sync(devh, urbh);
611 libusb_urb_handle_free(urbh);
616 libusb_urb_handle_free(urbh);
617 switch (ctrlh.status) {
618 case FP_URB_COMPLETED:
619 return ctrlh.actual_length;
623 usbi_warn("unrecognised status code %d", ctrlh.status);
628 struct sync_bulk_handle {
629 enum libusb_urb_cb_status status;
633 static void bulk_transfer_cb(struct libusb_dev_handle *devh,
634 struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
635 unsigned char endpoint, int rqlength, unsigned char *data,
636 int actual_length, void *user_data)
638 struct sync_bulk_handle *bulkh = (struct sync_bulk_handle *) user_data;
640 bulkh->status = status;
641 bulkh->actual_length = actual_length;
642 /* caller frees urbh */
645 static int do_sync_bulk_transfer(struct libusb_dev_handle *devh,
646 struct libusb_bulk_transfer *transfer, int *transferred,
647 unsigned int timeout, unsigned char urbtype)
649 struct libusb_urb_handle *urbh;
650 struct sync_bulk_handle bulkh;
652 memset(&bulkh, 0, sizeof(bulkh));
654 urbh = submit_bulk_transfer(devh, transfer, bulk_transfer_cb, &bulkh,
659 while (!bulkh.status) {
660 int r = libusb_poll();
662 libusb_urb_handle_cancel_sync(devh, urbh);
663 libusb_urb_handle_free(urbh);
668 *transferred = bulkh.actual_length;
669 libusb_urb_handle_free(urbh);
671 switch (bulkh.status) {
672 case FP_URB_COMPLETED:
677 usbi_warn("unrecognised status code %d", bulkh.status);
682 API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *devh,
683 struct libusb_bulk_transfer *transfer, int *transferred,
684 unsigned int timeout)
686 return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
687 USB_URB_TYPE_INTERRUPT);
690 API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *devh,
691 struct libusb_bulk_transfer *transfer, int *transferred,
692 unsigned int timeout)
694 return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
698 API_EXPORTED void libusb_urb_handle_free(struct libusb_urb_handle *urbh)
703 if (!(urbh->flags & LIBUSB_URBH_DATA_BELONGS_TO_USER))
704 free(urbh->urb.buffer);
708 int usbi_get_signalfd(void)