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