]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libusb/libusb10_io.c
Update to the final release version of BIND 9.6.1. It has the following
[FreeBSD/FreeBSD.git] / lib / libusb / libusb10_io.c
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 2009 Sylvestre Gallon. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/queue.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <poll.h>
32 #include <pthread.h>
33 #include <time.h>
34 #include <errno.h>
35
36 #include "libusb20.h"
37 #include "libusb20_desc.h"
38 #include "libusb20_int.h"
39 #include "libusb.h"
40 #include "libusb10.h"
41
42 static int 
43 get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out)
44 {
45         struct timeval timeout;
46         int ret;
47
48         ret = libusb_get_next_timeout(ctx, &timeout);
49         
50         if (ret) {
51                 if (timerisset(&timeout) == 0)
52                         return 1;
53                 if (timercmp(&timeout, tv, <) != 0)
54                         *out = timeout;
55                 else
56                         *out = *tv;
57         } else {
58                 *out = *tv;
59         }
60
61         return (0);
62 }       
63
64 static int 
65 handle_timeouts(struct libusb_context *ctx)
66 {
67         struct timespec sys_ts;
68         struct timeval sys_tv;
69         struct timeval *cur_tv;
70         struct usb_transfer *xfer;
71         struct libusb_transfer *uxfer;
72         int ret;
73
74         GET_CONTEXT(ctx);
75         ret = 0;
76
77         pthread_mutex_lock(&ctx->flying_transfers_lock);
78         if (USB_LIST_EMPTY(&ctx->flying_transfers))
79                 goto out;
80
81         ret = clock_gettime(CLOCK_MONOTONIC, &sys_ts);
82         TIMESPEC_TO_TIMEVAL(&sys_tv, &sys_ts);
83
84         LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) {
85                 cur_tv = &xfer->timeout;
86
87                 if (timerisset(cur_tv) == 0)
88                         goto out;
89         
90                 if (xfer->flags & USB_TIMED_OUT)
91                         continue;
92         
93                 if ((cur_tv->tv_sec > sys_tv.tv_sec) || (cur_tv->tv_sec == sys_tv.tv_sec &&
94                     cur_tv->tv_usec > sys_tv.tv_usec))
95                         goto out;
96
97                 xfer->flags |= USB_TIMED_OUT;
98                 uxfer = (libusb_transfer *) ((uint8_t *)xfer +
99                     sizeof(struct usb_transfer));
100                 ret = libusb_cancel_transfer(uxfer);
101         }
102 out:
103         pthread_mutex_unlock(&ctx->flying_transfers_lock);
104         return (ret);
105 }
106
107 static int
108 handle_events(struct libusb_context *ctx, struct timeval *tv)
109 {
110         struct libusb_pollfd *tmppollfd;
111         struct libusb_device_handle *devh;
112         struct usb_pollfd *ipollfd;
113         struct usb_transfer *cur;
114         struct usb_transfer *cancel;
115         struct libusb_transfer *xfer;
116         struct pollfd *fds;
117         struct pollfd *tfds;
118         nfds_t nfds;
119         int tmpfd;
120         int tmp;
121         int ret;
122         int timeout;
123         int i;
124        
125         GET_CONTEXT(ctx);
126         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events enter");
127
128         nfds = 0;
129         i = -1;
130
131         pthread_mutex_lock(&ctx->pollfds_lock);
132         LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list)
133                 nfds++;
134
135         fds = malloc(sizeof(*fds) * nfds);
136         if (fds == NULL)
137                 return (LIBUSB_ERROR_NO_MEM);
138
139         LIST_FOREACH_ENTRY(ipollfd, &ctx->pollfds, list) {
140                 tmppollfd = &ipollfd->pollfd;
141                 tmpfd = tmppollfd->fd;
142                 i++;
143                 fds[i].fd = tmpfd;
144                 fds[i].events = tmppollfd->events;
145                 fds[i].revents = 0;
146         }
147
148         pthread_mutex_unlock(&ctx->pollfds_lock);
149
150         timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
151         if (tv->tv_usec % 1000)
152                 timeout++;
153
154         ret = poll(fds, nfds, timeout);
155         if (ret == 0) {
156                 free(fds);
157                 return (handle_timeouts(ctx));
158         } else if (ret == -1 && errno == EINTR) {
159                 free(fds);
160                 return (LIBUSB_ERROR_INTERRUPTED);
161         } else if (ret < 0) {
162                 free(fds);
163                 return (LIBUSB_ERROR_IO);
164         }       
165
166         if (fds[0].revents) {
167                 if (ret == 1){
168                         ret = 0;
169                         goto handled;
170                 } else {
171                         fds[0].revents = 0;
172                         ret--;
173                 }
174         }
175
176         pthread_mutex_lock(&ctx->open_devs_lock);
177         for (i = 0 ; i < nfds && ret > 0 ; i++) {
178
179                 tfds = &fds[i];
180                 if (!tfds->revents)
181                         continue;
182
183                 ret--;
184                 LIST_FOREACH_ENTRY(devh, &ctx->open_devs, list) {
185                         if (libusb20_dev_get_fd(devh->os_priv) == tfds->fd)
186                                 break ;
187                 }
188
189                 if (tfds->revents & POLLERR) {
190                         usb_remove_pollfd(ctx, libusb20_dev_get_fd(devh->os_priv));
191                         usb_handle_disconnect(devh);
192                         continue ;
193                 }
194
195
196                 pthread_mutex_lock(&libusb20_lock);
197                 dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20_PROCESS");
198                 ret = libusb20_dev_process(devh->os_priv);
199                 pthread_mutex_unlock(&libusb20_lock);
200
201
202                 if (ret == 0 || ret == LIBUSB20_ERROR_NO_DEVICE)
203                         continue;
204                 else if (ret < 0)
205                         goto out;
206         }
207
208         ret = 0;
209 out:
210         pthread_mutex_unlock(&ctx->open_devs_lock);
211
212 handled:
213         free(fds);
214         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events leave");
215         return ret;
216 }
217
218 /* Polling and timing */
219
220 int
221 libusb_try_lock_events(libusb_context * ctx)
222 {
223         int ret;
224
225         GET_CONTEXT(ctx);
226         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events enter");
227
228         pthread_mutex_lock(&ctx->pollfd_modify_lock);
229         ret = ctx->pollfd_modify;
230         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
231
232         if (ret != 0)
233                 return (1);
234
235         ret = pthread_mutex_trylock(&ctx->events_lock);
236         
237         if (ret != 0)
238                 return (1);
239         
240         ctx->event_handler_active = 1;
241
242         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events leave");
243         return (0);
244 }
245
246 void
247 libusb_lock_events(libusb_context * ctx)
248 {
249         GET_CONTEXT(ctx);
250         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events enter");
251
252         pthread_mutex_lock(&ctx->events_lock);
253         ctx->event_handler_active = 1;
254
255         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events leave");
256 }
257
258 void
259 libusb_unlock_events(libusb_context * ctx)
260 {
261         GET_CONTEXT(ctx);
262         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events enter");
263
264         ctx->event_handler_active = 0;
265         pthread_mutex_unlock(&ctx->events_lock);
266
267         pthread_mutex_lock(&ctx->event_waiters_lock);
268         pthread_cond_broadcast(&ctx->event_waiters_cond);
269         pthread_mutex_unlock(&ctx->event_waiters_lock);
270
271         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events leave");
272 }
273
274 int
275 libusb_event_handling_ok(libusb_context * ctx)
276 {
277         int ret;
278
279         GET_CONTEXT(ctx);
280         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok enter");
281
282         pthread_mutex_lock(&ctx->pollfd_modify_lock);
283         ret = ctx->pollfd_modify;
284         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
285
286         if (ret != 0)
287                 return (0);
288
289         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok leave");
290         return (1);
291 }
292
293 int
294 libusb_event_handler_active(libusb_context * ctx)
295 {
296         int ret;
297
298         GET_CONTEXT(ctx);
299         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active enter");
300
301         pthread_mutex_lock(&ctx->pollfd_modify_lock);
302         ret = ctx->pollfd_modify;
303         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
304
305         if (ret != 0)
306                 return (1);
307
308         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active leave");
309         return (ctx->event_handler_active);
310 }
311
312 void
313 libusb_lock_event_waiters(libusb_context * ctx)
314 {
315         GET_CONTEXT(ctx);
316         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters enter");
317
318         pthread_mutex_lock(&ctx->event_waiters_lock);
319
320         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters leave");
321 }
322
323 void
324 libusb_unlock_event_waiters(libusb_context * ctx)
325 {
326         GET_CONTEXT(ctx);
327         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters enter");
328
329         pthread_mutex_unlock(&ctx->event_waiters_lock);
330
331         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters leave");
332 }
333
334 int
335 libusb_wait_for_event(libusb_context * ctx, struct timeval *tv)
336 {
337         int ret;
338         struct timespec ts;
339
340         GET_CONTEXT(ctx);
341         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
342
343         if (tv == NULL) {
344                 pthread_cond_wait(&ctx->event_waiters_cond, 
345                     &ctx->event_waiters_lock);
346                 return (0);
347         }
348
349         ret = clock_gettime(CLOCK_REALTIME, &ts);
350         if (ret < 0)
351                 return (LIBUSB_ERROR_OTHER);
352
353         ts.tv_sec = tv->tv_sec;
354         ts.tv_nsec = tv->tv_usec * 1000;
355         if (ts.tv_nsec > 1000000000) {
356                 ts.tv_nsec -= 1000000000;
357                 ts.tv_sec++;
358         }
359
360         ret = pthread_cond_timedwait(&ctx->event_waiters_cond,
361             &ctx->event_waiters_lock, &ts);
362
363         if (ret == ETIMEDOUT)
364                 return (1);
365
366         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event leave");
367         return (0);
368 }
369
370 int
371 libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv)
372 {
373         struct timeval timeout;
374         struct timeval poll_timeout;
375         int ret;
376         
377         GET_CONTEXT(ctx);
378         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter");
379
380         ret = get_next_timeout(ctx, tv, &poll_timeout);
381         if (ret != 0) {
382                 return handle_timeouts(ctx);
383         }
384 retry:
385         if (libusb_try_lock_events(ctx) == 0) {
386                 ret = handle_events(ctx, &poll_timeout);
387                 libusb_unlock_events(ctx);
388                 return ret;
389         }
390
391         libusb_lock_event_waiters(ctx);
392         if (libusb_event_handler_active(ctx) == 0) {
393                 libusb_unlock_event_waiters(ctx);
394                 goto retry;
395         }
396         
397         ret = libusb_wait_for_event(ctx, &poll_timeout);
398         libusb_unlock_event_waiters(ctx);
399
400         if (ret < 0)
401                 return ret;
402         else if (ret == 1)
403                 return (handle_timeouts(ctx));
404
405         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave");
406         return (0);
407 }
408
409 int
410 libusb_handle_events(libusb_context * ctx)
411 {
412         struct timeval tv;
413         int ret;
414
415         GET_CONTEXT(ctx);
416         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events enter");
417
418         tv.tv_sec = 2;
419         tv.tv_usec = 0;
420         ret = libusb_handle_events_timeout(ctx, &tv);
421
422         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events leave");
423         return (ret);
424 }
425
426 int
427 libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv)
428 {
429         int ret;
430         struct timeval poll_tv;
431
432         GET_CONTEXT(ctx);
433         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked enter");
434
435         ret = get_next_timeout(ctx, tv, &poll_tv);
436         if (ret != 0) {
437                 return handle_timeouts(ctx);
438         }
439
440         ret = handle_events(ctx, &poll_tv);
441
442         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked leave");
443         return (ret);
444 }
445
446 int
447 libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv)
448 {
449         struct usb_transfer *xfer;
450         struct timeval *next_tv;
451         struct timeval cur_tv;
452         struct timespec cur_ts;
453         int found;
454         int ret;
455
456         GET_CONTEXT(ctx);
457         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout enter");
458
459         found = 0;
460         pthread_mutex_lock(&ctx->flying_transfers_lock);
461         if (USB_LIST_EMPTY(&ctx->flying_transfers)) {
462                 pthread_mutex_unlock(&ctx->flying_transfers_lock);
463                 return (0);
464         }
465
466         LIST_FOREACH_ENTRY(xfer, &ctx->flying_transfers, list) {
467                 if (!(xfer->flags & USB_TIMED_OUT)) {
468                         found = 1;
469                         break ;
470                 }
471         }
472         pthread_mutex_unlock(&ctx->flying_transfers_lock);
473
474         if (found == 0) {
475                 return 0;
476         }
477
478         next_tv = &xfer->timeout;
479         if (timerisset(next_tv) == 0)
480                 return (0);
481
482         ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
483         if (ret < 0)
484                 return (LIBUSB_ERROR_OTHER);
485         TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);  
486
487         if (timercmp(&cur_tv, next_tv, >=) != 0)
488                 timerclear(tv);
489         else
490                 timersub(next_tv, &cur_tv, tv);
491
492         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout leave");
493         return (1);
494 }
495
496 void
497 libusb_set_pollfd_notifiers(libusb_context * ctx,
498     libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
499     void *user_data)
500 {
501         GET_CONTEXT(ctx);
502         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers enter");
503
504         ctx->fd_added_cb = added_cb;
505         ctx->fd_removed_cb = removed_cb;
506         ctx->fd_cb_user_data = user_data;
507
508         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers leave");
509 }
510
511 struct libusb_pollfd **
512 libusb_get_pollfds(libusb_context * ctx)
513 {
514         struct usb_pollfd *pollfd;
515         libusb_pollfd **ret;
516         int i;
517
518         GET_CONTEXT(ctx);
519         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds enter");
520
521         i = 0;
522         pthread_mutex_lock(&ctx->pollfds_lock);
523         LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list)
524                 i++;
525
526         ret = calloc(i + 1 , sizeof(struct libusb_pollfd *));
527         if (ret == NULL) {
528                 pthread_mutex_unlock(&ctx->pollfds_lock);
529                 return (ret);
530         }
531
532         i = 0;
533         LIST_FOREACH_ENTRY(pollfd, &ctx->pollfds, list)
534                 ret[i++] = (struct libusb_pollfd *) pollfd;
535         ret[i] = NULL;
536
537         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds leave");
538         return (ret);
539 }
540
541
542 /* Synchronous device I/O */
543
544 static void ctrl_tr_cb(struct libusb_transfer *transfer)
545 {
546         libusb_context *ctx;
547         int *complet;
548        
549         ctx = NULL;
550         GET_CONTEXT(ctx);
551         dprintf(ctx, LIBUSB_DEBUG_TRANSFER, "CALLBACK ENTER");
552
553         complet = transfer->user_data;
554         *complet = 1;
555 }
556
557 int
558 libusb_control_transfer(libusb_device_handle * devh,
559     uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
560     unsigned char *data, uint16_t wLength, unsigned int timeout)
561 {
562         struct libusb_transfer *xfer;
563         struct libusb_control_setup *ctr;
564         libusb_context *ctx;
565         unsigned char *buff;
566         int complet;
567         int ret;
568
569         ctx = devh->dev->ctx;
570         GET_CONTEXT(ctx);
571         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer enter");
572
573         if (devh == NULL || data == NULL)
574                 return (LIBUSB_ERROR_NO_MEM);
575
576         xfer = libusb_alloc_transfer(0);
577         if (xfer == NULL)
578                 return (LIBUSB_ERROR_NO_MEM);
579
580         buff = malloc(sizeof(libusb_control_setup) + wLength);
581         if (buff == NULL) {
582                 libusb_free_transfer(xfer);
583                 return (LIBUSB_ERROR_NO_MEM);
584         }
585
586         ctr = (libusb_control_setup *)buff;
587         ctr->bmRequestType = bmRequestType;
588         ctr->bRequest = bRequest;
589         ctr->wValue = wValue;
590         ctr->wIndex = wIndex;
591         ctr->wLength = wLength;
592         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
593                 memcpy(buff + sizeof(libusb_control_setup), data, wLength);
594
595         xfer->dev_handle = devh;
596         xfer->endpoint = 0;
597         xfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
598         xfer->timeout = timeout;
599         xfer->buffer = buff;
600         xfer->length = sizeof(libusb_control_setup) + wLength;
601         xfer->user_data = &complet;
602         xfer->callback = ctrl_tr_cb;
603         xfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
604         complet = 0;
605
606         if ((ret = libusb_submit_transfer(xfer)) < 0) {
607                 libusb_free_transfer(xfer);
608                 return (ret);
609         }
610
611         while (complet == 0)
612                 if ((ret = libusb_handle_events(ctx)) < 0) {
613                         libusb_cancel_transfer(xfer);
614                         while (complet == 0)
615                                 if (libusb_handle_events(ctx) < 0) {
616                                         break;
617                                 }
618                         libusb_free_transfer(xfer);
619                         return (ret);
620                 }
621
622
623         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
624                 memcpy(data, buff + sizeof(libusb_control_setup), wLength);
625
626         switch (xfer->status) {
627         case LIBUSB_TRANSFER_COMPLETED:
628                 ret = xfer->actual_length;
629                 break;
630         case LIBUSB_TRANSFER_TIMED_OUT:
631         case LIBUSB_TRANSFER_STALL:
632         case LIBUSB_TRANSFER_NO_DEVICE:
633                 ret = xfer->status;
634                 break;
635         default:
636                 ret = LIBUSB_ERROR_OTHER;
637         }
638         libusb_free_transfer(xfer);
639
640         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer leave");
641         return (ret);
642 }
643
644 static int
645 do_transfer(struct libusb_device_handle *devh, 
646     unsigned char endpoint, unsigned char *data, int length,
647     int *transferred, unsigned int timeout, int type)
648 {
649         struct libusb_transfer *xfer;
650         libusb_context *ctx;
651         int complet;
652         int ret;
653
654         if (devh == NULL || data == NULL)
655                 return (LIBUSB_ERROR_NO_MEM);
656
657         xfer = libusb_alloc_transfer(0);
658         if (xfer == NULL)
659                 return (LIBUSB_ERROR_NO_MEM);
660
661         ctx = devh->dev->ctx;
662
663         xfer->dev_handle = devh;
664         xfer->endpoint = endpoint;
665         xfer->type = type;
666         xfer->timeout = timeout;
667         xfer->buffer = data;
668         xfer->length = length;
669         xfer->user_data = &complet;
670         xfer->callback = ctrl_tr_cb;
671         complet = 0;
672
673         if ((ret = libusb_submit_transfer(xfer)) < 0) {
674                 libusb_free_transfer(xfer);
675                 return (ret);
676         }
677
678         while (complet == 0) {
679                 if ((ret = libusb_handle_events(ctx)) < 0) {
680                         libusb_cancel_transfer(xfer);
681                         libusb_free_transfer(xfer);
682                         while (complet == 0) {
683                                 if (libusb_handle_events(ctx) < 0)
684                                         break ;
685                         }
686                         return (ret);
687                 }
688         }
689
690         *transferred = xfer->actual_length;
691         switch (xfer->status) {
692         case LIBUSB_TRANSFER_COMPLETED:
693                 ret = xfer->actual_length;
694                 break;
695         case LIBUSB_TRANSFER_TIMED_OUT:
696         case LIBUSB_TRANSFER_OVERFLOW:
697         case LIBUSB_TRANSFER_STALL:
698         case LIBUSB_TRANSFER_NO_DEVICE:
699                 ret = xfer->status;
700                 break;
701         default:
702                 ret = LIBUSB_ERROR_OTHER;
703         }
704
705         libusb_free_transfer(xfer);
706         return (ret);
707 }
708
709 int
710 libusb_bulk_transfer(struct libusb_device_handle *devh,
711     unsigned char endpoint, unsigned char *data, int length,
712     int *transferred, unsigned int timeout)
713 {
714         libusb_context *ctx;
715         int ret;
716         
717         ctx = NULL;
718         GET_CONTEXT(ctx);
719         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
720
721         ret = do_transfer(devh, endpoint, data, length, transferred,
722             timeout, LIBUSB_TRANSFER_TYPE_BULK);
723
724         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
725         return (ret);
726 }
727
728 /*
729  * Need to fix xfer->type
730  */
731 int
732 libusb_interrupt_transfer(struct libusb_device_handle *devh,
733     unsigned char endpoint, unsigned char *data, int length, 
734     int *transferred, unsigned int timeout)
735 {
736         libusb_context *ctx;
737         int ret;
738
739         ctx = NULL;
740         GET_CONTEXT(ctx);
741         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
742
743         ret = do_transfer(devh, endpoint, data, length, transferred,
744             timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
745
746         dprintf(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
747         return (ret);
748 }