2 * I/O functions for libusb
3 * Copyright (C) 2007-2008 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
27 #include <sys/select.h>
34 #define TRANSFER_TO_PRIV(trf) (container_of((trf), struct usbi_transfer, pub))
36 /* this is a list of in-flight rb_handles, sorted by timeout expiration.
37 * URBs to timeout the soonest are placed at the beginning of the list, URBs
38 * that will time out later are placed after, and urbs with infinite timeout
39 * are always placed at the very end. */
40 static struct list_head flying_transfers;
42 /* user callbacks for pollfd changes */
43 static libusb_pollfd_added_cb fd_added_cb = NULL;
44 static libusb_pollfd_removed_cb fd_removed_cb = NULL;
48 list_init(&flying_transfers);
53 static int calculate_timeout(struct usbi_transfer *transfer)
56 struct timespec current_time;
57 unsigned int timeout = transfer->pub.timeout;
62 r = clock_gettime(CLOCK_MONOTONIC, ¤t_time);
64 usbi_err("failed to read monotonic clock, errno=%d", errno);
68 current_time.tv_sec += timeout / 1000;
69 current_time.tv_nsec += (timeout % 1000) * 1000000;
71 if (current_time.tv_nsec > 1000000000) {
72 current_time.tv_nsec -= 1000000000;
73 current_time.tv_sec++;
76 TIMESPEC_TO_TIMEVAL(&transfer->timeout, ¤t_time);
80 static void add_to_flying_list(struct usbi_transfer *transfer)
82 struct usbi_transfer *cur;
83 struct timeval *timeout = &transfer->timeout;
85 /* if we have no other flying transfers, start the list with this one */
86 if (list_empty(&flying_transfers)) {
87 list_add(&transfer->list, &flying_transfers);
91 /* if we have infinite timeout, append to end of list */
92 if (!timerisset(timeout)) {
93 list_add_tail(&transfer->list, &flying_transfers);
97 /* otherwise, find appropriate place in list */
98 list_for_each_entry(cur, &flying_transfers, list) {
99 /* find first timeout that occurs after the transfer in question */
100 struct timeval *cur_tv = &cur->timeout;
102 if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
103 (cur_tv->tv_sec == timeout->tv_sec &&
104 cur_tv->tv_usec > timeout->tv_usec)) {
105 list_add_tail(&transfer->list, &cur->list);
110 /* otherwise we need to be inserted at the end */
111 list_add_tail(&transfer->list, &flying_transfers);
114 static int submit_transfer(struct usbi_transfer *itransfer)
117 struct usb_urb *urb = &itransfer->urb;
118 struct libusb_transfer *transfer = &itransfer->pub;
119 int to_be_transferred = transfer->length - itransfer->transferred;
121 switch (transfer->endpoint_type) {
122 case LIBUSB_ENDPOINT_TYPE_CONTROL:
123 urb->type = USB_URB_TYPE_CONTROL;
125 case LIBUSB_ENDPOINT_TYPE_BULK:
126 urb->type = USB_URB_TYPE_BULK;
128 case LIBUSB_ENDPOINT_TYPE_INTERRUPT:
129 urb->type = USB_URB_TYPE_INTERRUPT;
132 usbi_err("unknown endpoint type %d", transfer->endpoint_type);
136 urb->endpoint = transfer->endpoint;
137 urb->buffer = transfer->buffer + itransfer->transferred;
138 urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
140 /* FIXME: for requests that we have to split into multiple URBs, we should
141 * submit all the URBs instantly: submit, submit, submit, reap, reap, reap
142 * rather than: submit, reap, submit, reap, submit, reap
143 * this will improve performance and fix bugs concerning behaviour when
144 * the user submits two similar multiple-urb requests */
145 usbi_dbg("transferring %d from %d bytes", urb->buffer_length,
148 r = ioctl(transfer->dev_handle->fd, IOCTL_USB_SUBMITURB, urb);
150 usbi_err("submiturb failed error %d errno=%d", r, errno);
154 add_to_flying_list(itransfer);
158 API_EXPORTED size_t libusb_get_transfer_alloc_size(void)
160 return sizeof(struct usbi_transfer);
163 void __init_transfer(struct usbi_transfer *transfer)
165 memset(transfer, 0, sizeof(*transfer));
168 API_EXPORTED void libusb_init_transfer(struct libusb_transfer *transfer)
170 __init_transfer(TRANSFER_TO_PRIV(transfer));
173 API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(void)
175 struct usbi_transfer *transfer = malloc(sizeof(*transfer));
179 __init_transfer(transfer);
180 return &transfer->pub;
183 API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer)
185 struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
188 itransfer->transferred = 0;
189 r = calculate_timeout(itransfer);
193 if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL) {
194 struct libusb_control_setup *setup =
195 (struct libusb_control_setup *) transfer->buffer;
197 usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
198 setup->bRequestType, setup->bRequest, setup->wValue, setup->wIndex,
201 setup->wValue = cpu_to_le16(setup->wValue);
202 setup->wIndex = cpu_to_le16(setup->wIndex);
203 setup->wLength = cpu_to_le16(setup->wLength);
206 return submit_transfer(itransfer);
209 API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer)
211 struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
215 r = ioctl(transfer->dev_handle->fd, IOCTL_USB_DISCARDURB, &itransfer->urb);
217 usbi_err("cancel transfer failed error %d", r);
221 API_EXPORTED int libusb_cancel_transfer_sync(struct libusb_transfer *transfer)
223 struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
227 r = ioctl(transfer->dev_handle->fd, IOCTL_USB_DISCARDURB, &itransfer->urb);
229 usbi_err("cancel transfer failed error %d", r);
233 itransfer->flags |= USBI_TRANSFER_SYNC_CANCELLED;
234 while (itransfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
243 static void handle_transfer_completion(struct usbi_transfer *itransfer,
244 enum libusb_transfer_status status)
246 struct libusb_transfer *transfer = &itransfer->pub;
248 if (status == LIBUSB_TRANSFER_SILENT_COMPLETION)
251 if (status == LIBUSB_TRANSFER_COMPLETED
252 && transfer->flags & LIBUSB_TRANSFER_SHORT_NOT_OK) {
253 int rqlen = transfer->length;
254 if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL)
255 rqlen -= LIBUSB_CONTROL_SETUP_SIZE;
256 if (rqlen != itransfer->transferred) {
257 usbi_dbg("interpreting short transfer as error");
258 status = LIBUSB_TRANSFER_ERROR;
262 transfer->status = status;
263 transfer->actual_length = itransfer->transferred;
264 if (transfer->callback)
265 transfer->callback(transfer);
266 if (transfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
267 libusb_free_transfer(transfer);
270 static void handle_transfer_cancellation(struct usbi_transfer *transfer)
272 /* if the URB is being cancelled synchronously, raise cancellation
273 * completion event by unsetting flag, and ensure that user callback does
276 if (transfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
277 transfer->flags &= ~USBI_TRANSFER_SYNC_CANCELLED;
278 usbi_dbg("detected sync. cancel");
279 handle_transfer_completion(transfer, LIBUSB_TRANSFER_SILENT_COMPLETION);
283 /* if the URB was cancelled due to timeout, report timeout to the user */
284 if (transfer->flags & USBI_TRANSFER_TIMED_OUT) {
285 usbi_dbg("detected timeout cancellation");
286 handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT);
290 /* otherwise its a normal async cancel */
291 handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED);
294 static int reap_for_devh(struct libusb_device_handle *devh)
298 struct usbi_transfer *itransfer;
299 struct libusb_transfer *transfer;
303 r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
304 if (r == -1 && errno == EAGAIN)
307 usbi_err("reap failed error %d errno=%d", r, errno);
311 itransfer = container_of(urb, struct usbi_transfer, urb);
312 transfer = &itransfer->pub;
314 usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
316 list_del(&itransfer->list);
318 if (urb->status == -2) {
319 handle_transfer_cancellation(itransfer);
323 /* FIXME: research what other status codes may exist */
324 if (urb->status != 0)
325 usbi_warn("unrecognised urb status %d", urb->status);
327 /* determine how much data was asked for */
328 length = transfer->length;
329 if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL)
330 length -= LIBUSB_CONTROL_SETUP_SIZE;
331 trf_requested = MIN(length - itransfer->transferred,
332 MAX_URB_BUFFER_LENGTH);
334 itransfer->transferred += urb->actual_length;
336 /* if we were provided less data than requested, then our transfer is
338 if (urb->actual_length < trf_requested) {
339 usbi_dbg("less data than requested (%d/%d) --> all done",
340 urb->actual_length, trf_requested);
341 handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
345 /* if we've transferred all data, we're done */
346 if (itransfer->transferred == length) {
347 usbi_dbg("transfer complete --> all done");
348 handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
352 /* otherwise, we have more data to transfer */
353 usbi_dbg("more data to transfer...");
354 memset(urb, 0, sizeof(*urb));
355 return submit_transfer(itransfer);
358 static void handle_timeout(struct usbi_transfer *itransfer)
360 /* handling timeouts is tricky, as we may race with the kernel: we may
361 * detect a timeout racing with the condition that the urb has actually
362 * completed. we asynchronously cancel the URB and report timeout
363 * to the user when the URB cancellation completes (or not at all if the
364 * URB actually gets delivered as per this race) */
365 struct libusb_transfer *transfer = &itransfer->pub;
368 itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
369 r = libusb_cancel_transfer(transfer);
371 usbi_warn("async cancel failed %d errno=%d", r, errno);
374 static int handle_timeouts(void)
376 struct timespec systime_ts;
377 struct timeval systime;
378 struct usbi_transfer *transfer;
381 if (list_empty(&flying_transfers))
384 /* get current time */
385 r = clock_gettime(CLOCK_MONOTONIC, &systime_ts);
389 TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
391 /* iterate through flying transfers list, finding all transfers that
392 * have expired timeouts */
393 list_for_each_entry(transfer, &flying_transfers, list) {
394 struct timeval *cur_tv = &transfer->timeout;
396 /* if we've reached transfers of infinite timeout, we're all done */
397 if (!timerisset(cur_tv))
400 /* ignore timeouts we've already handled */
401 if (transfer->flags & USBI_TRANSFER_TIMED_OUT)
404 /* if transfer has non-expired timeout, nothing more to do */
405 if ((cur_tv->tv_sec > systime.tv_sec) ||
406 (cur_tv->tv_sec == systime.tv_sec &&
407 cur_tv->tv_usec > systime.tv_usec))
410 /* otherwise, we've got an expired timeout to handle */
411 handle_timeout(transfer);
417 static int poll_io(struct timeval *tv)
419 struct libusb_device_handle *devh;
423 struct timeval select_timeout;
424 struct timeval timeout;
426 r = libusb_get_next_timeout(&timeout);
428 /* timeout already expired? */
429 if (!timerisset(&timeout))
430 return handle_timeouts();
432 /* choose the smallest of next URB timeout or user specified timeout */
433 if (timercmp(&timeout, tv, <))
434 select_timeout = timeout;
436 select_timeout = *tv;
438 select_timeout = *tv;
442 list_for_each_entry(devh, &open_devs, list) {
444 FD_SET(fd, &writefds);
449 usbi_dbg("select() with timeout in %d.%06ds", select_timeout.tv_sec,
450 select_timeout.tv_usec);
451 r = select(maxfd + 1, NULL, &writefds, NULL, &select_timeout);
452 usbi_dbg("select() returned %d with %d.%06ds remaining", r, select_timeout.tv_sec,
453 select_timeout.tv_usec);
455 *tv = select_timeout;
456 return handle_timeouts();
457 } else if (r == -1 && errno == EINTR) {
460 usbi_err("select failed %d err=%d\n", r, errno);
464 list_for_each_entry(devh, &open_devs, list) {
465 if (!FD_ISSET(devh->fd, &writefds))
467 r = reap_for_devh(devh);
468 if (r == -1 && errno == EAGAIN)
474 /* FIXME check return value? */
475 return handle_timeouts();
478 API_EXPORTED int libusb_poll_timeout(struct timeval *tv)
483 API_EXPORTED int libusb_poll(void)
491 API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
493 struct usbi_transfer *transfer;
494 struct timespec cur_ts;
495 struct timeval cur_tv;
496 struct timeval *next_timeout;
500 if (list_empty(&flying_transfers)) {
501 usbi_dbg("no URBs, no timeout!");
505 /* find next transfer which hasn't already been processed as timed out */
506 list_for_each_entry(transfer, &flying_transfers, list) {
507 if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
514 usbi_dbg("all URBs have already been processed for timeouts");
518 next_timeout = &transfer->timeout;
520 /* no timeout for next transfer */
521 if (!timerisset(next_timeout)) {
522 usbi_dbg("no URBs with timeouts, no timeout!");
526 r = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
528 usbi_err("failed to read monotonic clock, errno=%d", errno);
531 TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
533 if (timercmp(&cur_tv, next_timeout, >=)) {
534 usbi_dbg("first timeout already expired");
537 timersub(next_timeout, &cur_tv, tv);
538 usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
544 API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer)
546 struct usbi_transfer *itransfer;
550 if (transfer->flags & LIBUSB_TRANSFER_FREE_BUFFER)
551 free(transfer->buffer);
553 itransfer = TRANSFER_TO_PRIV(transfer);
557 API_EXPORTED void libusb_set_pollfd_notifiers(libusb_pollfd_added_cb added_cb,
558 libusb_pollfd_removed_cb removed_cb)
560 fd_added_cb = added_cb;
561 fd_removed_cb = removed_cb;
564 void usbi_add_pollfd(int fd, short events)
566 usbi_dbg("add fd %d events %d", fd, events);
568 fd_added_cb(fd, events);
571 void usbi_remove_pollfd(int fd)
573 usbi_dbg("remove fd %d", fd);