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