]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libusb/libusb10_io.c
Update less to v436. This is considered as a bugfix release from vendor.
[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 UNEXPORTED int
43 usb_add_pollfd(libusb_context *ctx, int fd, short events)
44 {
45         struct usb_pollfd *pollfd;
46
47         if (ctx == NULL)
48                 return (LIBUSB_ERROR_INVALID_PARAM);
49         
50         pollfd = malloc(sizeof(*pollfd));
51         if (pollfd == NULL)
52                 return (LIBUSB_ERROR_NO_MEM);
53
54         pollfd->pollfd.fd = fd;
55         pollfd->pollfd.events = events;
56
57         pthread_mutex_lock(&ctx->pollfds_lock);
58         TAILQ_INSERT_TAIL(&ctx->pollfds, pollfd, list);
59         pthread_mutex_unlock(&ctx->pollfds_lock);
60
61         if (ctx->fd_added_cb)
62                 ctx->fd_added_cb(fd, events, ctx->fd_cb_user_data);
63         return (0);
64 }
65
66 UNEXPORTED void
67 usb_remove_pollfd(libusb_context *ctx, int fd)
68 {
69         struct usb_pollfd *pollfd;
70         int found;
71
72         found = 0;
73         pthread_mutex_lock(&ctx->pollfds_lock);
74
75         TAILQ_FOREACH(pollfd, &ctx->pollfds, list) {
76                 if (pollfd->pollfd.fd == fd) {
77                         found = 1;
78                         break ;
79                 }
80         }
81
82         if (found == 0) {
83                 pthread_mutex_unlock(&ctx->pollfds_lock);
84                 return ;
85         }
86
87         TAILQ_REMOVE(&ctx->pollfds, pollfd, list);
88         pthread_mutex_unlock(&ctx->pollfds_lock);
89         free(pollfd);
90
91         if (ctx->fd_removed_cb)
92                 ctx->fd_removed_cb(fd, ctx->fd_cb_user_data);
93 }
94
95 UNEXPORTED void
96 usb_handle_transfer_completion(struct usb_transfer *uxfer, 
97     enum libusb_transfer_status status)
98 {
99         libusb_transfer *xfer;
100         libusb_context *ctx;
101         int len;
102
103         xfer = (struct libusb_transfer *) ((uint8_t *)uxfer + 
104             sizeof(struct usb_transfer));
105         ctx = xfer->dev_handle->dev->ctx;
106
107         pthread_mutex_lock(&ctx->flying_transfers_lock);
108         TAILQ_REMOVE(&ctx->flying_transfers, uxfer, list);
109         pthread_mutex_unlock(&ctx->flying_transfers_lock);
110
111         if (status == LIBUSB_TRANSFER_COMPLETED && xfer->flags &
112             LIBUSB_TRANSFER_SHORT_NOT_OK) {
113                 len = xfer->length;
114                 if (xfer->type == LIBUSB_TRANSFER_TYPE_CONTROL)
115                         len -= sizeof(libusb_control_setup);
116                 if (len != uxfer->transferred) {
117                         status = LIBUSB_TRANSFER_ERROR;
118                 }
119         }
120
121         xfer->status = status;
122         xfer->actual_length = uxfer->transferred;
123
124         if (xfer->callback)
125                 xfer->callback(xfer);
126         if (xfer->flags & LIBUSB_TRANSFER_FREE_TRANSFER)
127                 libusb_free_transfer(xfer);
128
129         pthread_mutex_lock(&ctx->event_waiters_lock);
130         pthread_cond_broadcast(&ctx->event_waiters_cond);
131         pthread_mutex_unlock(&ctx->event_waiters_lock);
132 }
133
134 UNEXPORTED void
135 usb_handle_disconnect(struct libusb_device_handle *devh)
136 {
137         struct libusb_context *ctx;
138         struct libusb_transfer *xfer;
139         struct usb_transfer *cur;
140         struct usb_transfer *to_cancel;
141
142         ctx = devh->dev->ctx;
143
144         while (1) {
145                 pthread_mutex_lock(&ctx->flying_transfers_lock);
146                 to_cancel = NULL;
147                 TAILQ_FOREACH(cur, &ctx->flying_transfers, list) {
148                         xfer = (struct libusb_transfer *) ((uint8_t *)cur + 
149                             sizeof(struct usb_transfer));
150                         if (xfer->dev_handle == devh) {
151                                 to_cancel = cur;
152                                 break ;
153                         }
154                 }
155                 pthread_mutex_unlock(&ctx->flying_transfers_lock);
156
157                 if (to_cancel == NULL)
158                         break ;
159                 
160                 usb_handle_transfer_completion(to_cancel, LIBUSB_TRANSFER_NO_DEVICE);
161         }
162         return ;
163 }
164
165 UNEXPORTED int 
166 get_next_timeout(libusb_context *ctx, struct timeval *tv, struct timeval *out)
167 {
168         struct timeval timeout;
169
170         if (libusb_get_next_timeout(ctx, &timeout)) {
171                 if (timerisset(&timeout) == 0)
172                         return 1;
173                 if (timercmp(&timeout, tv, <) != 0)
174                         *out = timeout;
175                 else
176                         *out = *tv;
177         } else {
178                 *out = *tv;
179         }
180
181         return (0);
182 }       
183
184 UNEXPORTED int 
185 handle_timeouts(struct libusb_context *ctx)
186 {
187         struct timespec sys_ts;
188         struct timeval sys_tv;
189         struct timeval *cur_tv;
190         struct usb_transfer *xfer;
191         struct libusb_transfer *uxfer;
192         int ret;
193
194         GET_CONTEXT(ctx);
195         ret = 0;
196
197         pthread_mutex_lock(&ctx->flying_transfers_lock);
198         if (TAILQ_EMPTY(&ctx->flying_transfers))
199                 goto out;
200
201         ret = clock_gettime(CLOCK_MONOTONIC, &sys_ts);
202         TIMESPEC_TO_TIMEVAL(&sys_tv, &sys_ts);
203
204         TAILQ_FOREACH(xfer, &ctx->flying_transfers, list) {
205                 cur_tv = &xfer->timeout;
206
207                 if (timerisset(cur_tv) == 0)
208                         goto out;
209         
210                 if (xfer->flags & USB_TIMED_OUT)
211                         continue;
212         
213                 if ((cur_tv->tv_sec > sys_tv.tv_sec) || (cur_tv->tv_sec == sys_tv.tv_sec &&
214                     cur_tv->tv_usec > sys_tv.tv_usec))
215                         goto out;
216
217                 xfer->flags |= USB_TIMED_OUT;
218                 uxfer = (libusb_transfer *) ((uint8_t *)xfer +
219                     sizeof(struct usb_transfer));
220                 ret = libusb_cancel_transfer(uxfer);
221         }
222 out:
223         pthread_mutex_unlock(&ctx->flying_transfers_lock);
224         return (ret);
225 }
226
227 UNEXPORTED int
228 handle_events(struct libusb_context *ctx, struct timeval *tv)
229 {
230         struct libusb_pollfd *tmppollfd;
231         struct libusb_device_handle *devh;
232         struct usb_pollfd *ipollfd;
233         struct pollfd *fds;
234         struct pollfd *tfds;
235         nfds_t nfds;
236         int tmpfd;
237         int ret;
238         int timeout;
239         int i;
240        
241         GET_CONTEXT(ctx);
242         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events enter");
243
244         nfds = 0;
245         i = -1;
246
247         pthread_mutex_lock(&ctx->pollfds_lock);
248         TAILQ_FOREACH(ipollfd, &ctx->pollfds, list)
249                 nfds++;
250
251         fds = alloca(sizeof(*fds) * nfds);
252         if (fds == NULL)
253                 return (LIBUSB_ERROR_NO_MEM);
254
255         TAILQ_FOREACH(ipollfd, &ctx->pollfds, list) {
256                 tmppollfd = &ipollfd->pollfd;
257                 tmpfd = tmppollfd->fd;
258                 i++;
259                 fds[i].fd = tmpfd;
260                 fds[i].events = tmppollfd->events;
261                 fds[i].revents = 0;
262         }
263
264         pthread_mutex_unlock(&ctx->pollfds_lock);
265
266         timeout = (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
267         if (tv->tv_usec % 1000)
268                 timeout++;
269
270         ret = poll(fds, nfds, timeout);
271         if (ret == 0) 
272                 return (handle_timeouts(ctx));
273         else if (ret == -1 && errno == EINTR)
274                 return (LIBUSB_ERROR_INTERRUPTED);
275         else if (ret < 0) 
276                 return (LIBUSB_ERROR_IO);
277
278         if (fds[0].revents) {
279                 if (ret == 1){
280                         ret = 0;
281                         goto handled;
282                 } else {
283                         fds[0].revents = 0;
284                         ret--;
285                 }
286         }
287
288         pthread_mutex_lock(&ctx->open_devs_lock);
289         for (i = 0, devh = NULL ; i < nfds && ret > 0 ; i++) {
290
291                 tfds = &fds[i];
292                 if (!tfds->revents)
293                         continue;
294
295                 ret--;
296                 TAILQ_FOREACH(devh, &ctx->open_devs, list) {
297                         if (libusb20_dev_get_fd(devh->os_priv) == tfds->fd)
298                                 break ;
299                 }
300
301                 if (tfds->revents & POLLERR) {
302                         usb_remove_pollfd(ctx, libusb20_dev_get_fd(devh->os_priv));
303                         if (devh != NULL)
304                                 usb_handle_disconnect(devh);
305                         continue ;
306                 }
307
308
309                 pthread_mutex_lock(&libusb20_lock);
310                 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "LIBUSB20_PROCESS");
311                 if (devh != NULL)
312                         ret = libusb20_dev_process(devh->os_priv);
313                 pthread_mutex_unlock(&libusb20_lock);
314
315
316                 if (ret == 0 || ret == LIBUSB20_ERROR_NO_DEVICE)
317                         continue;
318                 else if (ret < 0)
319                         goto out;
320         }
321
322         ret = 0;
323 out:
324         pthread_mutex_unlock(&ctx->open_devs_lock);
325
326 handled:
327         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "handle_events leave");
328         return ret;
329 }
330
331 /* Polling and timing */
332
333 int
334 libusb_try_lock_events(libusb_context * ctx)
335 {
336         int ret;
337
338         GET_CONTEXT(ctx);
339         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events enter");
340
341         pthread_mutex_lock(&ctx->pollfd_modify_lock);
342         ret = ctx->pollfd_modify;
343         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
344
345         if (ret != 0)
346                 return (1);
347
348         ret = pthread_mutex_trylock(&ctx->events_lock);
349         
350         if (ret != 0)
351                 return (1);
352         
353         ctx->event_handler_active = 1;
354
355         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_try_lock_events leave");
356         return (0);
357 }
358
359 void
360 libusb_lock_events(libusb_context * ctx)
361 {
362         GET_CONTEXT(ctx);
363         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events enter");
364
365         pthread_mutex_lock(&ctx->events_lock);
366         ctx->event_handler_active = 1;
367
368         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_events leave");
369 }
370
371 void
372 libusb_unlock_events(libusb_context * ctx)
373 {
374         GET_CONTEXT(ctx);
375         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events enter");
376
377         ctx->event_handler_active = 0;
378         pthread_mutex_unlock(&ctx->events_lock);
379
380         pthread_mutex_lock(&ctx->event_waiters_lock);
381         pthread_cond_broadcast(&ctx->event_waiters_cond);
382         pthread_mutex_unlock(&ctx->event_waiters_lock);
383
384         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_events leave");
385 }
386
387 int
388 libusb_event_handling_ok(libusb_context * ctx)
389 {
390         int ret;
391
392         GET_CONTEXT(ctx);
393         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok enter");
394
395         pthread_mutex_lock(&ctx->pollfd_modify_lock);
396         ret = ctx->pollfd_modify;
397         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
398
399         if (ret != 0)
400                 return (0);
401
402         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handling_ok leave");
403         return (1);
404 }
405
406 int
407 libusb_event_handler_active(libusb_context * ctx)
408 {
409         int ret;
410
411         GET_CONTEXT(ctx);
412         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active enter");
413
414         pthread_mutex_lock(&ctx->pollfd_modify_lock);
415         ret = ctx->pollfd_modify;
416         pthread_mutex_unlock(&ctx->pollfd_modify_lock);
417
418         if (ret != 0)
419                 return (1);
420
421         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_event_handler_active leave");
422         return (ctx->event_handler_active);
423 }
424
425 void
426 libusb_lock_event_waiters(libusb_context * ctx)
427 {
428         GET_CONTEXT(ctx);
429         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters enter");
430
431         pthread_mutex_lock(&ctx->event_waiters_lock);
432
433         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_lock_event_waiters leave");
434 }
435
436 void
437 libusb_unlock_event_waiters(libusb_context * ctx)
438 {
439         GET_CONTEXT(ctx);
440         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters enter");
441
442         pthread_mutex_unlock(&ctx->event_waiters_lock);
443
444         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_unlock_event_waiters leave");
445 }
446
447 int
448 libusb_wait_for_event(libusb_context * ctx, struct timeval *tv)
449 {
450         int ret;
451         struct timespec ts;
452
453         GET_CONTEXT(ctx);
454         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event enter");
455
456         if (tv == NULL) {
457                 pthread_cond_wait(&ctx->event_waiters_cond, 
458                     &ctx->event_waiters_lock);
459                 return (0);
460         }
461
462         ret = clock_gettime(CLOCK_REALTIME, &ts);
463         if (ret < 0)
464                 return (LIBUSB_ERROR_OTHER);
465
466         ts.tv_sec = tv->tv_sec;
467         ts.tv_nsec = tv->tv_usec * 1000;
468         if (ts.tv_nsec > 1000000000) {
469                 ts.tv_nsec -= 1000000000;
470                 ts.tv_sec++;
471         }
472
473         ret = pthread_cond_timedwait(&ctx->event_waiters_cond,
474             &ctx->event_waiters_lock, &ts);
475
476         if (ret == ETIMEDOUT)
477                 return (1);
478
479         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_wait_for_event leave");
480         return (0);
481 }
482
483 int
484 libusb_handle_events_timeout(libusb_context * ctx, struct timeval *tv)
485 {
486         struct timeval poll_timeout;
487         int ret;
488         
489         GET_CONTEXT(ctx);
490         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout enter");
491
492         ret = get_next_timeout(ctx, tv, &poll_timeout);
493         if (ret != 0) {
494                 return handle_timeouts(ctx);
495         }
496 retry:
497         if (libusb_try_lock_events(ctx) == 0) {
498                 ret = handle_events(ctx, &poll_timeout);
499                 libusb_unlock_events(ctx);
500                 return ret;
501         }
502
503         libusb_lock_event_waiters(ctx);
504         if (libusb_event_handler_active(ctx) == 0) {
505                 libusb_unlock_event_waiters(ctx);
506                 goto retry;
507         }
508         
509         ret = libusb_wait_for_event(ctx, &poll_timeout);
510         libusb_unlock_event_waiters(ctx);
511
512         if (ret < 0)
513                 return ret;
514         else if (ret == 1)
515                 return (handle_timeouts(ctx));
516
517         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_timeout leave");
518         return (0);
519 }
520
521 int
522 libusb_handle_events(libusb_context * ctx)
523 {
524         struct timeval tv;
525         int ret;
526
527         GET_CONTEXT(ctx);
528         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events enter");
529
530         tv.tv_sec = 2;
531         tv.tv_usec = 0;
532         ret = libusb_handle_events_timeout(ctx, &tv);
533
534         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events leave");
535         return (ret);
536 }
537
538 int
539 libusb_handle_events_locked(libusb_context * ctx, struct timeval *tv)
540 {
541         int ret;
542         struct timeval poll_tv;
543
544         GET_CONTEXT(ctx);
545         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked enter");
546
547         ret = get_next_timeout(ctx, tv, &poll_tv);
548         if (ret != 0) {
549                 return handle_timeouts(ctx);
550         }
551
552         ret = handle_events(ctx, &poll_tv);
553
554         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_handle_events_locked leave");
555         return (ret);
556 }
557
558 int
559 libusb_get_next_timeout(libusb_context * ctx, struct timeval *tv)
560 {
561         struct usb_transfer *xfer;
562         struct timeval *next_tv;
563         struct timeval cur_tv;
564         struct timespec cur_ts;
565         int found;
566         int ret;
567
568         GET_CONTEXT(ctx);
569         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout enter");
570
571         found = 0;
572         pthread_mutex_lock(&ctx->flying_transfers_lock);
573         if (TAILQ_EMPTY(&ctx->flying_transfers)) {
574                 pthread_mutex_unlock(&ctx->flying_transfers_lock);
575                 return (0);
576         }
577
578         TAILQ_FOREACH(xfer, &ctx->flying_transfers, list) {
579                 if (!(xfer->flags & USB_TIMED_OUT)) {
580                         found = 1;
581                         break ;
582                 }
583         }
584         pthread_mutex_unlock(&ctx->flying_transfers_lock);
585
586         if (found == 0) {
587                 return 0;
588         }
589
590         next_tv = &xfer->timeout;
591         if (timerisset(next_tv) == 0)
592                 return (0);
593
594         ret = clock_gettime(CLOCK_MONOTONIC, &cur_ts);
595         if (ret < 0)
596                 return (LIBUSB_ERROR_OTHER);
597         TIMESPEC_TO_TIMEVAL(&cur_tv, &cur_ts);  
598
599         if (timercmp(&cur_tv, next_tv, >=) != 0)
600                 timerclear(tv);
601         else
602                 timersub(next_tv, &cur_tv, tv);
603
604         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_next_timeout leave");
605         return (1);
606 }
607
608 void
609 libusb_set_pollfd_notifiers(libusb_context * ctx,
610     libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
611     void *user_data)
612 {
613         GET_CONTEXT(ctx);
614         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers enter");
615
616         ctx->fd_added_cb = added_cb;
617         ctx->fd_removed_cb = removed_cb;
618         ctx->fd_cb_user_data = user_data;
619
620         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_set_pollfd_notifiers leave");
621 }
622
623 struct libusb_pollfd **
624 libusb_get_pollfds(libusb_context * ctx)
625 {
626         struct usb_pollfd *pollfd;
627         libusb_pollfd **ret;
628         int i;
629
630         GET_CONTEXT(ctx);
631         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds enter");
632
633         i = 0;
634         pthread_mutex_lock(&ctx->pollfds_lock);
635         TAILQ_FOREACH(pollfd, &ctx->pollfds, list)
636                 i++;
637
638         ret = calloc(i + 1 , sizeof(struct libusb_pollfd *));
639         if (ret == NULL) {
640                 pthread_mutex_unlock(&ctx->pollfds_lock);
641                 return (ret);
642         }
643
644         i = 0;
645         TAILQ_FOREACH(pollfd, &ctx->pollfds, list)
646                 ret[i++] = (struct libusb_pollfd *) pollfd;
647         ret[i] = NULL;
648
649         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_get_pollfds leave");
650         return (ret);
651 }
652
653
654 /* Synchronous device I/O */
655
656 static void ctrl_tr_cb(struct libusb_transfer *transfer)
657 {
658         libusb_context *ctx;
659         int *complet;
660        
661         ctx = NULL;
662         GET_CONTEXT(ctx);
663         DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "CALLBACK ENTER");
664
665         complet = transfer->user_data;
666         *complet = 1;
667 }
668
669 int
670 libusb_control_transfer(libusb_device_handle * devh,
671     uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
672     unsigned char *data, uint16_t wLength, unsigned int timeout)
673 {
674         struct libusb_transfer *xfer;
675         struct libusb_control_setup *ctr;
676         libusb_context *ctx;
677         unsigned char *buff;
678         int complet;
679         int ret;
680
681         ctx = devh->dev->ctx;
682         GET_CONTEXT(ctx);
683         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer enter");
684
685         if (devh == NULL || data == NULL)
686                 return (LIBUSB_ERROR_NO_MEM);
687
688         xfer = libusb_alloc_transfer(0);
689         if (xfer == NULL)
690                 return (LIBUSB_ERROR_NO_MEM);
691
692         buff = malloc(sizeof(libusb_control_setup) + wLength);
693         if (buff == NULL) {
694                 libusb_free_transfer(xfer);
695                 return (LIBUSB_ERROR_NO_MEM);
696         }
697
698         ctr = (libusb_control_setup *)buff;
699         ctr->bmRequestType = bmRequestType;
700         ctr->bRequest = bRequest;
701         ctr->wValue = wValue;
702         ctr->wIndex = wIndex;
703         ctr->wLength = wLength;
704         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
705                 memcpy(buff + sizeof(libusb_control_setup), data, wLength);
706
707         xfer->dev_handle = devh;
708         xfer->endpoint = 0;
709         xfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
710         xfer->timeout = timeout;
711         xfer->buffer = buff;
712         xfer->length = sizeof(libusb_control_setup) + wLength;
713         xfer->user_data = &complet;
714         xfer->callback = ctrl_tr_cb;
715         xfer->flags = LIBUSB_TRANSFER_FREE_TRANSFER;
716         complet = 0;
717
718         if ((ret = libusb_submit_transfer(xfer)) < 0) {
719                 libusb_free_transfer(xfer);
720                 return (ret);
721         }
722
723         while (complet == 0)
724                 if ((ret = libusb_handle_events(ctx)) < 0) {
725                         libusb_cancel_transfer(xfer);
726                         while (complet == 0)
727                                 if (libusb_handle_events(ctx) < 0) {
728                                         break;
729                                 }
730                         libusb_free_transfer(xfer);
731                         return (ret);
732                 }
733
734
735         if ((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
736                 memcpy(data, buff + sizeof(libusb_control_setup), wLength);
737
738         switch (xfer->status) {
739         case LIBUSB_TRANSFER_COMPLETED:
740                 ret = xfer->actual_length;
741                 break;
742         case LIBUSB_TRANSFER_TIMED_OUT:
743         case LIBUSB_TRANSFER_STALL:
744         case LIBUSB_TRANSFER_NO_DEVICE:
745                 ret = xfer->status;
746                 break;
747         default:
748                 ret = LIBUSB_ERROR_OTHER;
749         }
750         libusb_free_transfer(xfer);
751
752         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_control_transfer leave");
753         return (ret);
754 }
755
756 static int
757 do_transfer(struct libusb_device_handle *devh, 
758     unsigned char endpoint, unsigned char *data, int length,
759     int *transferred, unsigned int timeout, int type)
760 {
761         struct libusb_transfer *xfer;
762         libusb_context *ctx;
763         int complet;
764         int ret;
765
766         if (devh == NULL || data == NULL)
767                 return (LIBUSB_ERROR_NO_MEM);
768
769         xfer = libusb_alloc_transfer(0);
770         if (xfer == NULL)
771                 return (LIBUSB_ERROR_NO_MEM);
772
773         ctx = devh->dev->ctx;
774         GET_CONTEXT(ctx);
775
776         xfer->dev_handle = devh;
777         xfer->endpoint = endpoint;
778         xfer->type = type;
779         xfer->timeout = timeout;
780         xfer->buffer = data;
781         xfer->length = length;
782         xfer->user_data = &complet;
783         xfer->callback = ctrl_tr_cb;
784         complet = 0;
785
786         DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "SUBMIT_TRANSFER");
787         if ((ret = libusb_submit_transfer(xfer)) < 0) {
788                 libusb_free_transfer(xfer);
789                 DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "SUBMIT_TRANSFER FAILED %i", ret);
790                 return (ret);
791         }
792
793         while (complet == 0) {
794                 if ((ret = libusb_handle_events(ctx)) < 0) {
795                         libusb_cancel_transfer(xfer);
796                         libusb_free_transfer(xfer);
797                         while (complet == 0) {
798                                 if (libusb_handle_events(ctx) < 0)
799                                         break ;
800                         }
801                         return (ret);
802                 }
803         }
804
805         *transferred = xfer->actual_length;
806         DPRINTF(ctx, LIBUSB_DEBUG_TRANSFER, "xfer->status %i", xfer->status);
807         switch (xfer->status) {
808         case LIBUSB_TRANSFER_COMPLETED:
809                 ret = xfer->actual_length;
810                 break;
811         case LIBUSB_TRANSFER_TIMED_OUT:
812         case LIBUSB_TRANSFER_OVERFLOW:
813         case LIBUSB_TRANSFER_STALL:
814         case LIBUSB_TRANSFER_NO_DEVICE:
815                 ret = xfer->status;
816                 break;
817         default:
818                 ret = LIBUSB_ERROR_OTHER;
819         }
820
821         libusb_free_transfer(xfer);
822         return (ret);
823 }
824
825 int
826 libusb_bulk_transfer(struct libusb_device_handle *devh,
827     unsigned char endpoint, unsigned char *data, int length,
828     int *transferred, unsigned int timeout)
829 {
830         libusb_context *ctx;
831         int ret;
832         
833         ctx = NULL;
834         GET_CONTEXT(ctx);
835         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer enter");
836
837         ret = do_transfer(devh, endpoint, data, length, transferred,
838             timeout, LIBUSB_TRANSFER_TYPE_BULK);
839
840         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_bulk_transfer leave");
841         return (ret);
842 }
843
844 /*
845  * Need to fix xfer->type
846  */
847 int
848 libusb_interrupt_transfer(struct libusb_device_handle *devh,
849     unsigned char endpoint, unsigned char *data, int length, 
850     int *transferred, unsigned int timeout)
851 {
852         libusb_context *ctx;
853         int ret;
854
855         ctx = NULL;
856         GET_CONTEXT(ctx);
857         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer enter");
858
859         ret = do_transfer(devh, endpoint, data, length, transferred,
860             timeout, LIBUSB_TRANSFER_TYPE_INTERRUPT);
861
862         DPRINTF(ctx, LIBUSB_DEBUG_FUNCTION, "libusb_interrupt_transfer leave");
863         return (ret);
864 }