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