Simplify cancellation API
[platform/upstream/libusb.git] / libusb / io.c
1 /*
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>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <config.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/select.h>
28 #include <sys/time.h>
29 #include <time.h>
30 #include <unistd.h>
31
32 #include "libusbi.h"
33
34 #define TRANSFER_TO_PRIV(trf) (container_of((trf), struct usbi_transfer, pub))
35
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;
41
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;
45
46 void usbi_io_init()
47 {
48         list_init(&flying_transfers);
49         fd_added_cb = NULL;
50         fd_removed_cb = NULL;
51 }
52
53 static int calculate_timeout(struct usbi_transfer *transfer)
54 {
55         int r;
56         struct timespec current_time;
57         unsigned int timeout = transfer->pub.timeout;
58
59         if (!timeout)
60                 return 0;
61
62         r = clock_gettime(CLOCK_MONOTONIC, &current_time);
63         if (r < 0) {
64                 usbi_err("failed to read monotonic clock, errno=%d", errno);
65                 return r;
66         }
67
68         current_time.tv_sec += timeout / 1000;
69         current_time.tv_nsec += (timeout % 1000) * 1000000;
70
71         if (current_time.tv_nsec > 1000000000) {
72                 current_time.tv_nsec -= 1000000000;
73                 current_time.tv_sec++;
74         }
75
76         TIMESPEC_TO_TIMEVAL(&transfer->timeout, &current_time);
77         return 0;
78 }
79
80 static void add_to_flying_list(struct usbi_transfer *transfer)
81 {
82         struct usbi_transfer *cur;
83         struct timeval *timeout = &transfer->timeout;
84
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);
88                 return;
89         }
90
91         /* if we have infinite timeout, append to end of list */
92         if (!timerisset(timeout)) {
93                 list_add_tail(&transfer->list, &flying_transfers);
94                 return;
95         }
96
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;
101
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);
106                         return;
107                 }
108         }
109
110         /* otherwise we need to be inserted at the end */
111         list_add_tail(&transfer->list, &flying_transfers);
112 }
113
114 static int submit_transfer(struct usbi_transfer *itransfer)
115 {
116         int r;
117         struct usb_urb *urb = &itransfer->urb;
118         struct libusb_transfer *transfer = &itransfer->pub;
119         int to_be_transferred = transfer->length - itransfer->transferred;
120
121         switch (transfer->endpoint_type) {
122         case LIBUSB_ENDPOINT_TYPE_CONTROL:
123                 urb->type = USB_URB_TYPE_CONTROL;
124                 break;
125         case LIBUSB_ENDPOINT_TYPE_BULK:
126                 urb->type = USB_URB_TYPE_BULK;
127                 break;
128         case LIBUSB_ENDPOINT_TYPE_INTERRUPT:
129                 urb->type = USB_URB_TYPE_INTERRUPT;
130                 break;
131         default:
132                 usbi_err("unknown endpoint type %d", transfer->endpoint_type);
133                 return -EINVAL;
134         }
135
136         urb->endpoint = transfer->endpoint;
137         urb->buffer = transfer->buffer + itransfer->transferred;
138         urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
139
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,
146                 to_be_transferred);
147
148         r = ioctl(transfer->dev_handle->fd, IOCTL_USB_SUBMITURB, urb);
149         if (r < 0) {
150                 usbi_err("submiturb failed error %d errno=%d", r, errno);
151                 return r;
152         }
153
154         add_to_flying_list(itransfer);
155         return 0;
156 }
157
158 API_EXPORTED size_t libusb_get_transfer_alloc_size(void)
159 {
160         return sizeof(struct usbi_transfer);
161 }
162
163 void __init_transfer(struct usbi_transfer *transfer)
164 {
165         memset(transfer, 0, sizeof(*transfer));
166 }
167
168 API_EXPORTED void libusb_init_transfer(struct libusb_transfer *transfer)
169 {
170         __init_transfer(TRANSFER_TO_PRIV(transfer));
171 }
172
173 API_EXPORTED struct libusb_transfer *libusb_alloc_transfer(void)
174 {
175         struct usbi_transfer *transfer = malloc(sizeof(*transfer));
176         if (!transfer)
177                 return NULL;
178
179         __init_transfer(transfer);
180         return &transfer->pub;
181 }
182
183 API_EXPORTED int libusb_submit_transfer(struct libusb_transfer *transfer)
184 {
185         struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
186         int r;
187
188         itransfer->transferred = 0;
189         r = calculate_timeout(itransfer);
190         if (r < 0)
191                 return r;
192
193         if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL) {
194                 struct libusb_control_setup *setup =
195                         (struct libusb_control_setup *) transfer->buffer;
196         
197                 usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
198                         setup->bRequestType, setup->bRequest, setup->wValue, setup->wIndex,
199                         setup->wLength);
200
201                 setup->wValue = cpu_to_le16(setup->wValue);
202                 setup->wIndex = cpu_to_le16(setup->wIndex);
203                 setup->wLength = cpu_to_le16(setup->wLength);
204         }
205
206         return submit_transfer(itransfer);
207 }
208
209 API_EXPORTED int libusb_cancel_transfer(struct libusb_transfer *transfer)
210 {
211         struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
212         int r;
213
214         usbi_dbg("");
215         r = ioctl(transfer->dev_handle->fd, IOCTL_USB_DISCARDURB, &itransfer->urb);
216         if (r < 0)
217                 usbi_err("cancel transfer failed error %d", r);
218         return r;
219 }
220
221 API_EXPORTED int libusb_cancel_transfer_sync(struct libusb_transfer *transfer)
222 {
223         struct usbi_transfer *itransfer = TRANSFER_TO_PRIV(transfer);
224         int r;
225
226         usbi_dbg("");
227         r = ioctl(transfer->dev_handle->fd, IOCTL_USB_DISCARDURB, &itransfer->urb);
228         if (r < 0) {
229                 usbi_err("cancel transfer failed error %d", r);
230                 return r;
231         }
232
233         itransfer->flags |= USBI_TRANSFER_SYNC_CANCELLED;
234         while (itransfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
235                 r = libusb_poll();
236                 if (r < 0)
237                         return r;
238         }
239
240         return 0;
241 }
242
243 static void handle_transfer_completion(struct usbi_transfer *itransfer,
244         enum libusb_transfer_status status)
245 {
246         struct libusb_transfer *transfer = &itransfer->pub;
247
248         if (status == LIBUSB_TRANSFER_SILENT_COMPLETION)
249                 return;
250
251         transfer->status = status;
252         transfer->actual_length = itransfer->transferred;
253         if (transfer->callback)
254                 transfer->callback(transfer);
255 }
256
257 static void handle_transfer_cancellation(struct usbi_transfer *transfer)
258 {
259         /* if the URB is being cancelled synchronously, raise cancellation
260          * completion event by unsetting flag, and ensure that user callback does
261          * not get called.
262          */
263         if (transfer->flags & USBI_TRANSFER_SYNC_CANCELLED) {
264                 transfer->flags &= ~USBI_TRANSFER_SYNC_CANCELLED;
265                 usbi_dbg("detected sync. cancel");
266                 handle_transfer_completion(transfer, LIBUSB_TRANSFER_SILENT_COMPLETION);
267                 return;
268         }
269
270         /* if the URB was cancelled due to timeout, report timeout to the user */
271         if (transfer->flags & USBI_TRANSFER_TIMED_OUT) {
272                 usbi_dbg("detected timeout cancellation");
273                 handle_transfer_completion(transfer, LIBUSB_TRANSFER_TIMED_OUT);
274                 return;
275         }
276
277         /* otherwise its a normal async cancel */
278         handle_transfer_completion(transfer, LIBUSB_TRANSFER_CANCELLED);
279 }
280
281 static int reap_for_devh(struct libusb_device_handle *devh)
282 {
283         int r;
284         struct usb_urb *urb;
285         struct usbi_transfer *itransfer;
286         struct libusb_transfer *transfer;
287         int trf_requested;
288         int length;
289
290         r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
291         if (r == -1 && errno == EAGAIN)
292                 return r;
293         if (r < 0) {
294                 usbi_err("reap failed error %d errno=%d", r, errno);
295                 return r;
296         }
297
298         itransfer = container_of(urb, struct usbi_transfer, urb);
299         transfer = &itransfer->pub;
300
301         usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
302                 urb->actual_length);
303         list_del(&itransfer->list);
304
305         if (urb->status == -2) {
306                 handle_transfer_cancellation(itransfer);
307                 return 0;
308         }
309
310         /* FIXME: research what other status codes may exist */
311         if (urb->status != 0)
312                 usbi_warn("unrecognised urb status %d", urb->status);
313
314         /* determine how much data was asked for */
315         length = transfer->length;
316         if (transfer->endpoint_type == LIBUSB_ENDPOINT_TYPE_CONTROL)
317                 length -= LIBUSB_CONTROL_SETUP_SIZE;
318         trf_requested = MIN(length - itransfer->transferred,
319                 MAX_URB_BUFFER_LENGTH);
320
321         itransfer->transferred += urb->actual_length;
322
323         /* if we were provided less data than requested, then our transfer is
324          * done */
325         if (urb->actual_length < trf_requested) {
326                 usbi_dbg("less data than requested (%d/%d) --> all done",
327                         urb->actual_length, trf_requested);
328                 handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
329                 return 0;
330         }
331
332         /* if we've transferred all data, we're done */
333         if (itransfer->transferred == length) {
334                 usbi_dbg("transfer complete --> all done");
335                 handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED);
336                 return 0;
337         }
338
339         /* otherwise, we have more data to transfer */
340         usbi_dbg("more data to transfer...");
341         memset(urb, 0, sizeof(*urb));
342         return submit_transfer(itransfer);
343 }
344
345 static void handle_timeout(struct usbi_transfer *itransfer)
346 {
347         /* handling timeouts is tricky, as we may race with the kernel: we may
348          * detect a timeout racing with the condition that the urb has actually
349          * completed. we asynchronously cancel the URB and report timeout
350          * to the user when the URB cancellation completes (or not at all if the
351          * URB actually gets delivered as per this race) */
352         struct libusb_transfer *transfer = &itransfer->pub;
353         int r;
354
355         itransfer->flags |= USBI_TRANSFER_TIMED_OUT;
356         r = libusb_cancel_transfer(transfer);
357         if (r < 0)
358                 usbi_warn("async cancel failed %d errno=%d", r, errno);
359 }
360
361 static int handle_timeouts(void)
362 {
363         struct timespec systime_ts;
364         struct timeval systime;
365         struct usbi_transfer *transfer;
366         int r;
367
368         if (list_empty(&flying_transfers))
369                 return 0;
370
371         /* get current time */
372         r = clock_gettime(CLOCK_MONOTONIC, &systime_ts);
373         if (r < 0)
374                 return r;
375
376         TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
377
378         /* iterate through flying transfers list, finding all transfers that
379          * have expired timeouts */
380         list_for_each_entry(transfer, &flying_transfers, list) {
381                 struct timeval *cur_tv = &transfer->timeout;
382
383                 /* if we've reached transfers of infinite timeout, we're all done */
384                 if (!timerisset(cur_tv))
385                         return 0;
386
387                 /* ignore timeouts we've already handled */
388                 if (transfer->flags & USBI_TRANSFER_TIMED_OUT)
389                         continue;
390
391                 /* if transfer has non-expired timeout, nothing more to do */
392                 if ((cur_tv->tv_sec > systime.tv_sec) ||
393                                 (cur_tv->tv_sec == systime.tv_sec &&
394                                         cur_tv->tv_usec > systime.tv_usec))
395                         return 0;
396         
397                 /* otherwise, we've got an expired timeout to handle */
398                 handle_timeout(transfer);
399         }
400
401         return 0;
402 }
403
404 static int poll_io(struct timeval *tv)
405 {
406         struct libusb_device_handle *devh;
407         int r;
408         int maxfd = 0;
409         fd_set writefds;
410         struct timeval select_timeout;
411         struct timeval timeout;
412
413         r = libusb_get_next_timeout(&timeout);
414         if (r) {
415                 /* timeout already expired? */
416                 if (!timerisset(&timeout))
417                         return handle_timeouts();
418
419                 /* choose the smallest of next URB timeout or user specified timeout */
420                 if (timercmp(&timeout, tv, <))
421                         select_timeout = timeout;
422                 else
423                         select_timeout = *tv;
424         } else {
425                 select_timeout = *tv;
426         }
427
428         FD_ZERO(&writefds);
429         list_for_each_entry(devh, &open_devs, list) {
430                 int fd = devh->fd;
431                 FD_SET(fd, &writefds);
432                 if (fd > maxfd)
433                         maxfd = fd;
434         }
435
436         usbi_dbg("select() with timeout in %d.%06ds", select_timeout.tv_sec,
437                 select_timeout.tv_usec);
438         r = select(maxfd + 1, NULL, &writefds, NULL, &select_timeout);
439         usbi_dbg("select() returned %d with %d.%06ds remaining", r, select_timeout.tv_sec,
440                 select_timeout.tv_usec);
441         if (r == 0) {
442                 *tv = select_timeout;
443                 return handle_timeouts();
444         } else if (r == -1 && errno == EINTR) {
445                 return 0;
446         } else if (r < 0) {
447                 usbi_err("select failed %d err=%d\n", r, errno);
448                 return r;
449         }
450
451         list_for_each_entry(devh, &open_devs, list) {
452                 if (!FD_ISSET(devh->fd, &writefds))
453                         continue;
454                 r = reap_for_devh(devh);
455                 if (r == -1 && errno == EAGAIN)
456                         continue;
457                 if (r < 0)
458                         return r;
459         }
460
461         /* FIXME check return value? */
462         return handle_timeouts();
463 }
464
465 API_EXPORTED int libusb_poll_timeout(struct timeval *tv)
466 {
467         return poll_io(tv);
468 }
469
470 API_EXPORTED int libusb_poll(void)
471 {
472         struct timeval tv;
473         tv.tv_sec = 2;
474         tv.tv_usec = 0;
475         return poll_io(&tv);
476 }
477
478 API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
479 {
480         struct usbi_transfer *transfer;
481         struct timespec cur_ts;
482         struct timeval cur_tv;
483         struct timeval *next_timeout;
484         int r;
485         int found = 0;
486
487         if (list_empty(&flying_transfers)) {
488                 usbi_dbg("no URBs, no timeout!");
489                 return 0;
490         }
491
492         /* find next transfer which hasn't already been processed as timed out */
493         list_for_each_entry(transfer, &flying_transfers, list) {
494                 if (!(transfer->flags & USBI_TRANSFER_TIMED_OUT)) {
495                         found = 1;
496                         break;
497                 }
498         }
499
500         if (!found) {
501                 usbi_dbg("all URBs have already been processed for timeouts");
502                 return 0;
503         }
504
505         next_timeout = &transfer->timeout;
506
507         /* no timeout for next transfer */
508         if (!timerisset(next_timeout)) {
509                 usbi_dbg("no URBs with timeouts, no timeout!");
510                 return 0;
511         }
512
513         r = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
514         if (r < 0) {
515                 usbi_err("failed to read monotonic clock, errno=%d", errno);
516                 return r;
517         }
518         TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
519
520         if (timercmp(&cur_tv, next_timeout, >=)) {
521                 usbi_dbg("first timeout already expired");
522                 timerclear(tv);
523         } else {
524                 timersub(next_timeout, &cur_tv, tv);
525                 usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
526         }
527
528         return 1;
529 }
530
531 API_EXPORTED void libusb_free_transfer(struct libusb_transfer *transfer)
532 {
533         struct usbi_transfer *itransfer;
534         if (!transfer)
535                 return;
536
537         itransfer = TRANSFER_TO_PRIV(transfer);
538         free(itransfer);
539 }
540
541 API_EXPORTED void libusb_set_pollfd_notifiers(libusb_pollfd_added_cb added_cb,
542         libusb_pollfd_removed_cb removed_cb)
543 {
544         fd_added_cb = added_cb;
545         fd_removed_cb = removed_cb;
546 }
547
548 void usbi_add_pollfd(int fd, short events)
549 {
550         usbi_dbg("add fd %d events %d", fd, events);
551         if (fd_added_cb)
552                 fd_added_cb(fd, events);
553 }
554
555 void usbi_remove_pollfd(int fd)
556 {
557         usbi_dbg("remove fd %d", fd);
558         if (fd_removed_cb)
559                 fd_removed_cb(fd);
560 }
561