xref: /freebsd/lib/libusb/libusb10_io.c (revision eb6219e337483cb80eccb6f2b4ad649bc1d751ec)
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 }
749