libusb01.c revision 208021
1/* $FreeBSD: head/lib/libusb/libusb20_compat01.c 208021 2010-05-13 00:26:30Z thompsa $ */
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	err = libusb20_dev_req_string_sync((void *)dev,
207	    strindex, langid, buf, buflen);
208
209	if (err)
210		return (-1);
211
212	return (0);
213}
214
215int
216usb_get_string_simple(usb_dev_handle * dev, int strindex,
217    char *buf, size_t buflen)
218{
219	int err;
220
221	err = libusb20_dev_req_string_simple_sync((void *)dev,
222	    strindex, buf, buflen);
223
224	if (err)
225		return (-1);
226
227	return (strlen(buf));
228}
229
230int
231usb_get_descriptor_by_endpoint(usb_dev_handle * udev, int ep, uint8_t type,
232    uint8_t ep_index, void *buf, int size)
233{
234	memset(buf, 0, size);
235
236	return (usb_control_msg(udev, ep | USB_ENDPOINT_IN,
237	    USB_REQ_GET_DESCRIPTOR, (type << 8) + ep_index, 0,
238	    buf, size, 1000));
239}
240
241int
242usb_get_descriptor(usb_dev_handle * udev, uint8_t type, uint8_t desc_index,
243    void *buf, int size)
244{
245	memset(buf, 0, size);
246
247	return (usb_control_msg(udev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
248	    (type << 8) + desc_index, 0, buf, size, 1000));
249}
250
251int
252usb_parse_descriptor(uint8_t *source, char *description, void *dest)
253{
254	uint8_t *sp = source;
255	uint8_t *dp = dest;
256	uint16_t w;
257	uint32_t d;
258	char *cp;
259
260	for (cp = description; *cp; cp++) {
261		switch (*cp) {
262		case 'b':		/* 8-bit byte */
263			*dp++ = *sp++;
264			break;
265			/*
266			 * 16-bit word, convert from little endian to CPU
267			 */
268		case 'w':
269			w = (sp[1] << 8) | sp[0];
270			sp += 2;
271			/* Align to word boundary */
272			dp += ((dp - (uint8_t *)0) & 1);
273			*((uint16_t *)dp) = w;
274			dp += 2;
275			break;
276			/*
277			 * 32-bit dword, convert from little endian to CPU
278			 */
279		case 'd':
280			d = (sp[3] << 24) | (sp[2] << 16) |
281			    (sp[1] << 8) | sp[0];
282			sp += 4;
283			/* Align to word boundary */
284			dp += ((dp - (uint8_t *)0) & 1);
285			/* Align to double word boundary */
286			dp += ((dp - (uint8_t *)0) & 2);
287			*((uint32_t *)dp) = d;
288			dp += 4;
289			break;
290		}
291	}
292	return (sp - source);
293}
294
295static void
296usb_parse_extra(struct usb_parse_state *ps, uint8_t **pptr, int *plen)
297{
298	void *ptr;
299	uint16_t len;
300
301	ptr = ps->a.currextra->ptr;
302	len = ps->a.currextra->len;
303
304	if (ps->preparse == 0) {
305		memcpy(ps->b.currextra, ptr, len);
306		*pptr = ps->b.currextra;
307		*plen = len;
308	}
309	ps->b.currextra += len;
310	return;
311}
312
313static void
314usb_parse_endpoint(struct usb_parse_state *ps)
315{
316	struct usb_endpoint_descriptor *bep;
317	struct libusb20_endpoint *aep;
318
319	aep = ps->a.currep;
320	bep = ps->b.currep++;
321
322	if (ps->preparse == 0) {
323		/* copy descriptor fields */
324		bep->bLength = aep->desc.bLength;
325		bep->bDescriptorType = aep->desc.bDescriptorType;
326		bep->bEndpointAddress = aep->desc.bEndpointAddress;
327		bep->bmAttributes = aep->desc.bmAttributes;
328		bep->wMaxPacketSize = aep->desc.wMaxPacketSize;
329		bep->bInterval = aep->desc.bInterval;
330		bep->bRefresh = aep->desc.bRefresh;
331		bep->bSynchAddress = aep->desc.bSynchAddress;
332	}
333	ps->a.currextra = &aep->extra;
334	usb_parse_extra(ps, &bep->extra, &bep->extralen);
335	return;
336}
337
338static void
339usb_parse_iface_sub(struct usb_parse_state *ps)
340{
341	struct libusb20_interface *aifc;
342	struct usb_interface_descriptor *bifc;
343	uint8_t x;
344
345	aifc = ps->a.currifc;
346	bifc = ps->b.currifc++;
347
348	if (ps->preparse == 0) {
349		/* copy descriptor fields */
350		bifc->bLength = aifc->desc.bLength;
351		bifc->bDescriptorType = aifc->desc.bDescriptorType;
352		bifc->bInterfaceNumber = aifc->desc.bInterfaceNumber;
353		bifc->bAlternateSetting = aifc->desc.bAlternateSetting;
354		bifc->bNumEndpoints = aifc->num_endpoints;
355		bifc->bInterfaceClass = aifc->desc.bInterfaceClass;
356		bifc->bInterfaceSubClass = aifc->desc.bInterfaceSubClass;
357		bifc->bInterfaceProtocol = aifc->desc.bInterfaceProtocol;
358		bifc->iInterface = aifc->desc.iInterface;
359		bifc->endpoint = ps->b.currep;
360	}
361	for (x = 0; x != aifc->num_endpoints; x++) {
362		ps->a.currep = aifc->endpoints + x;
363		usb_parse_endpoint(ps);
364	}
365
366	ps->a.currextra = &aifc->extra;
367	usb_parse_extra(ps, &bifc->extra, &bifc->extralen);
368	return;
369}
370
371static void
372usb_parse_iface(struct usb_parse_state *ps)
373{
374	struct libusb20_interface *aifc;
375	struct usb_interface *bifc;
376	uint8_t x;
377
378	aifc = ps->a.currifc;
379	bifc = ps->b.currifcw++;
380
381	if (ps->preparse == 0) {
382		/* initialise interface wrapper */
383		bifc->altsetting = ps->b.currifc;
384		bifc->num_altsetting = aifc->num_altsetting + 1;
385	}
386	usb_parse_iface_sub(ps);
387
388	for (x = 0; x != aifc->num_altsetting; x++) {
389		ps->a.currifc = aifc->altsetting + x;
390		usb_parse_iface_sub(ps);
391	}
392	return;
393}
394
395static void
396usb_parse_config(struct usb_parse_state *ps)
397{
398	struct libusb20_config *acfg;
399	struct usb_config_descriptor *bcfg;
400	uint8_t x;
401
402	acfg = ps->a.currcfg;
403	bcfg = ps->b.currcfg;
404
405	if (ps->preparse == 0) {
406		/* initialise config wrapper */
407		bcfg->bLength = acfg->desc.bLength;
408		bcfg->bDescriptorType = acfg->desc.bDescriptorType;
409		bcfg->wTotalLength = acfg->desc.wTotalLength;
410		bcfg->bNumInterfaces = acfg->num_interface;
411		bcfg->bConfigurationValue = acfg->desc.bConfigurationValue;
412		bcfg->iConfiguration = acfg->desc.iConfiguration;
413		bcfg->bmAttributes = acfg->desc.bmAttributes;
414		bcfg->MaxPower = acfg->desc.bMaxPower;
415		bcfg->interface = ps->b.currifcw;
416	}
417	for (x = 0; x != acfg->num_interface; x++) {
418		ps->a.currifc = acfg->interface + x;
419		usb_parse_iface(ps);
420	}
421
422	ps->a.currextra = &acfg->extra;
423	usb_parse_extra(ps, &bcfg->extra, &bcfg->extralen);
424	return;
425}
426
427int
428usb_parse_configuration(struct usb_config_descriptor *config,
429    uint8_t *buffer)
430{
431	struct usb_parse_state ps;
432	uint8_t *ptr;
433	uint32_t a;
434	uint32_t b;
435	uint32_t c;
436	uint32_t d;
437
438	if ((buffer == NULL) || (config == NULL)) {
439		return (-1);
440	}
441	memset(&ps, 0, sizeof(ps));
442
443	ps.a.currcfg = libusb20_parse_config_desc(buffer);
444	ps.b.currcfg = config;
445	if (ps.a.currcfg == NULL) {
446		/* could not parse config or out of memory */
447		return (-1);
448	}
449	/* do the pre-parse */
450	ps.preparse = 1;
451	usb_parse_config(&ps);
452
453	a = ((uint8_t *)(ps.b.currifcw) - ((uint8_t *)0));
454	b = ((uint8_t *)(ps.b.currifc) - ((uint8_t *)0));
455	c = ((uint8_t *)(ps.b.currep) - ((uint8_t *)0));
456	d = ((uint8_t *)(ps.b.currextra) - ((uint8_t *)0));
457
458	/* allocate memory for our configuration */
459	ptr = malloc(a + b + c + d);
460
461	/* "currifcw" must be first, hence this pointer is freed */
462	ps.b.currifcw = (void *)(ptr);
463	ps.b.currifc = (void *)(ptr + a);
464	ps.b.currep = (void *)(ptr + a + b);
465	ps.b.currextra = (void *)(ptr + a + b + c);
466
467	/* generate a libusb v0.1 compatible structure */
468	ps.preparse = 0;
469	usb_parse_config(&ps);
470
471	/* free config structure */
472	free(ps.a.currcfg);
473
474	return (0);			/* success */
475}
476
477void
478usb_destroy_configuration(struct usb_device *dev)
479{
480	uint8_t c;
481
482	if (dev->config == NULL) {
483		return;
484	}
485	for (c = 0; c != dev->descriptor.bNumConfigurations; c++) {
486		struct usb_config_descriptor *cf = &dev->config[c];
487
488		if (cf->interface != NULL) {
489			free(cf->interface);
490			cf->interface = NULL;
491		}
492	}
493
494	free(dev->config);
495	dev->config = NULL;
496	return;
497}
498
499void
500usb_fetch_and_parse_descriptors(usb_dev_handle * udev)
501{
502	struct usb_device *dev;
503	struct libusb20_device *pdev;
504	uint8_t *ptr;
505	int error;
506	uint32_t size;
507	uint16_t len;
508	uint8_t x;
509
510	if (udev == NULL) {
511		/* be NULL safe */
512		return;
513	}
514	dev = usb_device(udev);
515	pdev = (void *)udev;
516
517	if (dev->descriptor.bNumConfigurations == 0) {
518		/* invalid device */
519		return;
520	}
521	size = dev->descriptor.bNumConfigurations *
522	    sizeof(struct usb_config_descriptor);
523
524	dev->config = malloc(size);
525	if (dev->config == NULL) {
526		/* out of memory */
527		return;
528	}
529	memset(dev->config, 0, size);
530
531	for (x = 0; x != dev->descriptor.bNumConfigurations; x++) {
532
533		error = (pdev->methods->get_config_desc_full) (
534		    pdev, &ptr, &len, x);
535
536		if (error) {
537			usb_destroy_configuration(dev);
538			return;
539		}
540		usb_parse_configuration(dev->config + x, ptr);
541
542		/* free config buffer */
543		free(ptr);
544	}
545	return;
546}
547
548static int
549usb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size,
550    int timeout, int is_intr)
551{
552	struct libusb20_transfer *xfer;
553	uint32_t temp;
554	uint32_t maxsize;
555	uint32_t actlen;
556	char *oldbytes;
557
558	xfer = usb_get_transfer_by_ep_no(dev, ep);
559	if (xfer == NULL)
560		return (-1);
561
562	if (libusb20_tr_pending(xfer)) {
563		/* there is already a transfer ongoing */
564		return (-1);
565	}
566	maxsize = libusb20_tr_get_max_total_length(xfer);
567	oldbytes = bytes;
568
569	/*
570	 * We allow transferring zero bytes which is the same
571	 * equivalent to a zero length USB packet.
572	 */
573	do {
574
575		temp = size;
576		if (temp > maxsize) {
577			/* find maximum possible length */
578			temp = maxsize;
579		}
580		if (is_intr)
581			libusb20_tr_setup_intr(xfer, bytes, temp, timeout);
582		else
583			libusb20_tr_setup_bulk(xfer, bytes, temp, timeout);
584
585		libusb20_tr_start(xfer);
586
587		while (1) {
588
589			if (libusb20_dev_process((void *)dev) != 0) {
590				/* device detached */
591				return (-1);
592			}
593			if (libusb20_tr_pending(xfer) == 0) {
594				/* transfer complete */
595				break;
596			}
597			/* wait for USB event from kernel */
598			libusb20_dev_wait_process((void *)dev, -1);
599		}
600
601		switch (libusb20_tr_get_status(xfer)) {
602		case 0:
603			/* success */
604			break;
605		case LIBUSB20_TRANSFER_TIMED_OUT:
606			/* transfer timeout */
607			return (-ETIMEDOUT);
608		default:
609			/* other transfer error */
610			return (-ENXIO);
611		}
612		actlen = libusb20_tr_get_actual_length(xfer);
613
614		bytes += actlen;
615		size -= actlen;
616
617		if (actlen != temp) {
618			/* short transfer */
619			break;
620		}
621	} while (size > 0);
622
623	return (bytes - oldbytes);
624}
625
626int
627usb_bulk_write(usb_dev_handle * dev, int ep, char *bytes,
628    int size, int timeout)
629{
630	return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK,
631	    bytes, size, timeout, 0));
632}
633
634int
635usb_bulk_read(usb_dev_handle * dev, int ep, char *bytes,
636    int size, int timeout)
637{
638	return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK,
639	    bytes, size, timeout, 0));
640}
641
642int
643usb_interrupt_write(usb_dev_handle * dev, int ep, char *bytes,
644    int size, int timeout)
645{
646	return (usb_std_io(dev, ep & ~USB_ENDPOINT_DIR_MASK,
647	    bytes, size, timeout, 1));
648}
649
650int
651usb_interrupt_read(usb_dev_handle * dev, int ep, char *bytes,
652    int size, int timeout)
653{
654	return (usb_std_io(dev, ep | USB_ENDPOINT_DIR_MASK,
655	    bytes, size, timeout, 1));
656}
657
658int
659usb_control_msg(usb_dev_handle * dev, int requesttype, int request,
660    int value, int wIndex, char *bytes, int size, int timeout)
661{
662	struct LIBUSB20_CONTROL_SETUP_DECODED req;
663	int err;
664	uint16_t actlen;
665
666	LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req);
667
668	req.bmRequestType = requesttype;
669	req.bRequest = request;
670	req.wValue = value;
671	req.wIndex = wIndex;
672	req.wLength = size;
673
674	err = libusb20_dev_request_sync((void *)dev, &req, bytes,
675	    &actlen, timeout, 0);
676
677	if (err)
678		return (-1);
679
680	return (actlen);
681}
682
683int
684usb_set_configuration(usb_dev_handle * udev, int bConfigurationValue)
685{
686	struct usb_device *dev;
687	int err;
688	uint8_t i;
689
690	/*
691	 * Need to translate from "bConfigurationValue" to
692	 * configuration index:
693	 */
694
695	if (bConfigurationValue == 0) {
696		/* unconfigure */
697		i = 255;
698	} else {
699		/* lookup configuration index */
700		dev = usb_device(udev);
701
702		/* check if the configuration array is not there */
703		if (dev->config == NULL) {
704			return (-1);
705		}
706		for (i = 0;; i++) {
707			if (i == dev->descriptor.bNumConfigurations) {
708				/* "bConfigurationValue" not found */
709				return (-1);
710			}
711			if ((dev->config + i)->bConfigurationValue ==
712			    bConfigurationValue) {
713				break;
714			}
715		}
716	}
717
718	err = libusb20_dev_set_config_index((void *)udev, i);
719
720	if (err)
721		return (-1);
722
723	return (0);
724}
725
726int
727usb_claim_interface(usb_dev_handle * dev, int interface)
728{
729	struct libusb20_device *pdev = (void *)dev;
730
731	pdev->claimed_interface = interface;
732
733	return (0);
734}
735
736int
737usb_release_interface(usb_dev_handle * dev, int interface)
738{
739	/* do nothing */
740	return (0);
741}
742
743int
744usb_set_altinterface(usb_dev_handle * dev, int alternate)
745{
746	struct libusb20_device *pdev = (void *)dev;
747	int err;
748	uint8_t iface;
749
750	iface = pdev->claimed_interface;
751
752	err = libusb20_dev_set_alt_index((void *)dev, iface, alternate);
753
754	if (err)
755		return (-1);
756
757	return (0);
758}
759
760int
761usb_resetep(usb_dev_handle * dev, unsigned int ep)
762{
763	/* emulate an endpoint reset through clear-STALL */
764	return (usb_clear_halt(dev, ep));
765}
766
767int
768usb_clear_halt(usb_dev_handle * dev, unsigned int ep)
769{
770	struct libusb20_transfer *xfer;
771
772	xfer = usb_get_transfer_by_ep_no(dev, ep);
773	if (xfer == NULL)
774		return (-1);
775
776	libusb20_tr_clear_stall_sync(xfer);
777
778	return (0);
779}
780
781int
782usb_reset(usb_dev_handle * dev)
783{
784	int err;
785
786	err = libusb20_dev_reset((void *)dev);
787
788	if (err)
789		return (-1);
790
791	/*
792	 * Be compatible with LibUSB from sourceforge and close the
793	 * handle after reset!
794	 */
795	return (usb_close(dev));
796}
797
798const char *
799usb_strerror(void)
800{
801	/* TODO */
802	return ("Unknown error");
803}
804
805void
806usb_init(void)
807{
808	/* nothing to do */
809	return;
810}
811
812void
813usb_set_debug(int level)
814{
815	/* use kernel UGEN debugging if you need to see what is going on */
816	return;
817}
818
819int
820usb_find_busses(void)
821{
822	usb_busses = &usb_global_bus;
823	return (1);
824}
825
826int
827usb_find_devices(void)
828{
829	struct libusb20_device *pdev;
830	struct usb_device *udev;
831	struct LIBUSB20_DEVICE_DESC_DECODED *ddesc;
832	int devnum;
833	int err;
834
835	/* cleanup after last device search */
836	/* close all opened devices, if any */
837
838	while ((pdev = libusb20_be_device_foreach(usb_backend, NULL))) {
839		udev = pdev->privLuData;
840		libusb20_be_dequeue_device(usb_backend, pdev);
841		libusb20_dev_free(pdev);
842		if (udev != NULL) {
843			LIST_DEL(usb_global_bus.devices, udev);
844			free(udev);
845		}
846	}
847
848	/* free old USB backend, if any */
849
850	libusb20_be_free(usb_backend);
851
852	/* do a new backend device search */
853	usb_backend = libusb20_be_alloc_default();
854	if (usb_backend == NULL) {
855		return (-1);
856	}
857	/* iterate all devices */
858
859	devnum = 1;
860	pdev = NULL;
861	while ((pdev = libusb20_be_device_foreach(usb_backend, pdev))) {
862		udev = malloc(sizeof(*udev));
863		if (udev == NULL)
864			break;
865
866		memset(udev, 0, sizeof(*udev));
867
868		udev->bus = &usb_global_bus;
869
870		snprintf(udev->filename, sizeof(udev->filename),
871		    "/dev/ugen%u.%u",
872		    libusb20_dev_get_bus_number(pdev),
873		    libusb20_dev_get_address(pdev));
874
875		ddesc = libusb20_dev_get_device_desc(pdev);
876
877		udev->descriptor.bLength = sizeof(udev->descriptor);
878		udev->descriptor.bDescriptorType = ddesc->bDescriptorType;
879		udev->descriptor.bcdUSB = ddesc->bcdUSB;
880		udev->descriptor.bDeviceClass = ddesc->bDeviceClass;
881		udev->descriptor.bDeviceSubClass = ddesc->bDeviceSubClass;
882		udev->descriptor.bDeviceProtocol = ddesc->bDeviceProtocol;
883		udev->descriptor.bMaxPacketSize0 = ddesc->bMaxPacketSize0;
884		udev->descriptor.idVendor = ddesc->idVendor;
885		udev->descriptor.idProduct = ddesc->idProduct;
886		udev->descriptor.bcdDevice = ddesc->bcdDevice;
887		udev->descriptor.iManufacturer = ddesc->iManufacturer;
888		udev->descriptor.iProduct = ddesc->iProduct;
889		udev->descriptor.iSerialNumber = ddesc->iSerialNumber;
890		udev->descriptor.bNumConfigurations =
891		    ddesc->bNumConfigurations;
892		if (udev->descriptor.bNumConfigurations > USB_MAXCONFIG) {
893			/* truncate number of configurations */
894			udev->descriptor.bNumConfigurations = USB_MAXCONFIG;
895		}
896		udev->devnum = devnum++;
897		/* link together the two structures */
898		udev->dev = pdev;
899		pdev->privLuData = udev;
900
901		err = libusb20_dev_open(pdev, 0);
902		if (err == 0) {
903			/* XXX get all config descriptors by default */
904			usb_fetch_and_parse_descriptors((void *)pdev);
905			libusb20_dev_close(pdev);
906		}
907		LIST_ADD(usb_global_bus.devices, udev);
908	}
909
910	return (devnum - 1);			/* success */
911}
912
913struct usb_device *
914usb_device(usb_dev_handle * dev)
915{
916	struct libusb20_device *pdev;
917
918	pdev = (void *)dev;
919
920	return (pdev->privLuData);
921}
922
923struct usb_bus *
924usb_get_busses(void)
925{
926	return (usb_busses);
927}
928