xref: /freebsd/lib/libusb/libusb20.c (revision d59c7ea2701fe7b73b32eef49a7c712ef38de5a0)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #ifdef LIBUSB_GLOBAL_INCLUDE_FILE
29 #include LIBUSB_GLOBAL_INCLUDE_FILE
30 #else
31 #include <ctype.h>
32 #include <poll.h>
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <time.h>
38 #include <sys/queue.h>
39 #endif
40 
41 #include "libusb20.h"
42 #include "libusb20_desc.h"
43 #include "libusb20_int.h"
44 
45 static int
46 dummy_int(void)
47 {
48 	return (LIBUSB20_ERROR_NOT_SUPPORTED);
49 }
50 
51 static void
52 dummy_void(void)
53 {
54 	return;
55 }
56 
57 static void
58 dummy_callback(struct libusb20_transfer *xfer)
59 {
60 	;				/* style fix */
61 	switch (libusb20_tr_get_status(xfer)) {
62 	case LIBUSB20_TRANSFER_START:
63 		libusb20_tr_submit(xfer);
64 		break;
65 	default:
66 		/* complete or error */
67 		break;
68 	}
69 	return;
70 }
71 
72 #define	dummy_get_config_desc_full (void *)dummy_int
73 #define	dummy_get_config_index (void *)dummy_int
74 #define	dummy_set_config_index (void *)dummy_int
75 #define	dummy_set_alt_index (void *)dummy_int
76 #define	dummy_reset_device (void *)dummy_int
77 #define	dummy_check_connected (void *)dummy_int
78 #define	dummy_set_power_mode (void *)dummy_int
79 #define	dummy_get_power_mode (void *)dummy_int
80 #define	dummy_get_power_usage (void *)dummy_int
81 #define	dummy_get_stats (void *)dummy_int
82 #define	dummy_kernel_driver_active (void *)dummy_int
83 #define	dummy_detach_kernel_driver (void *)dummy_int
84 #define	dummy_attach_kernel_driver (void *)dummy_int
85 #define	dummy_do_request_sync (void *)dummy_int
86 #define	dummy_tr_open (void *)dummy_int
87 #define	dummy_tr_close (void *)dummy_int
88 #define	dummy_tr_clear_stall_sync (void *)dummy_int
89 #define	dummy_process (void *)dummy_int
90 #define	dummy_dev_info (void *)dummy_int
91 #define	dummy_dev_get_iface_driver (void *)dummy_int
92 
93 #define	dummy_tr_submit (void *)dummy_void
94 #define	dummy_tr_cancel_async (void *)dummy_void
95 
96 static const struct libusb20_device_methods libusb20_dummy_methods = {
97 	LIBUSB20_DEVICE(LIBUSB20_DECLARE, dummy)
98 };
99 
100 void
101 libusb20_tr_callback_wrapper(struct libusb20_transfer *xfer)
102 {
103 	;				/* style fix */
104 
105 repeat:
106 
107 	if (!xfer->is_pending) {
108 		xfer->status = LIBUSB20_TRANSFER_START;
109 	} else {
110 		xfer->is_pending = 0;
111 	}
112 
113 	xfer->callback(xfer);
114 
115 	if (xfer->is_restart) {
116 		xfer->is_restart = 0;
117 		goto repeat;
118 	}
119 	if (xfer->is_draining &&
120 	    (!xfer->is_pending)) {
121 		xfer->is_draining = 0;
122 		xfer->status = LIBUSB20_TRANSFER_DRAINED;
123 		xfer->callback(xfer);
124 	}
125 	return;
126 }
127 
128 int
129 libusb20_tr_close(struct libusb20_transfer *xfer)
130 {
131 	int error;
132 
133 	if (!xfer->is_opened) {
134 		return (LIBUSB20_ERROR_OTHER);
135 	}
136 	error = xfer->pdev->methods->tr_close(xfer);
137 
138 	if (xfer->pLength) {
139 		free(xfer->pLength);
140 	}
141 	if (xfer->ppBuffer) {
142 		free(xfer->ppBuffer);
143 	}
144 	/* reset variable fields in case the transfer is opened again */
145 	xfer->priv_sc0 = NULL;
146 	xfer->priv_sc1 = NULL;
147 	xfer->is_opened = 0;
148 	xfer->is_pending = 0;
149 	xfer->is_cancel = 0;
150 	xfer->is_draining = 0;
151 	xfer->is_restart = 0;
152 	xfer->status = 0;
153 	xfer->flags = 0;
154 	xfer->nFrames = 0;
155 	xfer->aFrames = 0;
156 	xfer->timeout = 0;
157 	xfer->maxFrames = 0;
158 	xfer->maxTotalLength = 0;
159 	xfer->maxPacketLen = 0;
160 	return (error);
161 }
162 
163 int
164 libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
165     uint32_t MaxFrameCount, uint8_t ep_no)
166 {
167 	return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0));
168 }
169 
170 int
171 libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
172     uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id)
173 {
174 	uint32_t size;
175 	uint8_t pre_scale;
176 	int error;
177 
178 	if (xfer->is_opened)
179 		return (LIBUSB20_ERROR_BUSY);
180 	if (MaxFrameCount & LIBUSB20_MAX_FRAME_PRE_SCALE) {
181 		MaxFrameCount &= ~LIBUSB20_MAX_FRAME_PRE_SCALE;
182 		/*
183 		 * The kernel can setup 8 times more frames when
184 		 * pre-scaling ISOCHRONOUS transfers. Make sure the
185 		 * length and pointer buffers are big enough:
186 		 */
187 		MaxFrameCount *= 8;
188 		pre_scale = 1;
189 	} else {
190 		pre_scale = 0;
191 	}
192 	if (MaxFrameCount == 0)
193 		return (LIBUSB20_ERROR_INVALID_PARAM);
194 
195 	xfer->maxFrames = MaxFrameCount;
196 
197 	size = MaxFrameCount * sizeof(xfer->pLength[0]);
198 	xfer->pLength = malloc(size);
199 	if (xfer->pLength == NULL) {
200 		return (LIBUSB20_ERROR_NO_MEM);
201 	}
202 	memset(xfer->pLength, 0, size);
203 
204 	size = MaxFrameCount * sizeof(xfer->ppBuffer[0]);
205 	xfer->ppBuffer = malloc(size);
206 	if (xfer->ppBuffer == NULL) {
207 		free(xfer->pLength);
208 		return (LIBUSB20_ERROR_NO_MEM);
209 	}
210 	memset(xfer->ppBuffer, 0, size);
211 
212 	if (pre_scale) {
213 		error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
214 		    MaxFrameCount / 8, ep_no, stream_id, 1);
215 	} else {
216 		error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
217 		    MaxFrameCount, ep_no, stream_id, 0);
218 	}
219 
220 	if (error) {
221 		free(xfer->ppBuffer);
222 		free(xfer->pLength);
223 	} else {
224 		xfer->is_opened = 1;
225 	}
226 	return (error);
227 }
228 
229 struct libusb20_transfer *
230 libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t trIndex)
231 {
232 	if (trIndex >= pdev->nTransfer) {
233 		return (NULL);
234 	}
235 	return (pdev->pTransfer + trIndex);
236 }
237 
238 uint32_t
239 libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer)
240 {
241 	return (xfer->aFrames);
242 }
243 
244 uint16_t
245 libusb20_tr_get_time_complete(struct libusb20_transfer *xfer)
246 {
247 	return (xfer->timeComplete);
248 }
249 
250 uint32_t
251 libusb20_tr_get_actual_length(struct libusb20_transfer *xfer)
252 {
253 	uint32_t x;
254 	uint32_t actlen = 0;
255 
256 	for (x = 0; x != xfer->aFrames; x++) {
257 		actlen += xfer->pLength[x];
258 	}
259 	return (actlen);
260 }
261 
262 uint32_t
263 libusb20_tr_get_max_frames(struct libusb20_transfer *xfer)
264 {
265 	return (xfer->maxFrames);
266 }
267 
268 uint32_t
269 libusb20_tr_get_max_packet_length(struct libusb20_transfer *xfer)
270 {
271 	/*
272 	 * Special Case NOTE: If the packet multiplier is non-zero for
273 	 * High Speed USB, the value returned is equal to
274 	 * "wMaxPacketSize * multiplier" !
275 	 */
276 	return (xfer->maxPacketLen);
277 }
278 
279 uint32_t
280 libusb20_tr_get_max_total_length(struct libusb20_transfer *xfer)
281 {
282 	return (xfer->maxTotalLength);
283 }
284 
285 uint8_t
286 libusb20_tr_get_status(struct libusb20_transfer *xfer)
287 {
288 	return (xfer->status);
289 }
290 
291 uint8_t
292 libusb20_tr_pending(struct libusb20_transfer *xfer)
293 {
294 	return (xfer->is_pending);
295 }
296 
297 void   *
298 libusb20_tr_get_priv_sc0(struct libusb20_transfer *xfer)
299 {
300 	return (xfer->priv_sc0);
301 }
302 
303 void   *
304 libusb20_tr_get_priv_sc1(struct libusb20_transfer *xfer)
305 {
306 	return (xfer->priv_sc1);
307 }
308 
309 void
310 libusb20_tr_stop(struct libusb20_transfer *xfer)
311 {
312 	if (!xfer->is_opened) {
313 		/* transfer is not opened */
314 		return;
315 	}
316 	if (!xfer->is_pending) {
317 		/* transfer not pending */
318 		return;
319 	}
320 	if (xfer->is_cancel) {
321 		/* already cancelling */
322 		return;
323 	}
324 	xfer->is_cancel = 1;		/* we are cancelling */
325 
326 	xfer->pdev->methods->tr_cancel_async(xfer);
327 	return;
328 }
329 
330 void
331 libusb20_tr_drain(struct libusb20_transfer *xfer)
332 {
333 	if (!xfer->is_opened) {
334 		/* transfer is not opened */
335 		return;
336 	}
337 	/* make sure that we are cancelling */
338 	libusb20_tr_stop(xfer);
339 
340 	if (xfer->is_pending) {
341 		xfer->is_draining = 1;
342 	}
343 	return;
344 }
345 
346 void
347 libusb20_tr_clear_stall_sync(struct libusb20_transfer *xfer)
348 {
349 	xfer->pdev->methods->tr_clear_stall_sync(xfer);
350 	return;
351 }
352 
353 void
354 libusb20_tr_set_buffer(struct libusb20_transfer *xfer, void *buffer, uint16_t frIndex)
355 {
356 	xfer->ppBuffer[frIndex] = buffer;
357 	return;
358 }
359 
360 void
361 libusb20_tr_set_callback(struct libusb20_transfer *xfer, libusb20_tr_callback_t *cb)
362 {
363 	xfer->callback = cb;
364 	return;
365 }
366 
367 void
368 libusb20_tr_set_flags(struct libusb20_transfer *xfer, uint8_t flags)
369 {
370 	xfer->flags = flags;
371 	return;
372 }
373 
374 uint8_t
375 libusb20_tr_get_flags(struct libusb20_transfer *xfer)
376 {
377 	return (xfer->flags);
378 }
379 
380 uint32_t
381 libusb20_tr_get_length(struct libusb20_transfer *xfer, uint16_t frIndex)
382 {
383 	return (xfer->pLength[frIndex]);
384 }
385 
386 void
387 libusb20_tr_set_length(struct libusb20_transfer *xfer, uint32_t length, uint16_t frIndex)
388 {
389 	xfer->pLength[frIndex] = length;
390 	return;
391 }
392 
393 void
394 libusb20_tr_set_priv_sc0(struct libusb20_transfer *xfer, void *sc0)
395 {
396 	xfer->priv_sc0 = sc0;
397 	return;
398 }
399 
400 void
401 libusb20_tr_set_priv_sc1(struct libusb20_transfer *xfer, void *sc1)
402 {
403 	xfer->priv_sc1 = sc1;
404 	return;
405 }
406 
407 void
408 libusb20_tr_set_timeout(struct libusb20_transfer *xfer, uint32_t timeout)
409 {
410 	xfer->timeout = timeout;
411 	return;
412 }
413 
414 void
415 libusb20_tr_set_total_frames(struct libusb20_transfer *xfer, uint32_t nFrames)
416 {
417 	if (nFrames > xfer->maxFrames) {
418 		/* should not happen */
419 		nFrames = xfer->maxFrames;
420 	}
421 	xfer->nFrames = nFrames;
422 	return;
423 }
424 
425 void
426 libusb20_tr_setup_bulk(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
427 {
428 	xfer->ppBuffer[0] = pBuf;
429 	xfer->pLength[0] = length;
430 	xfer->timeout = timeout;
431 	xfer->nFrames = 1;
432 	return;
433 }
434 
435 void
436 libusb20_tr_setup_control(struct libusb20_transfer *xfer, void *psetup, void *pBuf, uint32_t timeout)
437 {
438 	uint16_t len;
439 
440 	xfer->ppBuffer[0] = psetup;
441 	xfer->pLength[0] = 8;		/* fixed */
442 	xfer->timeout = timeout;
443 
444 	len = ((uint8_t *)psetup)[6] | (((uint8_t *)psetup)[7] << 8);
445 
446 	if (len != 0) {
447 		xfer->nFrames = 2;
448 		xfer->ppBuffer[1] = pBuf;
449 		xfer->pLength[1] = len;
450 	} else {
451 		xfer->nFrames = 1;
452 	}
453 	return;
454 }
455 
456 void
457 libusb20_tr_setup_intr(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint32_t timeout)
458 {
459 	xfer->ppBuffer[0] = pBuf;
460 	xfer->pLength[0] = length;
461 	xfer->timeout = timeout;
462 	xfer->nFrames = 1;
463 	return;
464 }
465 
466 void
467 libusb20_tr_setup_isoc(struct libusb20_transfer *xfer, void *pBuf, uint32_t length, uint16_t frIndex)
468 {
469 	if (frIndex >= xfer->maxFrames) {
470 		/* should not happen */
471 		return;
472 	}
473 	xfer->ppBuffer[frIndex] = pBuf;
474 	xfer->pLength[frIndex] = length;
475 	return;
476 }
477 
478 uint8_t
479 libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer,
480     void *pbuf, uint32_t length, uint32_t *pactlen,
481     uint32_t timeout)
482 {
483 	struct libusb20_device *pdev = xfer->pdev;
484 	uint32_t transfer_max;
485 	uint32_t transfer_act;
486 	uint8_t retval;
487 
488 	/* set some sensible default value */
489 	if (pactlen != NULL)
490 		*pactlen = 0;
491 
492 	/* check for error condition */
493 	if (libusb20_tr_pending(xfer))
494 		return (LIBUSB20_ERROR_OTHER);
495 
496 	do {
497 		/* compute maximum transfer length */
498 		transfer_max =
499 		    libusb20_tr_get_max_total_length(xfer);
500 
501 		if (transfer_max > length)
502 			transfer_max = length;
503 
504 		/* setup bulk or interrupt transfer */
505 		libusb20_tr_setup_bulk(xfer, pbuf,
506 		    transfer_max, timeout);
507 
508 		/* start the transfer */
509 		libusb20_tr_start(xfer);
510 
511 		/* wait for transfer completion */
512 		while (libusb20_dev_process(pdev) == 0) {
513 
514 			if (libusb20_tr_pending(xfer) == 0)
515 				break;
516 
517 			libusb20_dev_wait_process(pdev, -1);
518 		}
519 
520 		transfer_act = libusb20_tr_get_actual_length(xfer);
521 
522 		/* update actual length, if any */
523 		if (pactlen != NULL)
524 			pactlen[0] += transfer_act;
525 
526 		/* check transfer status */
527 		retval = libusb20_tr_get_status(xfer);
528 		if (retval)
529 			break;
530 
531 		/* check for short transfer */
532 		if (transfer_act != transfer_max)
533 			break;
534 
535 		/* update buffer pointer and length */
536 		pbuf = ((uint8_t *)pbuf) + transfer_max;
537 		length = length - transfer_max;
538 
539 	} while (length != 0);
540 
541 	return (retval);
542 }
543 
544 void
545 libusb20_tr_submit(struct libusb20_transfer *xfer)
546 {
547 	if (!xfer->is_opened) {
548 		/* transfer is not opened */
549 		return;
550 	}
551 	if (xfer->is_pending) {
552 		/* should not happen */
553 		return;
554 	}
555 	xfer->is_pending = 1;		/* we are pending */
556 	xfer->is_cancel = 0;		/* not cancelling */
557 	xfer->is_restart = 0;		/* not restarting */
558 
559 	xfer->pdev->methods->tr_submit(xfer);
560 	return;
561 }
562 
563 void
564 libusb20_tr_start(struct libusb20_transfer *xfer)
565 {
566 	if (!xfer->is_opened) {
567 		/* transfer is not opened */
568 		return;
569 	}
570 	if (xfer->is_pending) {
571 		if (xfer->is_cancel) {
572 			/* cancelling - restart */
573 			xfer->is_restart = 1;
574 		}
575 		/* transfer not pending */
576 		return;
577 	}
578 	/* get into the callback */
579 	libusb20_tr_callback_wrapper(xfer);
580 	return;
581 }
582 
583 /* USB device operations */
584 
585 int
586 libusb20_dev_close(struct libusb20_device *pdev)
587 {
588 	struct libusb20_transfer *xfer;
589 	uint16_t x;
590 	int error = 0;
591 
592 	if (!pdev->is_opened) {
593 		return (LIBUSB20_ERROR_OTHER);
594 	}
595 	for (x = 0; x != pdev->nTransfer; x++) {
596 		xfer = pdev->pTransfer + x;
597 
598 		if (!xfer->is_opened) {
599 			/* transfer is not opened */
600 			continue;
601 		}
602 
603 		libusb20_tr_drain(xfer);
604 
605 		libusb20_tr_close(xfer);
606 	}
607 
608 	if (pdev->pTransfer != NULL) {
609 		free(pdev->pTransfer);
610 		pdev->pTransfer = NULL;
611 	}
612 	error = pdev->beMethods->close_device(pdev);
613 
614 	pdev->methods = &libusb20_dummy_methods;
615 
616 	pdev->is_opened = 0;
617 
618 	/*
619 	 * Make sure libusb20_tr_get_pointer() fails:
620 	 */
621 	pdev->nTransfer = 0;
622 
623 	/*
624 	 * The following variable is only used by the libusb v0.1
625 	 * compat layer:
626 	 */
627 	pdev->claimed_interface = 0;
628 
629 	/*
630 	 * The following variable is only used by the libusb v1.0
631 	 * compat layer:
632 	 */
633 	pdev->auto_detach = 0;
634 
635 	return (error);
636 }
637 
638 int
639 libusb20_dev_detach_kernel_driver(struct libusb20_device *pdev, uint8_t ifaceIndex)
640 {
641 	int error;
642 
643 	error = pdev->methods->detach_kernel_driver(pdev, ifaceIndex);
644 	return (error);
645 }
646 
647 int
648 libusb20_dev_attach_kernel_driver(struct libusb20_device *pdev,
649     uint8_t ifaceIndex)
650 {
651 	int error;
652 
653 	error = pdev->methods->attach_kernel_driver(pdev, ifaceIndex);
654 	return (error);
655 }
656 
657 struct LIBUSB20_DEVICE_DESC_DECODED *
658 libusb20_dev_get_device_desc(struct libusb20_device *pdev)
659 {
660 	return (&(pdev->ddesc));
661 }
662 
663 int
664 libusb20_dev_get_fd(struct libusb20_device *pdev)
665 {
666 	return (pdev->file);
667 }
668 
669 int
670 libusb20_dev_kernel_driver_active(struct libusb20_device *pdev, uint8_t ifaceIndex)
671 {
672 	int error;
673 
674 	error = pdev->methods->kernel_driver_active(pdev, ifaceIndex);
675 	return (error);
676 }
677 
678 int
679 libusb20_dev_open(struct libusb20_device *pdev, uint16_t nTransferMax)
680 {
681 	struct libusb20_transfer *xfer;
682 	uint32_t size;
683 	uint16_t x;
684 	int error;
685 
686 	if (pdev->is_opened) {
687 		return (LIBUSB20_ERROR_BUSY);
688 	}
689 	if (nTransferMax >= 256) {
690 		return (LIBUSB20_ERROR_INVALID_PARAM);
691 	} else if (nTransferMax != 0) {
692 		size = sizeof(pdev->pTransfer[0]) * nTransferMax;
693 		pdev->pTransfer = malloc(size);
694 		if (pdev->pTransfer == NULL) {
695 			return (LIBUSB20_ERROR_NO_MEM);
696 		}
697 		memset(pdev->pTransfer, 0, size);
698 	}
699 	/* initialise all transfers */
700 	for (x = 0; x != nTransferMax; x++) {
701 
702 		xfer = pdev->pTransfer + x;
703 
704 		xfer->pdev = pdev;
705 		xfer->trIndex = x;
706 		xfer->callback = &dummy_callback;
707 	}
708 
709 	/* set "nTransfer" early */
710 	pdev->nTransfer = nTransferMax;
711 
712 	error = pdev->beMethods->open_device(pdev, nTransferMax);
713 
714 	if (error) {
715 		if (pdev->pTransfer != NULL) {
716 			free(pdev->pTransfer);
717 			pdev->pTransfer = NULL;
718 		}
719 		pdev->file = -1;
720 		pdev->file_ctrl = -1;
721 		pdev->nTransfer = 0;
722 	} else {
723 		pdev->is_opened = 1;
724 	}
725 	return (error);
726 }
727 
728 int
729 libusb20_dev_reset(struct libusb20_device *pdev)
730 {
731 	int error;
732 
733 	error = pdev->methods->reset_device(pdev);
734 	return (error);
735 }
736 
737 int
738 libusb20_dev_check_connected(struct libusb20_device *pdev)
739 {
740 	int error;
741 
742 	error = pdev->methods->check_connected(pdev);
743 	return (error);
744 }
745 
746 int
747 libusb20_dev_set_power_mode(struct libusb20_device *pdev, uint8_t power_mode)
748 {
749 	int error;
750 
751 	error = pdev->methods->set_power_mode(pdev, power_mode);
752 	return (error);
753 }
754 
755 uint8_t
756 libusb20_dev_get_power_mode(struct libusb20_device *pdev)
757 {
758 	int error;
759 	uint8_t power_mode;
760 
761 	error = pdev->methods->get_power_mode(pdev, &power_mode);
762 	if (error)
763 		power_mode = LIBUSB20_POWER_ON;	/* fake power mode */
764 	return (power_mode);
765 }
766 
767 int
768 libusb20_dev_get_port_path(struct libusb20_device *pdev, uint8_t *buf, uint8_t bufsize)
769 {
770 
771 	if (pdev->port_level == 0) {
772 		/*
773 		 * Fallback for backends without port path:
774 		 */
775 		if (bufsize < 2)
776 			return (LIBUSB20_ERROR_OVERFLOW);
777 		buf[0] = pdev->parent_address;
778 		buf[1] = pdev->parent_port;
779 		return (2);
780 	}
781 
782 	/* check if client buffer is too small */
783 	if (pdev->port_level > bufsize)
784 		return (LIBUSB20_ERROR_OVERFLOW);
785 
786 	/* copy port number information */
787 	memcpy(buf, pdev->port_path, pdev->port_level);
788 
789 	return (pdev->port_level);	/* success */
790 }
791 
792 uint16_t
793 libusb20_dev_get_power_usage(struct libusb20_device *pdev)
794 {
795 	int error;
796 	uint16_t power_usage;
797 
798 	error = pdev->methods->get_power_usage(pdev, &power_usage);
799 	if (error)
800 		power_usage = 0;
801 	return (power_usage);
802 }
803 
804 int
805 libusb20_dev_set_alt_index(struct libusb20_device *pdev, uint8_t ifaceIndex, uint8_t altIndex)
806 {
807 	int error;
808 
809 	error = pdev->methods->set_alt_index(pdev, ifaceIndex, altIndex);
810 	return (error);
811 }
812 
813 int
814 libusb20_dev_set_config_index(struct libusb20_device *pdev, uint8_t configIndex)
815 {
816 	int error;
817 
818 	error = pdev->methods->set_config_index(pdev, configIndex);
819 	return (error);
820 }
821 
822 int
823 libusb20_dev_request_sync(struct libusb20_device *pdev,
824     struct LIBUSB20_CONTROL_SETUP_DECODED *setup, void *data,
825     uint16_t *pactlen, uint32_t timeout, uint8_t flags)
826 {
827 	int error;
828 
829 	error = pdev->methods->do_request_sync(pdev,
830 	    setup, data, pactlen, timeout, flags);
831 	return (error);
832 }
833 
834 int
835 libusb20_dev_req_string_sync(struct libusb20_device *pdev,
836     uint8_t str_index, uint16_t langid, void *ptr, uint16_t len)
837 {
838 	struct LIBUSB20_CONTROL_SETUP_DECODED req;
839 	int error;
840 	int flags;
841 
842 	/* make sure memory is initialised */
843 	memset(ptr, 0, len);
844 
845 	if (len < 4) {
846 		/* invalid length */
847 		return (LIBUSB20_ERROR_INVALID_PARAM);
848 	}
849 	LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
850 
851 	/*
852 	 * We need to read the USB string in two steps else some USB
853 	 * devices will complain.
854 	 */
855 	req.bmRequestType =
856 	    LIBUSB20_REQUEST_TYPE_STANDARD |
857 	    LIBUSB20_RECIPIENT_DEVICE |
858 	    LIBUSB20_ENDPOINT_IN;
859 	req.bRequest = LIBUSB20_REQUEST_GET_DESCRIPTOR;
860 	req.wValue = (LIBUSB20_DT_STRING << 8) | str_index;
861 	req.wIndex = langid;
862 	req.wLength = 4;		/* bytes */
863 
864 	error = libusb20_dev_request_sync(pdev, &req,
865 	    ptr, NULL, 1000, LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK);
866 	if (error) {
867 		/* try to request full string */
868 		req.wLength = 255;
869 		flags = 0;
870 	} else {
871 		/* extract length and request full string */
872 		req.wLength = *(uint8_t *)ptr;
873 		flags = LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK;
874 	}
875 	if (req.wLength > len) {
876 		/* partial string read */
877 		req.wLength = len;
878 	}
879 	error = libusb20_dev_request_sync(pdev, &req, ptr, NULL, 1000, flags);
880 	if (error)
881 		return (error);
882 
883 	if (((uint8_t *)ptr)[1] != LIBUSB20_DT_STRING)
884 		return (LIBUSB20_ERROR_OTHER);
885 	return (0);			/* success */
886 }
887 
888 int
889 libusb20_dev_req_string_simple_sync(struct libusb20_device *pdev,
890     uint8_t str_index, void *ptr, uint16_t len)
891 {
892 	char *buf;
893 	int error;
894 	uint16_t langid;
895 	uint16_t n;
896 	uint16_t i;
897 	uint16_t c;
898 	uint8_t temp[255];
899 	uint8_t swap;
900 
901 	/* the following code derives from the FreeBSD USB kernel */
902 
903 	if ((len < 1) || (ptr == NULL)) {
904 		/* too short buffer */
905 		return (LIBUSB20_ERROR_INVALID_PARAM);
906 	}
907 	error = libusb20_dev_req_string_sync(pdev,
908 	    0, 0, temp, sizeof(temp));
909 	if (error < 0) {
910 		*(uint8_t *)ptr = 0;	/* zero terminate */
911 		return (error);
912 	}
913 	langid = temp[2] | (temp[3] << 8);
914 
915 	error = libusb20_dev_req_string_sync(pdev, str_index,
916 	    langid, temp, sizeof(temp));
917 	if (error < 0) {
918 		*(uint8_t *)ptr = 0;	/* zero terminate */
919 		return (error);
920 	}
921 	if (temp[0] < 2) {
922 		/* string length is too short */
923 		*(uint8_t *)ptr = 0;	/* zero terminate */
924 		return (LIBUSB20_ERROR_OTHER);
925 	}
926 	/* reserve one byte for terminating zero */
927 	len--;
928 
929 	/* find maximum length */
930 	n = (temp[0] / 2) - 1;
931 	if (n > len) {
932 		n = len;
933 	}
934 	/* reset swap state */
935 	swap = 3;
936 
937 	/* setup output buffer pointer */
938 	buf = ptr;
939 
940 	/* convert and filter */
941 	for (i = 0; (i != n); i++) {
942 		c = temp[(2 * i) + 2] | (temp[(2 * i) + 3] << 8);
943 
944 		/* convert from Unicode, handle buggy strings */
945 		if (((c & 0xff00) == 0) && (swap & 1)) {
946 			/* Little Endian, default */
947 			*buf = c;
948 			swap = 1;
949 		} else if (((c & 0x00ff) == 0) && (swap & 2)) {
950 			/* Big Endian */
951 			*buf = c >> 8;
952 			swap = 2;
953 		} else {
954 			/* skip invalid character */
955 			continue;
956 		}
957 		/*
958 		 * Filter by default - we don't allow greater and less than
959 		 * signs because they might confuse the dmesg printouts!
960 		 */
961 		if ((*buf == '<') || (*buf == '>') || (!isprint(*buf))) {
962 			/* skip invalid character */
963 			continue;
964 		}
965 		buf++;
966 	}
967 	*buf = 0;			/* zero terminate string */
968 
969 	return (0);
970 }
971 
972 struct libusb20_config *
973 libusb20_dev_alloc_config(struct libusb20_device *pdev, uint8_t configIndex)
974 {
975 	struct libusb20_config *retval = NULL;
976 	uint8_t *ptr;
977 	uint16_t len;
978 	uint8_t do_close;
979 	int error;
980 
981 	/*
982 	 * Catch invalid configuration descriptor reads early on to
983 	 * avoid issues with devices that don't check for a valid USB
984 	 * configuration read request.
985 	 */
986 	if (configIndex >= pdev->ddesc.bNumConfigurations)
987 		return (NULL);
988 
989 	if (!pdev->is_opened) {
990 		error = libusb20_dev_open(pdev, 0);
991 		if (error) {
992 			return (NULL);
993 		}
994 		do_close = 1;
995 	} else {
996 		do_close = 0;
997 	}
998 	error = pdev->methods->get_config_desc_full(pdev,
999 	    &ptr, &len, configIndex);
1000 
1001 	if (error) {
1002 		goto done;
1003 	}
1004 	/* parse new config descriptor */
1005 	retval = libusb20_parse_config_desc(ptr);
1006 
1007 	/* free config descriptor */
1008 	free(ptr);
1009 
1010 done:
1011 	if (do_close) {
1012 		error = libusb20_dev_close(pdev);
1013 	}
1014 	return (retval);
1015 }
1016 
1017 struct libusb20_device *
1018 libusb20_dev_alloc(void)
1019 {
1020 	struct libusb20_device *pdev;
1021 
1022 	pdev = malloc(sizeof(*pdev));
1023 	if (pdev == NULL) {
1024 		return (NULL);
1025 	}
1026 	memset(pdev, 0, sizeof(*pdev));
1027 
1028 	pdev->file = -1;
1029 	pdev->file_ctrl = -1;
1030 	pdev->methods = &libusb20_dummy_methods;
1031 	return (pdev);
1032 }
1033 
1034 uint8_t
1035 libusb20_dev_get_config_index(struct libusb20_device *pdev)
1036 {
1037 	int error;
1038 	uint8_t cfg_index;
1039 	uint8_t do_close;
1040 
1041 	if (!pdev->is_opened) {
1042 		error = libusb20_dev_open(pdev, 0);
1043 		if (error == 0) {
1044 			do_close = 1;
1045 		} else {
1046 			do_close = 0;
1047 		}
1048 	} else {
1049 		do_close = 0;
1050 	}
1051 
1052 	error = pdev->methods->get_config_index(pdev, &cfg_index);
1053 	if (error)
1054 		cfg_index = 0xFF;	/* current config index */
1055 	if (do_close) {
1056 		if (libusb20_dev_close(pdev)) {
1057 			/* ignore */
1058 		}
1059 	}
1060 	return (cfg_index);
1061 }
1062 
1063 uint8_t
1064 libusb20_dev_get_mode(struct libusb20_device *pdev)
1065 {
1066 	return (pdev->usb_mode);
1067 }
1068 
1069 uint8_t
1070 libusb20_dev_get_speed(struct libusb20_device *pdev)
1071 {
1072 	return (pdev->usb_speed);
1073 }
1074 
1075 int
1076 libusb20_dev_get_stats(struct libusb20_device *pdev, struct libusb20_device_stats *pstats)
1077 {
1078 	uint8_t do_close;
1079 	int error;
1080 
1081 	if (!pdev->is_opened) {
1082 		error = libusb20_dev_open(pdev, 0);
1083 		if (error == 0) {
1084 			do_close = 1;
1085 		} else {
1086 			do_close = 0;
1087 		}
1088 	} else {
1089 		do_close = 0;
1090 	}
1091 
1092 	error = pdev->methods->get_stats(pdev, pstats);
1093 
1094 	if (do_close)
1095 		(void) libusb20_dev_close(pdev);
1096 
1097 	return (error);
1098 }
1099 
1100 /* if this function returns an error, the device is gone */
1101 int
1102 libusb20_dev_process(struct libusb20_device *pdev)
1103 {
1104 	int error;
1105 
1106 	error = pdev->methods->process(pdev);
1107 	return (error);
1108 }
1109 
1110 void
1111 libusb20_dev_wait_process(struct libusb20_device *pdev, int timeout)
1112 {
1113 	struct pollfd pfd[1];
1114 
1115 	if (!pdev->is_opened) {
1116 		return;
1117 	}
1118 	pfd[0].fd = pdev->file;
1119 	pfd[0].events = (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM);
1120 	pfd[0].revents = 0;
1121 
1122 	if (poll(pfd, 1, timeout)) {
1123 		/* ignore any error */
1124 	}
1125 	return;
1126 }
1127 
1128 void
1129 libusb20_dev_free(struct libusb20_device *pdev)
1130 {
1131 	if (pdev == NULL) {
1132 		/* be NULL safe */
1133 		return;
1134 	}
1135 	if (pdev->is_opened) {
1136 		if (libusb20_dev_close(pdev)) {
1137 			/* ignore any errors */
1138 		}
1139 	}
1140 	free(pdev);
1141 	return;
1142 }
1143 
1144 int
1145 libusb20_dev_get_info(struct libusb20_device *pdev,
1146     struct usb_device_info *pinfo)
1147 {
1148 	if (pinfo == NULL)
1149 		return (LIBUSB20_ERROR_INVALID_PARAM);
1150 
1151 	return (pdev->beMethods->dev_get_info(pdev, pinfo));
1152 }
1153 
1154 const char *
1155 libusb20_dev_get_backend_name(struct libusb20_device *pdev)
1156 {
1157 	return (pdev->beMethods->get_backend_name());
1158 }
1159 
1160 const char *
1161 libusb20_dev_get_desc(struct libusb20_device *pdev)
1162 {
1163 	return (pdev->usb_desc);
1164 }
1165 
1166 void
1167 libusb20_dev_set_debug(struct libusb20_device *pdev, int debug)
1168 {
1169 	pdev->debug = debug;
1170 	return;
1171 }
1172 
1173 int
1174 libusb20_dev_get_debug(struct libusb20_device *pdev)
1175 {
1176 	return (pdev->debug);
1177 }
1178 
1179 uint8_t
1180 libusb20_dev_get_address(struct libusb20_device *pdev)
1181 {
1182 	return (pdev->device_address);
1183 }
1184 
1185 uint8_t
1186 libusb20_dev_get_parent_address(struct libusb20_device *pdev)
1187 {
1188 	return (pdev->parent_address);
1189 }
1190 
1191 uint8_t
1192 libusb20_dev_get_parent_port(struct libusb20_device *pdev)
1193 {
1194 	return (pdev->parent_port);
1195 }
1196 
1197 uint8_t
1198 libusb20_dev_get_bus_number(struct libusb20_device *pdev)
1199 {
1200 	return (pdev->bus_number);
1201 }
1202 
1203 int
1204 libusb20_dev_get_iface_desc(struct libusb20_device *pdev,
1205     uint8_t iface_index, char *buf, uint8_t len)
1206 {
1207 	if ((buf == NULL) || (len == 0))
1208 		return (LIBUSB20_ERROR_INVALID_PARAM);
1209 
1210 	buf[0] = 0;		/* set default string value */
1211 
1212 	return (pdev->beMethods->dev_get_iface_desc(
1213 	    pdev, iface_index, buf, len));
1214 }
1215 
1216 /* USB backend operations */
1217 
1218 int
1219 libusb20_be_get_dev_quirk(struct libusb20_backend *pbe,
1220     uint16_t quirk_index, struct libusb20_quirk *pq)
1221 {
1222 	return (pbe->methods->root_get_dev_quirk(pbe, quirk_index, pq));
1223 }
1224 
1225 int
1226 libusb20_be_get_quirk_name(struct libusb20_backend *pbe,
1227     uint16_t quirk_index, struct libusb20_quirk *pq)
1228 {
1229 	return (pbe->methods->root_get_quirk_name(pbe, quirk_index, pq));
1230 }
1231 
1232 int
1233 libusb20_be_add_dev_quirk(struct libusb20_backend *pbe,
1234     struct libusb20_quirk *pq)
1235 {
1236 	return (pbe->methods->root_add_dev_quirk(pbe, pq));
1237 }
1238 
1239 int
1240 libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe,
1241     struct libusb20_quirk *pq)
1242 {
1243 	return (pbe->methods->root_remove_dev_quirk(pbe, pq));
1244 }
1245 
1246 int
1247 libusb20_be_set_template(struct libusb20_backend *pbe, int temp)
1248 {
1249 	return (pbe->methods->root_set_template(pbe, temp));
1250 }
1251 
1252 int
1253 libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp)
1254 {
1255 	int temp;
1256 
1257 	if (ptemp == NULL)
1258 		ptemp = &temp;
1259 
1260 	return (pbe->methods->root_get_template(pbe, ptemp));
1261 }
1262 
1263 struct libusb20_device *
1264 libusb20_be_device_foreach(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1265 {
1266 	if (pbe == NULL) {
1267 		pdev = NULL;
1268 	} else if (pdev == NULL) {
1269 		pdev = TAILQ_FIRST(&(pbe->usb_devs));
1270 	} else {
1271 		pdev = TAILQ_NEXT(pdev, dev_entry);
1272 	}
1273 	return (pdev);
1274 }
1275 
1276 struct libusb20_backend *
1277 libusb20_be_alloc(const struct libusb20_backend_methods *methods,
1278     struct libusb20_be_ctx *pctx)
1279 {
1280 	struct libusb20_backend *pbe;
1281 
1282 	pbe = malloc(sizeof(*pbe));
1283 	if (pbe == NULL) {
1284 		return (NULL);
1285 	}
1286 	memset(pbe, 0, sizeof(*pbe));
1287 
1288 	if (pctx == NULL) {
1289 		/* the backend owns its own context */
1290 		pctx = libusb20_be_ctx_alloc();
1291 		if (pctx == NULL) {
1292 			free(pbe);
1293 			return (NULL);
1294 		}
1295 		pbe->be_ctx_owner = 1;
1296 	}
1297 	pbe->be_ctx = pctx;
1298 
1299 	TAILQ_INIT(&(pbe->usb_devs));
1300 
1301 	pbe->methods = methods;		/* set backend methods */
1302 
1303 	/* do the initial device scan */
1304 	if (pbe->methods->init_backend) {
1305 		pbe->methods->init_backend(pbe);
1306 	}
1307 	return (pbe);
1308 }
1309 
1310 struct libusb20_backend *
1311 libusb20_be_alloc_linux(struct libusb20_be_ctx *pctx)
1312 {
1313 	return (NULL);
1314 }
1315 
1316 struct libusb20_backend *
1317 libusb20_be_alloc_ugen20(struct libusb20_be_ctx *pctx)
1318 {
1319 	return (libusb20_be_alloc(&libusb20_ugen20_backend, pctx));
1320 }
1321 
1322 struct libusb20_backend *
1323 libusb20_be_alloc_default(struct libusb20_be_ctx *pctx)
1324 {
1325 	struct libusb20_backend *pbe;
1326 
1327 #ifdef __linux__
1328 	pbe = libusb20_be_alloc_linux(pctx);
1329 	if (pbe) {
1330 		return (pbe);
1331 	}
1332 #endif
1333 	pbe = libusb20_be_alloc_ugen20(pctx);
1334 	if (pbe) {
1335 		return (pbe);
1336 	}
1337 	return (NULL);			/* no backend found */
1338 }
1339 
1340 void
1341 libusb20_be_free(struct libusb20_backend *pbe)
1342 {
1343 	struct libusb20_device *pdev;
1344 
1345 	if (pbe == NULL) {
1346 		/* be NULL safe */
1347 		return;
1348 	}
1349 	while ((pdev = libusb20_be_device_foreach(pbe, NULL))) {
1350 		libusb20_be_dequeue_device(pbe, pdev);
1351 		libusb20_dev_free(pdev);
1352 	}
1353 	if (pbe->methods->exit_backend) {
1354 		pbe->methods->exit_backend(pbe);
1355 	}
1356 	if (pbe->be_ctx_owner)
1357 		libusb20_be_ctx_free(pbe->be_ctx);
1358 	/* free backend */
1359 	free(pbe);
1360 }
1361 
1362 void
1363 libusb20_be_enqueue_device(struct libusb20_backend *pbe, struct libusb20_device *pdev)
1364 {
1365 	pdev->beMethods = pbe->methods;	/* copy backend methods */
1366 	TAILQ_INSERT_TAIL(&(pbe->usb_devs), pdev, dev_entry);
1367 }
1368 
1369 void
1370 libusb20_be_dequeue_device(struct libusb20_backend *pbe,
1371     struct libusb20_device *pdev)
1372 {
1373 	TAILQ_REMOVE(&(pbe->usb_devs), pdev, dev_entry);
1374 }
1375 
1376 const char *
1377 libusb20_strerror(int code)
1378 {
1379 	switch (code) {
1380 	case LIBUSB20_SUCCESS:
1381 		return ("Success");
1382 	case LIBUSB20_ERROR_IO:
1383 		return ("I/O error");
1384 	case LIBUSB20_ERROR_INVALID_PARAM:
1385 		return ("Invalid parameter");
1386 	case LIBUSB20_ERROR_ACCESS:
1387 		return ("Permissions error");
1388 	case LIBUSB20_ERROR_NO_DEVICE:
1389 		return ("No device");
1390 	case LIBUSB20_ERROR_NOT_FOUND:
1391 		return ("Not found");
1392 	case LIBUSB20_ERROR_BUSY:
1393 		return ("Device busy");
1394 	case LIBUSB20_ERROR_TIMEOUT:
1395 		return ("Timeout");
1396 	case LIBUSB20_ERROR_OVERFLOW:
1397 		return ("Overflow");
1398 	case LIBUSB20_ERROR_PIPE:
1399 		return ("Pipe error");
1400 	case LIBUSB20_ERROR_INTERRUPTED:
1401 		return ("Interrupted");
1402 	case LIBUSB20_ERROR_NO_MEM:
1403 		return ("Out of memory");
1404 	case LIBUSB20_ERROR_NOT_SUPPORTED:
1405 		return ("Not supported");
1406 	case LIBUSB20_ERROR_OTHER:
1407 		return ("Other error");
1408 	default:
1409 		return ("Unknown error");
1410 	}
1411 }
1412 
1413 const char *
1414 libusb20_error_name(int code)
1415 {
1416 	switch (code) {
1417 	case LIBUSB20_SUCCESS:
1418 		return ("LIBUSB20_SUCCESS");
1419 	case LIBUSB20_ERROR_IO:
1420 		return ("LIBUSB20_ERROR_IO");
1421 	case LIBUSB20_ERROR_INVALID_PARAM:
1422 		return ("LIBUSB20_ERROR_INVALID_PARAM");
1423 	case LIBUSB20_ERROR_ACCESS:
1424 		return ("LIBUSB20_ERROR_ACCESS");
1425 	case LIBUSB20_ERROR_NO_DEVICE:
1426 		return ("LIBUSB20_ERROR_NO_DEVICE");
1427 	case LIBUSB20_ERROR_NOT_FOUND:
1428 		return ("LIBUSB20_ERROR_NOT_FOUND");
1429 	case LIBUSB20_ERROR_BUSY:
1430 		return ("LIBUSB20_ERROR_BUSY");
1431 	case LIBUSB20_ERROR_TIMEOUT:
1432 		return ("LIBUSB20_ERROR_TIMEOUT");
1433 	case LIBUSB20_ERROR_OVERFLOW:
1434 		return ("LIBUSB20_ERROR_OVERFLOW");
1435 	case LIBUSB20_ERROR_PIPE:
1436 		return ("LIBUSB20_ERROR_PIPE");
1437 	case LIBUSB20_ERROR_INTERRUPTED:
1438 		return ("LIBUSB20_ERROR_INTERRUPTED");
1439 	case LIBUSB20_ERROR_NO_MEM:
1440 		return ("LIBUSB20_ERROR_NO_MEM");
1441 	case LIBUSB20_ERROR_NOT_SUPPORTED:
1442 		return ("LIBUSB20_ERROR_NOT_SUPPORTED");
1443 	case LIBUSB20_ERROR_OTHER:
1444 		return ("LIBUSB20_ERROR_OTHER");
1445 	default:
1446 		return ("LIBUSB20_ERROR_UNKNOWN");
1447 	}
1448 }
1449