libusb01.c revision 224085
1/* $FreeBSD: head/lib/libusb/libusb01.c 224085 2011-07-16 08:29:12Z hselasky $ */
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/*
28 * This file contains the emulation layer for LibUSB v0.1 from sourceforge.
29 */
30
31#include <sys/queue.h>
32
33#include <errno.h>
34#include <stdio.h>
35#include <stdlib.h>
36
37#include "libusb20.h"
38#include "libusb20_desc.h"
39#include "libusb20_int.h"
40#include "usb.h"
41
42/*
43 * The two following macros were taken from the original LibUSB v0.1
44 * for sake of compatibility:
45 */
46#define	LIST_ADD(begin, ent)	   \
47  do {				   \
48    if (begin) {		   \
49      ent->next = begin;	   \
50      ent->next->prev = ent;	   \
51    } else {			   \
52      ent->next = NULL;		   \
53    }				   \
54    ent->prev = NULL;		   \
55    begin = ent;		   \
56  } while(0)
57
58#define	LIST_DEL(begin, ent)		 \
59  do {					 \
60    if (ent->prev) {			 \
61      ent->prev->next = ent->next;	 \
62    } else {				 \
63      begin = ent->next;		 \
64    }					 \
65    if (ent->next) {			 \
66      ent->next->prev = ent->prev;	 \
67    }					 \
68    ent->prev = NULL;			 \
69    ent->next = NULL;			 \
70  } while (0)
71
72struct usb_bus *usb_busses = NULL;
73
74static struct usb_bus usb_global_bus = {
75	.dirname = {"/dev/usb"},
76	.root_dev = NULL,
77	.devices = NULL,
78};
79
80static struct libusb20_backend *usb_backend = NULL;
81
82struct usb_parse_state {
83
84	struct {
85		struct libusb20_endpoint *currep;
86		struct libusb20_interface *currifc;
87		struct libusb20_config *currcfg;
88		struct libusb20_me_struct *currextra;
89	}	a;
90
91	struct {
92		struct usb_config_descriptor *currcfg;
93		struct usb_interface_descriptor *currifc;
94		struct usb_endpoint_descriptor *currep;
95		struct usb_interface *currifcw;
96		uint8_t *currextra;
97	}	b;
98
99	uint8_t	preparse;
100};
101
102static struct libusb20_transfer *
103usb_get_transfer_by_ep_no(usb_dev_handle * dev, uint8_t ep_no)
104{
105	struct libusb20_device *pdev = (void *)dev;
106	struct libusb20_transfer *xfer;
107	int err;
108	uint32_t bufsize;
109	uint8_t x;
110	uint8_t speed;
111
112	x = (ep_no & LIBUSB20_ENDPOINT_ADDRESS_MASK) * 2;
113
114	if (ep_no & LIBUSB20_ENDPOINT_DIR_MASK) {
115		/* this is an IN endpoint */
116		x |= 1;
117	}
118	speed = libusb20_dev_get_speed(pdev);
119
120	/* select a sensible buffer size */
121	if (speed == LIBUSB20_SPEED_LOW) {
122		bufsize = 256;
123	} else if (speed == LIBUSB20_SPEED_FULL) {
124		bufsize = 4096;
125	} else {
126		bufsize = 16384;
127	}
128
129	xfer = libusb20_tr_get_pointer(pdev, x);
130
131	if (xfer == NULL)
132		return (xfer);
133
134	err = libusb20_tr_open(xfer, bufsize, 1, ep_no);
135	if (err == LIBUSB20_ERROR_BUSY) {
136		/* already opened */
137		return (xfer);
138	} else if (err) {
139		return (NULL);
140	}
141	/* success */
142	return (xfer);
143}
144
145usb_dev_handle *
146usb_open(struct usb_device *dev)
147{
148	int err;
149
150	err = libusb20_dev_open(dev->dev, 16 * 2);
151	if (err == LIBUSB20_ERROR_BUSY) {
152		/*
153		 * Workaround buggy USB applications which open the USB
154		 * device multiple times:
155		 */
156		return (dev->dev);
157	}
158	if (err)
159		return (NULL);
160
161	/*
162	 * Dequeue USB device from backend queue so that it does not get
163	 * freed when the backend is re-scanned:
164	 */
165	libusb20_be_dequeue_device(usb_backend, dev->dev);
166
167	return (dev->dev);
168}
169
170int
171usb_close(usb_dev_handle * udev)
172{
173	struct usb_device *dev;
174	int err;
175
176	err = libusb20_dev_close((void *)udev);
177
178	if (err)
179		return (-1);
180
181	if (usb_backend != NULL) {
182		/*
183		 * Enqueue USB device to backend queue so that it gets freed
184		 * when the backend is re-scanned:
185		 */
186		libusb20_be_enqueue_device(usb_backend, (void *)udev);
187	} else {
188		/*
189		 * The backend is gone. Free device data so that we
190		 * don't start leaking memory!
191		 */
192		dev = usb_device(udev);
193		libusb20_dev_free((void *)udev);
194		LIST_DEL(usb_global_bus.devices, dev);
195		free(dev);
196	}
197	return (0);
198}
199
200int
201usb_get_string(usb_dev_handle * dev, int strindex,
202    int langid, char *buf, size_t buflen)
203{
204	int err;
205
206	if (dev == NULL)
207		return (-1);
208
209	if (buflen > 65535)
210		buflen = 65535;
211
212	err = libusb20_dev_req_string_sync((void *)dev,
213	    strindex, langid, buf, buflen);
214
215	if (err)
216		return (-1);
217
218	return (0);
219}
220
221int
222usb_get_string_simple(usb_dev_handle * dev, int strindex,
223    char *buf, size_t buflen)
224{
225	int err;
226
227	if (dev == NULL)
228		return (-1);
229
230	if (buflen > 65535)
231		buflen = 65535;
232
233	err = libusb20_dev_req_string_simple_sync((void *)dev,
234	    strindex, buf, buflen);
235
236	if (err)
237		return (-1);
238
239	return (strlen(buf));
240}
241
242int
243usb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type,
244    uint8_t ep_index, void *buf, int size)
245{
246	memset(buf, 0, size);
247
248	if (udev == NULL)
249		return (-1);
250
251	if (size > 65535)
252		size = 65535;
253
254	return (usb_control_msg(udev, ep | USB_ENDPOINT_IN,
255	    USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0,
256	    buf, size, 1000));
257}
258
259int
260usb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index,
261    void *buf, int size)
262{
263	memset(buf, 0, size);
264
265	if (udev == NULL)
266		return (-1);
267
268	if (size > 65535)
269		size = 65535;
270
271	return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
272	    (type << 8) + desc_index, 0, buf, size, 1000));
273}
274
275int
276usb_parse_descriptor(uint8_t *source, char *description, void *dest)
277{
278	uint8_t *sp = source;
279	uint8_t *dp = dest;
280	uint16_t w;
281	uint32_t d;
282	char *cp;
283
284	for (cp = description; *cp; cp++) {
285		switch (*cp) {
286		case 'b':		/* 8-bit byte */
287			*dp++ = *sp++;
288			break;
289			/*
290			 * 16-bit word, convert from little endian to CPU
291			 */
292		case 'w':
293			w = (sp[1] << 8) | sp[0];
294			sp += 2;
295			/* Align to word boundary */
296			dp += ((dp - (uint8_t *)0) & 1);
297			*((uint16_t *)dp) = w;
298			dp += 2;
299			break;
300			/*
301			 * 32-bit dword, convert from little endian to CPU
302			 */
303		case 'd':
304			d = (sp[3] << 24) | (sp[2] << 16) |
305			    (sp[1] << 8) | sp[0];
306			sp += 4;
307			/* Align to word boundary */
308			dp += ((dp - (uint8_t *)0) & 1);
309			/* Align to double word boundary */
310			dp += ((dp - (uint8_t *)0) & 2);
311			*((uint32_t *)dp) = d;
312			dp += 4;
313			break;
314		}
315	}
316	return (sp - source);
317}
318
319static void
320usb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen)
321{
322	void *ptr;
323	uint16_t len;
324
325	ptr = ps->a.currextra->ptr;
326	len = ps->a.currextra->len;
327
328	if (ps->preparse == 0) {
329		memcpy(ps->b.currextra, ptr, len);
330		*pptr = ps->b.currextra;
331		*plen = len;
332	}
333	ps->b.currextra += len;
334	return;
335}
336
337static void
338usb_parse_endpoint(struct usb_parse_state *ps)
339{
340	struct usb_endpoint_descriptor *bep;
341	struct libusb20_endpoint *aep;
342
343	aep = ps->a.currep;
344	bep = ps->b.currep++;
345
346	if (ps->preparse == 0) {
347		/* copy descriptor fields */
348		bep->bLength = aep->desc.bLength;
349		bep->bDescriptorType = aep->desc.bDescriptorType;
350		bep->bEndpointAddress = aep->desc.bEndpointAddress;
351		bep->bmAttributes = aep->desc.bmAttributes;
352		bep->wMaxPacketSize = aep->desc.wMaxPacketSize;
353		bep->bInterval = aep->desc.bInterval;
354		bep->bRefresh = aep->desc.bRefresh;
355		bep->bSynchAddress = aep->desc.bSynchAddress;
356	}
357	ps->a.currextra = &aep->extra;
358	usb_parse_extra(ps, &bep->extra, &bep->extralen);
359	return;
360}
361
362static void
363usb_parse_iface_sub(struct usb_parse_state *ps)
364{
365	struct libusb20_interface *aifc;
366	struct usb_interface_descriptor *bifc;
367	uint8_t x;
368
369	aifc = ps->a.currifc;
370	bifc = ps->b.currifc++;
371
372	if (ps->preparse == 0) {
373		/* copy descriptor fields */
374		bifc->bLength = aifc->desc.bLength;
375		bifc->bDescriptorType = aifc->desc.bDescriptorType;
376		bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber;
377		bifc->bAlternateSetting = aifc->desc.bAlternateSetting;
378		bifc->bNumEndpoints = aifc->num_endpoints;
379		bifc->bInterfaceClass = aifc->desc.bInterfaceClass;
380		bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass;
381		bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol;
382		bifc->iInterface = aifc->desc.iInterface;
383		bifc->endpoint = ps->b.currep;
384	}
385	for (x = 0; x != aifc->num_endpoints; x++) {
386		ps->a.currep = aifc->endpoints + x;
387		usb_parse_endpoint(ps);
388	}
389
390	ps->a.currextra = &aifc->extra;
391	usb_parse_extra(ps, &bifc->extra, &bifc->extralen);
392	return;
393}
394
395static void
396usb_parse_iface(struct usb_parse_state *ps)
397{
398	struct libusb20_interface *aifc;
399	struct usb_interface *bifc;
400	uint8_t x;
401
402	aifc = ps->a.currifc;
403	bifc = ps->b.currifcw++;
404
405	if (ps->preparse == 0) {
406		/* initialise interface wrapper */
407		bifc->altsetting = ps->b.currifc;
408		bifc->num_altsetting = aifc->num_altsetting + 1;
409	}
410	usb_parse_iface_sub(ps);
411
412	for (x = 0; x != aifc->num_altsetting; x++) {
413		ps->a.currifc = aifc->altsetting + x;
414		usb_parse_iface_sub(ps);
415	}
416	return;
417}
418
419static void
420usb_parse_config(struct usb_parse_state *ps)
421{
422	struct libusb20_config *acfg;
423	struct usb_config_descriptor *bcfg;
424	uint8_t x;
425
426	acfg = ps->a.currcfg;
427	bcfg = ps->b.currcfg;
428
429	if (ps->preparse == 0) {
430		/* initialise config wrapper */
431		bcfg->bLength = acfg->desc.bLength;
432		bcfg->bDescriptorType = acfg->desc.bDescriptorType;
433		bcfg->wTotalLength = acfg->desc.wTotalLength;
434		bcfg->bNumInterfaces = acfg->num_interface;
435		bcfg->bConfigurationValue = acfg->desc.bConfigurationValue;
436		bcfg->iConfiguration = acfg->desc.iConfiguration;
437		bcfg->bmAttributes = acfg->desc.bmAttributes;
438		bcfg->MaxPower = acfg->desc.bMaxPower;
439		bcfg->interface = ps->b.currifcw;
440	}
441	for (x = 0; x != acfg->num_interface; x++) {
442		ps->a.currifc = acfg->interface + x;
443		usb_parse_iface(ps);
444	}
445
446	ps->a.currextra = &acfg->extra;
447	usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen);
448	return;
449}
450
451int
452usb_parse_configuration(struct usb_config_descriptor *config,
453    uint8_t *buffer)
454{
455	struct usb_parse_state ps;
456	uint8_t *ptr;
457	uint32_t a;
458	uint32_t b;
459	uint32_t c;
460	uint32_t d;
461
462	if ((buffer == NULL) || (config == NULL)) {
463		return (-1);
464	}
465	memset(&ps, 0, sizeof(ps));
466
467	ps.a.currcfg = libusb20_parse_config_desc(buffer);
468	ps.b.currcfg = config;
469	if (ps.a.currcfg == NULL) {
470		/* could not parse config or out of memory */
471		return (-1);
472	}
473	/* do the pre-parse */
474	ps.preparse = 1;
475	usb_parse_config(&ps);
476
477	a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0));
478	b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0));
479	c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0));
480	d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0));
481
482	/* allocate memory for our configuration */
483	ptr = malloc(a + b + c + d);
484	if (ptr == NULL) {
485		/* free config structure */
486		free(ps.a.currcfg);
487		return (-1);
488	}
489
490	/* "currifcw" must be first, hence this pointer is freed */
491	ps.b.currifcw = (void *)(ptr);
492	ps.b.currifc = (void *)(ptr + a);
493	ps.b.currep = (void *)(ptr + a + b);
494	ps.b.currextra = (void *)(ptr + a + b + c);
495
496	/* generate a libusb v0.1 compatible structure */
497	ps.preparse = 0;
498	usb_parse_config(&ps);
499
500	/* free config structure */
501	free(ps.a.currcfg);
502
503	return (0);			/* success */
504}
505
506void
507usb_destroy_configuration(struct usb_device *dev)
508{
509	uint8_t c;
510
511	if (dev->config == NULL) {
512		return;
513	}
514	for (c = 0; c != dev->descriptor.bNumConfigurations; c++) {
515		struct usb_config_descriptor *cf = &dev->config[c];
516
517		if (cf->interface != NULL) {
518			free(cf->interface);
519			cf->interface = NULL;
520		}
521	}
522
523	free(dev->config);
524	dev->config = NULL;
525	return;
526}
527
528void
529usb_fetch_and_parse_descriptors(usb_dev_handle * udev)
530{
531	struct usb_device *dev;
532	struct libusb20_device *pdev;
533	uint8_t *ptr;
534	int error;
535	uint32_t size;
536	uint16_t len;
537	uint8_t x;
538
539	if (udev == NULL) {
540		/* be NULL safe */
541		return;
542	}
543	dev = usb_device(udev);
544	pdev = (void *)udev;
545
546	if (dev->descriptor.bNumConfigurations == 0) {
547		/* invalid device */
548		return;
549	}
550	size = dev->descriptor.bNumConfigurations *
551	    sizeof(struct usb_config_descriptor);
552
553	dev->config = malloc(size);
554	if (dev->config == NULL) {
555		/* out of memory */
556		return;
557	}
558	memset(dev->config, 0, size);
559
560	for (x = 0; x != dev->descriptor.bNumConfigurations; x++) {
561
562		error = (pdev->methods->get_config_desc_full) (
563		    pdev, &ptr, &len, x);
564
565		if (error) {
566			usb_destroy_configuration(dev);
567			return;
568		}
569		usb_parse_configuration(dev->config + x, ptr);
570
571		/* free config buffer */
572		free(ptr);
573	}
574	return;
575}
576
577static int
578usb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size,
579    int timeout, int is_intr)
580{
581	struct libusb20_transfer *xfer;
582	uint32_t temp;
583	uint32_t maxsize;
584	uint32_t actlen;
585	char *oldbytes;
586
587	xfer = usb_get_transfer_by_ep_no(dev, ep);
588	if (xfer == NULL)
589		return (-1);
590
591	if (libusb20_tr_pending(xfer)) {
592		/* there is already a transfer ongoing */
593		return (-1);
594	}
595	maxsize = libusb20_tr_get_max_total_length(xfer);
596	oldbytes = bytes;
597
598	/*
599	 * We allow transferring zero bytes which is the same
600	 * equivalent to a zero length USB packet.
601	 */
602	do {
603
604		temp = size;
605		if (temp > maxsize) {
606			/* find maximum possible length */
607			temp = maxsize;
608		}
609		if (is_intr)
610			libusb20_tr_setup_intr(xfer, bytes, temp, timeout);
611		else
612			libusb20_tr_setup_bulk(xfer, bytes, temp, timeout);
613
614		libusb20_tr_start(xfer);
615
616		while (1) {
617
618			if (libusb20_dev_process((void *)dev) != 0) {
619				/* device detached */
620				return (-1);
621			}
622			if (libusb20_tr_pending(xfer) == 0) {
623				/* transfer complete */
624				break;
625			}
626			/* wait for USB event from kernel */
627			libusb20_dev_wait_process((void *)dev, -1);
628		}
629
630		switch (libusb20_tr_get_status(xfer)) {
631		case 0:
632			/* success */
633			break;
634		case LIBUSB20_TRANSFER_TIMED_OUT:
635			/* transfer timeout */
636			return (-ETIMEDOUT);
637		default:
638			/* other transfer error */
639			return (-ENXIO);
640		}
641		actlen = libusb20_tr_get_actual_length(xfer);
642
643		bytes += actlen;
644		size -= actlen;
645
646		if (actlen != temp) {
647			/* short transfer */
648			break;
649		}
650	} while (size > 0);
651
652	return (bytes - oldbytes);
653}
654
655int
656usb_bulk_write(usb_dev_handle * dev, int ep, char *bytes,
657    int size, int timeout)
658{
659	return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK,
660	    bytes, size, timeout, 0));
661}
662
663int
664usb_bulk_read(usb_dev_handle * dev, int ep, char *bytes,
665    int size, int timeout)
666{
667	return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK,
668	    bytes, size, timeout, 0));
669}
670
671int
672usb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes,
673    int size, int timeout)
674{
675	return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK,
676	    bytes, size, timeout, 1));
677}
678
679int
680usb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes,
681    int size, int timeout)
682{
683	return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK,
684	    bytes, size, timeout, 1));
685}
686
687int
688usb_control_msg(usb_dev_handle * dev, int requesttype, int request,
689    int value, int wIndex, char *bytes, int size, int timeout)
690{
691	struct LIBUSB20_CONTROL_SETUP_DECODED req;
692	int err;
693	uint16_t actlen;
694
695	LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
696
697	req.bmRequestType = requesttype;
698	req.bRequest = request;
699	req.wValue = value;
700	req.wIndex = wIndex;
701	req.wLength = size;
702
703	err = libusb20_dev_request_sync((void *)dev, &req, bytes,
704	    &actlen, timeout, 0);
705
706	if (err)
707		return (-1);
708
709	return (actlen);
710}
711
712int
713usb_set_configuration(usb_dev_handle * udev, int bConfigurationValue)
714{
715	struct usb_device *dev;
716	int err;
717	uint8_t i;
718
719	/*
720	 * Need to translate from "bConfigurationValue" to
721	 * configuration index:
722	 */
723
724	if (bConfigurationValue == 0) {
725		/* unconfigure */
726		i = 255;
727	} else {
728		/* lookup configuration index */
729		dev = usb_device(udev);
730
731		/* check if the configuration array is not there */
732		if (dev->config == NULL) {
733			return (-1);
734		}
735		for (i = 0;; i++) {
736			if (i == dev->descriptor.bNumConfigurations) {
737				/* "bConfigurationValue" not found */
738				return (-1);
739			}
740			if ((dev->config + i)->bConfigurationValue ==
741			    bConfigurationValue) {
742				break;
743			}
744		}
745	}
746
747	err = libusb20_dev_set_config_index((void *)udev, i);
748
749	if (err)
750		return (-1);
751
752	return (0);
753}
754
755int
756usb_claim_interface(usb_dev_handle * dev, int interface)
757{
758	struct libusb20_device *pdev = (void *)dev;
759
760	pdev->claimed_interface = interface;
761
762	return (0);
763}
764
765int
766usb_release_interface(usb_dev_handle * dev, int interface)
767{
768	/* do nothing */
769	return (0);
770}
771
772int
773usb_set_altinterface(usb_dev_handle * dev, int alternate)
774{
775	struct libusb20_device *pdev = (void *)dev;
776	int err;
777	uint8_t iface;
778
779	iface = pdev->claimed_interface;
780
781	err = libusb20_dev_set_alt_index((void *)dev, iface, alternate);
782
783	if (err)
784		return (-1);
785
786	return (0);
787}
788
789int
790usb_resetep(usb_dev_handle * dev, unsigned int ep)
791{
792	/* emulate an endpoint reset through clear-STALL */
793	return (usb_clear_halt(dev, ep));
794}
795
796int
797usb_clear_halt(usb_dev_handle * dev, unsigned int ep)
798{
799	struct libusb20_transfer *xfer;
800
801	xfer = usb_get_transfer_by_ep_no(dev, ep);
802	if (xfer == NULL)
803		return (-1);
804
805	libusb20_tr_clear_stall_sync(xfer);
806
807	return (0);
808}
809
810int
811usb_reset(usb_dev_handle * dev)
812{
813	int err;
814
815	err = libusb20_dev_reset((void *)dev);
816
817	if (err)
818		return (-1);
819
820	/*
821	 * Be compatible with LibUSB from sourceforge and close the
822	 * handle after reset!
823	 */
824	return (usb_close(dev));
825}
826
827int
828usb_check_connected(usb_dev_handle * dev)
829{
830	int err;
831
832	err = libusb20_dev_check_connected((void *)dev);
833
834	if (err)
835		return (-1);
836
837	return (0);
838}
839
840const char *
841usb_strerror(void)
842{
843	/* TODO */
844	return ("Unknown error");
845}
846
847void
848usb_init(void)
849{
850	/* nothing to do */
851	return;
852}
853
854void
855usb_set_debug(int level)
856{
857	/* use kernel UGEN debugging if you need to see what is going on */
858	return;
859}
860
861int
862usb_find_busses(void)
863{
864	usb_busses = &usb_global_bus;
865	return (1);
866}
867
868int
869usb_find_devices(void)
870{
871	struct libusb20_device *pdev;
872	struct usb_device *udev;
873	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
874	int devnum;
875	int err;
876
877	/* cleanup after last device search */
878	/* close all opened devices, if any */
879
880	while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) {
881		udev = pdev->privLuData;
882		libusb20_be_dequeue_device(usb_backend, pdev);
883		libusb20_dev_free(pdev);
884		if (udev != NULL) {
885			LIST_DEL(usb_global_bus.devices, udev);
886			free(udev);
887		}
888	}
889
890	/* free old USB backend, if any */
891
892	libusb20_be_free(usb_backend);
893
894	/* do a new backend device search */
895	usb_backend = libusb20_be_alloc_default();
896	if (usb_backend == NULL) {
897		return (-1);
898	}
899	/* iterate all devices */
900
901	devnum = 1;
902	pdev = NULL;
903	while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) {
904		udev = malloc(sizeof(*udev));
905		if (udev == NULL)
906			break;
907
908		memset(udev, 0, sizeof(*udev));
909
910		udev->bus = &usb_global_bus;
911
912		snprintf(udev->filename, sizeof(udev->filename),
913		    "/dev/ugen%u.%u",
914		    libusb20_dev_get_bus_number(pdev),
915		    libusb20_dev_get_address(pdev));
916
917		ddesc = libusb20_dev_get_device_desc(pdev);
918
919		udev->descriptor.bLength = sizeof(udev->descriptor);
920		udev->descriptor.bDescriptorType = ddesc->bDescriptorType;
921		udev->descriptor.bcdUSB = ddesc->bcdUSB;
922		udev->descriptor.bDeviceClass = ddesc->bDeviceClass;
923		udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass;
924		udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol;
925		udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0;
926		udev->descriptor.idVendor = ddesc->idVendor;
927		udev->descriptor.idProduct = ddesc->idProduct;
928		udev->descriptor.bcdDevice = ddesc->bcdDevice;
929		udev->descriptor.iManufacturer = ddesc->iManufacturer;
930		udev->descriptor.iProduct = ddesc->iProduct;
931		udev->descriptor.iSerialNumber = ddesc->iSerialNumber;
932		udev->descriptor.bNumConfigurations =
933		    ddesc->bNumConfigurations;
934		if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
935			/* truncate number of configurations */
936			udev->descriptor.bNumConfigurations = USB_MAXCONFIG;
937		}
938		udev->devnum = devnum++;
939		/* link together the two structures */
940		udev->dev = pdev;
941		pdev->privLuData = udev;
942
943		err = libusb20_dev_open(pdev, 0);
944		if (err == 0) {
945			/* XXX get all config descriptors by default */
946			usb_fetch_and_parse_descriptors((void *)pdev);
947			libusb20_dev_close(pdev);
948		}
949		LIST_ADD(usb_global_bus.devices, udev);
950	}
951
952	return (devnum - 1);			/* success */
953}
954
955struct usb_device *
956usb_device(usb_dev_handle * dev)
957{
958	struct libusb20_device *pdev;
959
960	pdev = (void *)dev;
961
962	return (pdev->privLuData);
963}
964
965struct usb_bus *
966usb_get_busses(void)
967{
968	return (usb_busses);
969}
970
971int
972usb_get_driver_np(usb_dev_handle * dev, int interface, char *name, int namelen)
973{
974	struct libusb20_device *pdev;
975	char *ptr;
976	int err;
977
978	pdev = (void *)dev;
979
980	if (pdev == NULL)
981		return (-1);
982	if (namelen < 1)
983		return (-1);
984	if (namelen > 255)
985		namelen = 255;
986
987	err = libusb20_dev_get_iface_desc(pdev, interface, name, namelen);
988	if (err != 0)
989		return (-1);
990
991	/* we only want the driver name */
992	ptr = strstr(name, ":");
993	if (ptr != NULL)
994		*ptr = 0;
995
996	return (0);
997}
998
999int
1000usb_detach_kernel_driver_np(usb_dev_handle * dev, int interface)
1001{
1002	struct libusb20_device *pdev;
1003	int err;
1004
1005	pdev = (void *)dev;
1006
1007	if (pdev == NULL)
1008		return (-1);
1009
1010	err = libusb20_dev_detach_kernel_driver(pdev, interface);
1011	if (err != 0)
1012		return (-1);
1013
1014	return (0);
1015}
1016