Notifications for changes to the fd set
[platform/upstream/libusb.git] / libusb / io.c
1 /*
2  * I/O functions for libusb
3  * Copyright (C) 2007 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
23 #include <errno.h>
24 #include <signal.h>
25 #include <stdint.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <sys/select.h>
29 #include <sys/time.h>
30 #include <time.h>
31 #include <unistd.h>
32
33 #include "libusbi.h"
34
35 /* this is a list of in-flight rb_handles, sorted by timeout expiration.
36  * URBs to timeout the soonest are placed at the beginning of the list, URBs
37  * that will time out later are placed after, and urbs with infinite timeout
38  * are always placed at the very end. */
39 static struct list_head flying_urbs;
40
41 /* user callbacks for pollfd changes */
42 static libusb_pollfd_added_cb fd_added_cb = NULL;
43 static libusb_pollfd_removed_cb fd_removed_cb = NULL;
44
45 void usbi_io_init()
46 {
47         list_init(&flying_urbs);
48         fd_added_cb = NULL;
49         fd_removed_cb = NULL;
50 }
51
52 static int calculate_timeout(struct libusb_urb_handle *urbh,
53         unsigned int timeout)
54 {
55         int r;
56         struct timespec current_time;
57
58         if (!timeout)
59                 return 0;
60
61         r = clock_gettime(CLOCK_MONOTONIC, &current_time);
62         if (r < 0) {
63                 usbi_err("failed to read monotonic clock, errno=%d", errno);
64                 return r;
65         }
66
67         current_time.tv_sec += timeout / 1000;
68         current_time.tv_nsec += (timeout % 1000) * 1000000;
69
70         if (current_time.tv_nsec > 1000000000) {
71                 current_time.tv_nsec -= 1000000000;
72                 current_time.tv_sec++;
73         }
74
75         TIMESPEC_TO_TIMEVAL(&urbh->timeout, &current_time);
76         return 0;
77 }
78
79 static void add_to_flying_list(struct libusb_urb_handle *urbh)
80 {
81         struct libusb_urb_handle *cur;
82         struct timeval *timeout = &urbh->timeout;
83
84         /* if we have no other flying urbs, start the list with this one */
85         if (list_empty(&flying_urbs)) {
86                 list_add(&urbh->list, &flying_urbs);
87                 return;
88         }
89
90         /* if we have infinite timeout, append to end of list */
91         if (!timerisset(timeout)) {
92                 list_add_tail(&urbh->list, &flying_urbs);
93                 return;
94         }
95
96         /* otherwise, find appropriate place in list */
97         list_for_each_entry(cur, &flying_urbs, list) {
98                 /* find first timeout that occurs after the urbh in question */
99                 struct timeval *cur_tv = &cur->timeout;
100
101                 if (!timerisset(cur_tv) || (cur_tv->tv_sec > timeout->tv_sec) ||
102                                 (cur_tv->tv_sec == timeout->tv_sec &&
103                                         cur_tv->tv_usec > timeout->tv_usec)) {
104                         list_add_tail(&urbh->list, &cur->list);
105                         return;
106                 }
107         }
108
109         /* otherwise we need to be inserted at the end */
110         list_add_tail(&urbh->list, &flying_urbs);
111 }
112
113 static int submit_urb(struct libusb_dev_handle *devh,
114         struct libusb_urb_handle *urbh)
115 {
116         int r;
117         struct usb_urb *urb = &urbh->urb;
118         int to_be_transferred = urbh->transfer_len - urbh->transferred;
119
120         urb->type = urbh->urb_type;
121         urb->endpoint = urbh->endpoint;
122         urb->buffer = urbh->buffer + urbh->transferred;
123         urb->buffer_length = MIN(to_be_transferred, MAX_URB_BUFFER_LENGTH);
124
125         /* FIXME: for requests that we have to split into multiple URBs, we should
126          * submit all the URBs instantly: submit, submit, submit, reap, reap, reap
127          * rather than: submit, reap, submit, reap, submit, reap
128          * this will improve performance and fix bugs concerning behaviour when
129          * the user submits two similar multiple-urb requests */
130         usbi_dbg("transferring %d from %d bytes", urb->buffer_length,
131                 to_be_transferred);
132
133         r = ioctl(devh->fd, IOCTL_USB_SUBMITURB, &urbh->urb);
134         if (r < 0) {
135                 usbi_err("submiturb failed error %d errno=%d", r, errno);
136                 return r;
137         }
138
139         add_to_flying_list(urbh);
140         return 0;
141 }
142
143 API_EXPORTED struct libusb_urb_handle *libusb_async_control_transfer(
144         struct libusb_dev_handle *devh, struct libusb_control_transfer *transfer,
145         libusb_ctrl_cb_fn callback, void *user_data, unsigned int timeout)
146 {
147         struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
148         struct libusb_ctrl_setup *setup;
149         unsigned char *urbdata;
150         int urbdata_length = sizeof(struct libusb_ctrl_setup) + transfer->length;
151         int r;
152
153         if (!urbh)
154                 return NULL;
155         memset(urbh, 0, sizeof(*urbh));
156         urbh->devh = devh;
157         urbh->callback = callback;
158         urbh->user_data = user_data;
159         r = calculate_timeout(urbh, timeout);
160         if (r < 0) {
161                 free(urbh);
162                 return NULL;
163         }
164
165         urbdata = malloc(urbdata_length);
166         if (!urbdata) {
167                 free(urbh);
168                 return NULL;
169         }
170
171         usbi_dbg("RQT=%02x RQ=%02x VAL=%04x IDX=%04x length=%d",
172                 transfer->requesttype, transfer->request, transfer->value,
173                 transfer->index, transfer->length);
174
175         setup = (struct libusb_ctrl_setup *) urbdata;
176         setup->bRequestType = transfer->requesttype;
177         setup->bRequest = transfer->request;
178         setup->wValue = cpu_to_le16(transfer->value);
179         setup->wIndex = cpu_to_le16(transfer->index);
180         setup->wLength = cpu_to_le16(transfer->length);
181
182         if ((transfer->requesttype & 0x80) == LIBUSB_ENDPOINT_OUT)
183                 memcpy(urbdata + sizeof(struct libusb_ctrl_setup), transfer->data,
184                 transfer->length);
185
186         urbh->urb_type = USB_URB_TYPE_CONTROL;
187         urbh->buffer = urbdata;
188         urbh->transfer_len = urbdata_length;
189
190         r = submit_urb(devh, urbh);
191         if (r < 0) {
192                 free(urbh);
193                 free(urbdata);
194                 return NULL;
195         }
196
197         return urbh;
198 }
199
200 static struct libusb_urb_handle *submit_bulk_transfer(
201         struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
202         libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout,
203         unsigned char urbtype)
204 {
205         struct libusb_urb_handle *urbh = malloc(sizeof(*urbh));
206         int r;
207
208         usbi_dbg("length %d timeout %d", transfer->length, timeout);
209
210         if (!urbh)
211                 return NULL;
212         memset(urbh, 0, sizeof(*urbh));
213         r = calculate_timeout(urbh, timeout);
214         if (r < 0) {
215                 free(urbh);
216                 return NULL;
217         }
218         urbh->devh = devh;
219         urbh->callback = callback;
220         urbh->user_data = user_data;
221         urbh->flags |= LIBUSB_URBH_DATA_BELONGS_TO_USER;
222         urbh->endpoint = transfer->endpoint;
223         urbh->urb_type = urbtype;
224         urbh->buffer = transfer->data;
225         urbh->transfer_len = transfer->length;
226
227         r = submit_urb(devh, urbh);
228         if (r < 0) {
229                 free(urbh);
230                 return NULL;
231         }
232
233         return urbh;
234 }
235
236 API_EXPORTED struct libusb_urb_handle *libusb_async_bulk_transfer(
237         struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
238         libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
239 {
240         return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
241                 USB_URB_TYPE_BULK);
242 }
243
244 API_EXPORTED struct libusb_urb_handle *libusb_async_interrupt_transfer(
245         struct libusb_dev_handle *devh, struct libusb_bulk_transfer *transfer,
246         libusb_bulk_cb_fn callback, void *user_data, unsigned int timeout)
247 {
248         return submit_bulk_transfer(devh, transfer, callback, user_data, timeout,
249                 USB_URB_TYPE_INTERRUPT);
250 }
251
252 API_EXPORTED int libusb_urb_handle_cancel(struct libusb_dev_handle *devh,
253         struct libusb_urb_handle *urbh)
254 {
255         int r;
256         usbi_dbg("");
257         r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
258         if (r < 0)
259                 usbi_err("cancel urb failed error %d", r);
260         return r;
261 }
262
263 API_EXPORTED int libusb_urb_handle_cancel_sync(struct libusb_dev_handle *devh,
264         struct libusb_urb_handle *urbh)
265 {
266         int r;
267         usbi_dbg("");
268         r = ioctl(devh->fd, IOCTL_USB_DISCARDURB, &urbh->urb);
269         if (r < 0) {
270                 usbi_err("cancel urb failed error %d", r);
271                 return r;
272         }
273
274         urbh->flags |= LIBUSB_URBH_SYNC_CANCELLED;
275         while (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
276                 r = libusb_poll();
277                 if (r < 0)
278                         return r;
279         }
280
281         return 0;
282 }
283
284 #include <stdio.h>
285 int handle_transfer_completion(struct libusb_dev_handle *devh,
286         struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status)
287 {
288         struct usb_urb *urb = &urbh->urb;
289
290         if (status == FP_URB_SILENT_COMPLETION)
291                 return 0;
292
293         if (urb->type == USB_URB_TYPE_CONTROL) {
294                 libusb_ctrl_cb_fn callback = urbh->callback;
295                 int i;
296                 printf("ctrl completed status %d\n", status);
297                 for (i = 0; i < urbh->transferred + sizeof(struct libusb_ctrl_setup); i++)
298                         printf("%02x ", ((unsigned char *) urb->buffer)[i]);
299                 printf("\n");
300                 if (callback)
301                         callback(devh, urbh, status, urb->buffer,
302                                 urb->buffer + sizeof(struct libusb_ctrl_setup), urbh->transferred,
303                                 urbh->user_data);
304         } else if (urb->type == USB_URB_TYPE_BULK ||
305                         urb->type == USB_URB_TYPE_INTERRUPT) {
306                 libusb_bulk_cb_fn callback = urbh->callback;
307                 if (callback)
308                         callback(devh, urbh, status, urbh->endpoint, urbh->transfer_len,
309                                 urbh->buffer, urbh->transferred, urbh->user_data);
310         }
311         return 0;
312 }
313
314 static int handle_transfer_cancellation(struct libusb_dev_handle *devh,
315         struct libusb_urb_handle *urbh)
316 {
317         /* if the URB is being cancelled synchronously, raise cancellation
318          * completion event by unsetting flag, and ensure that user callback does
319          * not get called.
320          */
321         if (urbh->flags & LIBUSB_URBH_SYNC_CANCELLED) {
322                 urbh->flags &= ~LIBUSB_URBH_SYNC_CANCELLED;
323                 usbi_dbg("detected sync. cancel");
324                 return handle_transfer_completion(devh, urbh, FP_URB_SILENT_COMPLETION);
325         }
326
327         /* if the URB was cancelled due to timeout, report timeout to the user */
328         if (urbh->flags & LIBUSB_URBH_TIMED_OUT) {
329                 usbi_dbg("detected timeout cancellation");
330                 return handle_transfer_completion(devh, urbh, FP_URB_TIMEOUT);
331         }
332
333         /* otherwise its a normal async cancel */
334         return handle_transfer_completion(devh, urbh, FP_URB_CANCELLED);
335 }
336
337 static int reap_for_devh(struct libusb_dev_handle *devh)
338 {
339         int r;
340         struct usb_urb *urb;
341         struct libusb_urb_handle *urbh;
342         int trf_requested;
343
344         r = ioctl(devh->fd, IOCTL_USB_REAPURBNDELAY, &urb);
345         if (r == -1 && errno == EAGAIN)
346                 return r;
347         if (r < 0) {
348                 usbi_err("reap failed error %d errno=%d", r, errno);
349                 return r;
350         }
351
352         urbh = container_of(urb, struct libusb_urb_handle, urb);
353
354         usbi_dbg("urb type=%d status=%d transferred=%d", urb->type, urb->status,
355                 urb->actual_length);
356         list_del(&urbh->list);
357
358         if (urb->status == -2)
359                 return handle_transfer_cancellation(devh, urbh);
360         /* FIXME: research what other status codes may exist */
361         if (urb->status != 0)
362                 usbi_warn("unrecognised urb status %d", urb->status);
363
364         /* determine how much data was asked for */
365         trf_requested = MIN(urbh->transfer_len - urbh->transferred,
366                 MAX_URB_BUFFER_LENGTH);
367
368         urbh->transferred += urb->actual_length;        
369
370         /* if we were provided less data than requested, then our transfer is
371          * done */
372         if (urb->actual_length < trf_requested) {
373                 usbi_dbg("less data than requested (%d/%d) --> all done",
374                         urb->actual_length, trf_requested);
375                 return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
376         }
377
378         /* if we've transferred all data, we're done */
379         if (urbh->transferred == urbh->transfer_len) {
380                 usbi_dbg("transfer complete --> all done");
381                 return handle_transfer_completion(devh, urbh, FP_URB_COMPLETED);
382         }
383
384         /* otherwise, we have more data to transfer */
385         usbi_dbg("more data to transfer...");
386         memset(urb, 0, sizeof(*urb));
387         return submit_urb(devh, urbh);
388 }
389
390 static void handle_timeout(struct libusb_urb_handle *urbh)
391 {
392         /* handling timeouts is tricky, as we may race with the kernel: we may
393          * detect a timeout racing with the condition that the urb has actually
394          * completed. we asynchronously cancel the URB and report timeout
395          * to the user when the URB cancellation completes (or not at all if the
396          * URB actually gets delivered as per this race) */
397         int r;
398
399
400         urbh->flags |= LIBUSB_URBH_TIMED_OUT;
401         r = libusb_urb_handle_cancel(urbh->devh, urbh);
402         if (r < 0)
403                 usbi_warn("async cancel failed %d errno=%d", r, errno);
404 }
405
406 static int handle_timeouts(void)
407 {
408         struct timespec systime_ts;
409         struct timeval systime;
410         struct libusb_urb_handle *urbh;
411         int r;
412
413         if (list_empty(&flying_urbs))
414                 return 0;
415
416         /* get current time */
417         r = clock_gettime(CLOCK_MONOTONIC, &systime_ts);
418         if (r < 0)
419                 return r;
420
421         TIMESPEC_TO_TIMEVAL(&systime, &systime_ts);
422
423         /* iterate through flying urbs list, finding all urbs that have expired
424          * timeouts */
425         list_for_each_entry(urbh, &flying_urbs, list) {
426                 struct timeval *cur_tv = &urbh->timeout;
427
428                 /* if we've reached urbs of infinite timeout, we're all done */
429                 if (!timerisset(cur_tv))
430                         return 0;
431
432                 /* ignore timeouts we've already handled */
433                 if (urbh->flags & LIBUSB_URBH_TIMED_OUT)
434                         continue;
435
436                 /* if urb has non-expired timeout, nothing more to do */
437                 if ((cur_tv->tv_sec > systime.tv_sec) ||
438                                 (cur_tv->tv_sec == systime.tv_sec &&
439                                         cur_tv->tv_usec > systime.tv_usec))
440                         return 0;
441         
442                 /* otherwise, we've got an expired timeout to handle */
443                 handle_timeout(urbh);
444         }
445
446         return 0;
447 }
448
449 static int poll_io(struct timeval *tv)
450 {
451         struct libusb_dev_handle *devh;
452         int r;
453         int maxfd = 0;
454         fd_set writefds;
455         struct timeval select_timeout;
456         struct timeval timeout;
457
458         r = libusb_get_next_timeout(&timeout);
459         if (r) {
460                 /* timeout already expired? */
461                 if (!timerisset(&timeout))
462                         return handle_timeouts();
463
464                 /* choose the smallest of next URB timeout or user specified timeout */
465                 if (timercmp(&timeout, tv, <))
466                         select_timeout = timeout;
467                 else
468                         select_timeout = *tv;
469         } else {
470                 select_timeout = *tv;
471         }
472
473         FD_ZERO(&writefds);
474         list_for_each_entry(devh, &open_devs, list) {
475                 int fd = devh->fd;
476                 FD_SET(fd, &writefds);
477                 if (fd > maxfd)
478                         maxfd = fd;
479         }
480
481         usbi_dbg("select() with timeout in %d.%06ds", select_timeout.tv_sec,
482                 select_timeout.tv_usec);
483         r = select(maxfd + 1, NULL, &writefds, NULL, &select_timeout);
484         usbi_dbg("select() returned %d with %d.%06ds remaining", r, select_timeout.tv_sec,
485                 select_timeout.tv_usec);
486         if (r == 0) {
487                 *tv = select_timeout;
488                 return handle_timeouts();
489         } else if (r == -1 && errno == EINTR) {
490                 return 0;
491         } else if (r < 0) {
492                 usbi_err("select failed %d err=%d\n", r, errno);
493                 return r;
494         }
495
496         list_for_each_entry(devh, &open_devs, list) {
497                 if (!FD_ISSET(devh->fd, &writefds))
498                         continue;
499                 r = reap_for_devh(devh);
500                 if (r == -1 && errno == EAGAIN)
501                         continue;
502                 if (r < 0)
503                         return r;
504         }
505
506         /* FIXME check return value? */
507         return handle_timeouts();
508 }
509
510 API_EXPORTED int libusb_poll_timeout(struct timeval *tv)
511 {
512         return poll_io(tv);
513 }
514
515 API_EXPORTED int libusb_poll(void)
516 {
517         struct timeval tv;
518         tv.tv_sec = 2;
519         tv.tv_usec = 0;
520         return poll_io(&tv);
521 }
522
523 API_EXPORTED int libusb_get_next_timeout(struct timeval *tv)
524 {
525         struct libusb_urb_handle *urbh;
526         struct timespec cur_ts;
527         struct timeval cur_tv;
528         struct timeval *next_timeout;
529         int r;
530         int found = 0;
531
532         if (list_empty(&flying_urbs)) {
533                 usbi_dbg("no URBs, no timeout!");
534                 return 0;
535         }
536
537         /* find next urb which hasn't already been processed as timed out */
538         list_for_each_entry(urbh, &flying_urbs, list) {
539                 if (!(urbh->flags & LIBUSB_URBH_TIMED_OUT)) {
540                         found = 1;
541                         break;
542                 }
543         }
544
545         if (!found) {
546                 usbi_dbg("all URBs have already been processed for timeouts");
547                 return 0;
548         }
549
550         next_timeout = &urbh->timeout;
551
552         /* no timeout for next urb */
553         if (!timerisset(next_timeout)) {
554                 usbi_dbg("no URBs with timeouts, no timeout!");
555                 return 0;
556         }
557
558         r = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
559         if (r < 0) {
560                 usbi_err("failed to read monotonic clock, errno=%d", errno);
561                 return r;
562         }
563         TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);
564
565         if (timercmp(&cur_tv, next_timeout, >=)) {
566                 usbi_dbg("first timeout already expired");
567                 timerclear(tv);
568         } else {
569                 timersub(next_timeout, &cur_tv, tv);
570                 usbi_dbg("next timeout in %d.%06ds", tv->tv_sec, tv->tv_usec);
571         }
572
573         return 1;
574 }
575
576 struct sync_ctrl_handle {
577         enum libusb_urb_cb_status status;
578         unsigned char *data;
579         int actual_length;
580 };
581
582 static void ctrl_transfer_cb(struct libusb_dev_handle *devh,
583         struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
584         struct libusb_ctrl_setup *setup, unsigned char *data, int actual_length,
585         void *user_data)
586 {
587         struct sync_ctrl_handle *ctrlh = (struct sync_ctrl_handle *) user_data;
588         usbi_dbg("actual_length=%d", actual_length);
589
590         if (status == FP_URB_COMPLETED) {
591                 /* copy results into user-defined buffer */
592                 if (setup->bRequestType & LIBUSB_ENDPOINT_IN)
593                         memcpy(ctrlh->data, data, actual_length);
594         }
595
596         ctrlh->status = status;
597         ctrlh->actual_length = actual_length;
598         /* caller frees urbh */
599 }
600
601 API_EXPORTED int libusb_control_transfer(struct libusb_dev_handle *devh,
602         struct libusb_control_transfer *transfer, unsigned int timeout)
603 {
604         struct libusb_urb_handle *urbh;
605         struct sync_ctrl_handle ctrlh;
606
607         memset(&ctrlh, 0, sizeof(ctrlh));
608         ctrlh.data = transfer->data;
609
610         urbh = libusb_async_control_transfer(devh, transfer, ctrl_transfer_cb,
611                 &ctrlh, timeout);
612         if (!urbh)
613                 return -1;
614
615         while (!ctrlh.status) {
616                 int r = libusb_poll();
617                 if (r < 0) {
618                         libusb_urb_handle_cancel_sync(devh, urbh);
619                         libusb_urb_handle_free(urbh);
620                         return r;
621                 }
622         }
623
624         libusb_urb_handle_free(urbh);
625         switch (ctrlh.status) {
626         case FP_URB_COMPLETED:
627                 return ctrlh.actual_length;
628         case FP_URB_TIMEOUT:
629                 return -ETIMEDOUT;
630         default:
631                 usbi_warn("unrecognised status code %d", ctrlh.status);
632                 return -1;
633         }
634 }
635
636 struct sync_bulk_handle {
637         enum libusb_urb_cb_status status;
638         int actual_length;
639 };
640
641 static void bulk_transfer_cb(struct libusb_dev_handle *devh,
642         struct libusb_urb_handle *urbh, enum libusb_urb_cb_status status,
643         unsigned char endpoint, int rqlength, unsigned char *data,
644         int actual_length, void *user_data)
645 {
646         struct sync_bulk_handle *bulkh = (struct sync_bulk_handle *) user_data;
647         usbi_dbg("");
648         bulkh->status = status;
649         bulkh->actual_length = actual_length;
650         /* caller frees urbh */
651 }
652
653 static int do_sync_bulk_transfer(struct libusb_dev_handle *devh,
654         struct libusb_bulk_transfer *transfer, int *transferred,
655         unsigned int timeout, unsigned char urbtype)
656 {
657         struct libusb_urb_handle *urbh;
658         struct sync_bulk_handle bulkh;
659
660         memset(&bulkh, 0, sizeof(bulkh));
661
662         urbh = submit_bulk_transfer(devh, transfer, bulk_transfer_cb, &bulkh,
663                 timeout, urbtype);
664         if (!urbh)
665                 return -1;
666
667         while (!bulkh.status) {
668                 int r = libusb_poll();
669                 if (r < 0) {
670                         libusb_urb_handle_cancel_sync(devh, urbh);
671                         libusb_urb_handle_free(urbh);
672                         return r;
673                 }
674         }
675
676         *transferred = bulkh.actual_length;
677         libusb_urb_handle_free(urbh);
678
679         switch (bulkh.status) {
680         case FP_URB_COMPLETED:
681                 return 0;
682         case FP_URB_TIMEOUT:
683                 return -ETIMEDOUT;
684         default:
685                 usbi_warn("unrecognised status code %d", bulkh.status);
686                 return -1;
687         }
688 }
689
690 API_EXPORTED int libusb_interrupt_transfer(struct libusb_dev_handle *devh,
691         struct libusb_bulk_transfer *transfer, int *transferred,
692         unsigned int timeout)
693 {
694         return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
695                 USB_URB_TYPE_INTERRUPT);
696 }
697
698 API_EXPORTED int libusb_bulk_transfer(struct libusb_dev_handle *devh,
699         struct libusb_bulk_transfer *transfer, int *transferred,
700         unsigned int timeout)
701 {
702         return do_sync_bulk_transfer(devh, transfer, transferred, timeout,
703                 USB_URB_TYPE_BULK);
704 }
705
706 API_EXPORTED void libusb_urb_handle_free(struct libusb_urb_handle *urbh)
707 {
708         if (!urbh)
709                 return;
710
711         if (!(urbh->flags & LIBUSB_URBH_DATA_BELONGS_TO_USER))
712                 free(urbh->urb.buffer);
713         free(urbh);
714 }
715
716 API_EXPORTED void libusb_set_pollfd_notifiers(libusb_pollfd_added_cb added_cb,
717         libusb_pollfd_removed_cb removed_cb)
718 {
719         fd_added_cb = added_cb;
720         fd_removed_cb = removed_cb;
721 }
722
723 void usbi_add_pollfd(int fd, short events)
724 {
725         usbi_dbg("add fd %d events %d", fd, events);
726         if (fd_added_cb)
727                 fd_added_cb(fd, events);
728 }
729
730 void usbi_remove_pollfd(int fd)
731 {
732         usbi_dbg("remove fd %d", fd);
733         if (fd_removed_cb)
734                 fd_removed_cb(fd);
735 }
736