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