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