diff options
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
| -rw-r--r-- | sys/dev/usb/usb_subr.c | 1127 | 
1 files changed, 0 insertions, 1127 deletions
| diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c deleted file mode 100644 index d903c07951642..0000000000000 --- a/sys/dev/usb/usb_subr.c +++ /dev/null @@ -1,1127 +0,0 @@ -/*	$NetBSD: usb_subr.c,v 1.27 1999/01/08 11:58:25 augustss Exp $	*/ -/*	FreeBSD $Id: usb_subr.c,v 1.6 1999/01/07 23:31:40 n_hibma Exp $ */ - -/* - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Lennart Augustsson (augustss@carlstedt.se) at - * Carlstedt Research & Technology. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *        This product includes software developed by the NetBSD - *        Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - *    contributors may be used to endorse or promote products derived - *    from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#if defined(__NetBSD__) -#include <sys/device.h> -#elif defined(__FreeBSD__) -#include <sys/module.h> -#include <sys/bus.h> -#endif -#include <sys/proc.h> -#include <sys/select.h> - -#include <dev/usb/usb.h> - -#include <dev/usb/usbdi.h> -#include <dev/usb/usbdi_util.h> -#include <dev/usb/usbdivar.h> -#include <dev/usb/usbdevs.h> -#include <dev/usb/usb_quirks.h> - -#if defined(__FreeBSD__) -#include <machine/clock.h> -#define delay(d)         DELAY(d) -#endif - -#ifdef USB_DEBUG -#define DPRINTF(x)	if (usbdebug) printf x -#define DPRINTFN(n,x)	if (usbdebug>(n)) printf x -extern int usbdebug; -#else -#define DPRINTF(x) -#define DPRINTFN(n,x) -#endif - -static usbd_status	usbd_set_config __P((usbd_device_handle, int)); -char *usbd_get_string __P((usbd_device_handle, int, char *)); -int usbd_getnewaddr __P((usbd_bus_handle bus)); -#if defined(__NetBSD__) -int usbd_print __P((void *aux, const char *pnp)); -int usbd_submatch __P((bdevice *, struct cfdata *cf, void *)); -#endif -void usbd_free_iface_data __P((usbd_device_handle dev, int ifcno)); -void usbd_kill_pipe __P((usbd_pipe_handle)); -usbd_status usbd_probe_and_attach  -	__P((bdevice *parent, usbd_device_handle dev, int port, int addr)); - - -#ifdef USBVERBOSE -typedef u_int16_t usb_vendor_id_t; -typedef u_int16_t usb_product_id_t; - -/* - * Descriptions of of known vendors and devices ("products"). - */ -struct usb_knowndev { -	usb_vendor_id_t		vendor; -	usb_product_id_t	product; -	int			flags; -	char			*vendorname, *productname; -}; -#define	USB_KNOWNDEV_NOPROD	0x01		/* match on vendor only */ - -#include <dev/usb/usbdevs_data.h> -#endif /* USBVERBOSE */ - -#ifdef USB_DEBUG -char *usbd_error_strs[] = { -	"NORMAL_COMPLETION", -	"IN_PROGRESS", -	"PENDING_REQUESTS", -	"NOT_STARTED", -	"INVAL", -	"IS_IDLE", -	"NOMEM", -	"CANCELLED", -	"BAD_ADDRESS", -	"IN_USE", -	"INTERFACE_NOT_ACTIVE", -	"NO_ADDR", -	"SET_ADDR_FAILED", -	"NO_POWER", -	"TOO_DEEP", -	"IOERROR", -	"NOT_CONFIGURED", -	"TIMEOUT", -	"SHORT_XFER", -	"STALLED", -	"XXX", -}; -#endif - -usbd_status -usbd_get_string_desc(dev, sindex, langid, sdesc) -	usbd_device_handle dev; -	int sindex; -	int langid; -	usb_string_descriptor_t *sdesc; -{ -	usb_device_request_t req; -	usbd_status r; - -	req.bmRequestType = UT_READ_DEVICE; -	req.bRequest = UR_GET_DESCRIPTOR; -	USETW2(req.wValue, UDESC_STRING, sindex); -	USETW(req.wIndex, langid); -	USETW(req.wLength, 1);	/* only size byte first */ -	r = usbd_do_request(dev, &req, sdesc); -	if (r != USBD_NORMAL_COMPLETION) -		return (r); -	USETW(req.wLength, sdesc->bLength);	/* the whole string */ -	return (usbd_do_request(dev, &req, sdesc)); -} - -char * -usbd_get_string(dev, si, buf) -	usbd_device_handle dev; -	int si; -	char *buf; -{ -	int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE; -	usb_string_descriptor_t us; -	char *s; -	int i, n; -	u_int16_t c; -	usbd_status r; - -	if (si == 0) -		return (0); -	if (dev->quirks->uq_flags & UQ_NO_STRINGS) -		return (0); -	if (dev->langid == USBD_NOLANG) { -		/* Set up default language */ -		r = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us); -		if (r != USBD_NORMAL_COMPLETION || us.bLength < 4) { -			dev->langid = 0; /* Well, just pick English then */ -		} else { -			/* Pick the first language as the default. */ -			dev->langid = UGETW(us.bString[0]); -		} -	} -	r = usbd_get_string_desc(dev, si, dev->langid, &us); -	if (r != USBD_NORMAL_COMPLETION) -		return (0); -	s = buf; -	n = us.bLength / 2 - 1; -	for (i = 0; i < n; i++) { -		c = UGETW(us.bString[i]); -		/* Convert from Unicode, handle buggy strings. */ -		if ((c & 0xff00) == 0) -			*s++ = c; -		else if ((c & 0x00ff) == 0 && swap) -			*s++ = c >> 8; -		else  -			*s++ = '?'; -	} -	*s++ = 0; -	return buf; -} - -void -usbd_devinfo_vp(dev, v, p) -	usbd_device_handle dev; -	char *v, *p; -{ -	usb_device_descriptor_t *udd = &dev->ddesc; -	char *vendor = 0, *product = 0; -#ifdef USBVERBOSE -	struct usb_knowndev *kdp; -#endif - -	vendor = usbd_get_string(dev, udd->iManufacturer, v); -	product = usbd_get_string(dev, udd->iProduct, p); -#ifdef USBVERBOSE -	if (!vendor) { -		for(kdp = usb_knowndevs; -		    kdp->vendorname != NULL; -		    kdp++) { -			if (kdp->vendor == UGETW(udd->idVendor) &&  -			    (kdp->product == UGETW(udd->idProduct) || -			     (kdp->flags & USB_KNOWNDEV_NOPROD) != 0)) -				break; -		} -		if (kdp->vendorname == NULL) -			vendor = product = NULL; -		else { -			vendor = kdp->vendorname; -			product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ? -				kdp->productname : NULL; -		} -	} -#endif -	if (vendor) -		strcpy(v, vendor); -	else -		sprintf(v, "vendor 0x%04x", UGETW(udd->idVendor)); -	if (product) -		strcpy(p, product); -	else -		sprintf(p, "product 0x%04x", UGETW(udd->idProduct)); -} - -int -usbd_printBCD(cp, bcd) -	char *cp; -	int bcd; -{ -	return (sprintf(cp, "%x.%02x", bcd >> 8, bcd & 0xff)); -} - -void -usbd_devinfo(dev, showclass, cp) -	usbd_device_handle dev; -	int showclass; -	char *cp; -{ -	usb_device_descriptor_t *udd = &dev->ddesc; -	char vendor[USB_MAX_STRING_LEN]; -	char product[USB_MAX_STRING_LEN]; -	int bcdDevice, bcdUSB; - -	usbd_devinfo_vp(dev, vendor, product); -	cp += sprintf(cp, "%s %s", vendor, product); -	if (showclass) -		cp += sprintf(cp, ", class %d/%d", -			      udd->bDeviceClass, udd->bDeviceSubClass); -	bcdUSB = UGETW(udd->bcdUSB); -	bcdDevice = UGETW(udd->bcdDevice); -	cp += sprintf(cp, ", rev "); -	cp += usbd_printBCD(cp, bcdUSB); -	*cp++ = '/'; -	cp += usbd_printBCD(cp, bcdDevice); -	cp += sprintf(cp, ", addr %d", dev->address); -	*cp = 0; -} - -/* Delay for a certain number of ms */ -void -usb_delay_ms(bus, ms) -	usbd_bus_handle bus; -	u_int ms; -{ -	/* Wait at least two clock ticks so we know the time has passed. */ -	if (bus->use_polling) -		delay((ms+1) * 1000); -	else -		tsleep(&ms, PRIBIO, "usbdly", (ms*hz+999)/1000 + 1); -} - -/* Delay given a device handle. */ -void -usbd_delay_ms(dev, ms) -	usbd_device_handle dev; -	u_int ms; -{ -	usb_delay_ms(dev->bus, ms); -} - -usbd_status -usbd_reset_port(dev, port, ps) -	usbd_device_handle dev; -	int port; -	usb_port_status_t *ps; -{ -	usb_device_request_t req; -	usbd_status r; -	int n; -	 -	req.bmRequestType = UT_WRITE_CLASS_OTHER; -	req.bRequest = UR_SET_FEATURE; -	USETW(req.wValue, UHF_PORT_RESET); -	USETW(req.wIndex, port); -	USETW(req.wLength, 0); -	r = usbd_do_request(dev, &req, 0); -	DPRINTFN(1,("usbd_reset_port: port %d reset done, error=%d(%s)\n", -		    port, r, usbd_error_strs[r])); -	if (r != USBD_NORMAL_COMPLETION) -		return (r); -	n = 10; -	do { -		/* Wait for device to recover from reset. */ -		usbd_delay_ms(dev, USB_PORT_RESET_DELAY); -		r = usbd_get_port_status(dev, port, ps); -		if (r != USBD_NORMAL_COMPLETION) { -			DPRINTF(("usbd_reset_port: get status failed %d\n",r)); -			return (r); -		} -	} while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0); -	if (n == 0) { -		printf("usbd_reset_port: timeout\n"); -		return (USBD_IOERROR); -	} -	r = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET); -#ifdef USB_DEBUG -	if (r != USBD_NORMAL_COMPLETION) -		DPRINTF(("usbd_reset_port: clear port feature failed %d\n",r)); -#endif - -	/* Wait for the device to recover from reset. */ -	usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY); -	return (r); -} - -usb_interface_descriptor_t * -usbd_find_idesc(cd, ifaceidx, altidx) -	usb_config_descriptor_t *cd; -	int ifaceidx; -	int altidx; -{ -	char *p = (char *)cd; -	char *end = p + UGETW(cd->wTotalLength); -	usb_interface_descriptor_t *d; -	int curidx, lastidx, curaidx = 0; - -	for (curidx = lastidx = -1; p < end; ) { -		d = (usb_interface_descriptor_t *)p; -		DPRINTFN(4,("usbd_find_idesc: idx=%d(%d) altidx=%d(%d) len=%d " -			    "type=%d\n",  -			    ifaceidx, curidx, altidx, curaidx, -			    d->bLength, d->bDescriptorType)); -		if (d->bLength == 0) /* bad descriptor */ -			break; -		p += d->bLength; -		if (p <= end && d->bDescriptorType == UDESC_INTERFACE) { -			if (d->bInterfaceNumber != lastidx) { -				lastidx = d->bInterfaceNumber; -				curidx++; -				curaidx = 0; -			} else -				curaidx++; -			if (ifaceidx == curidx && altidx == curaidx) -				return (d); -		} -	} -	return (0); -} - -usb_endpoint_descriptor_t * -usbd_find_edesc(cd, ifaceidx, altidx, endptidx) -	usb_config_descriptor_t *cd; -	int ifaceidx; -	int altidx; -	int endptidx; -{ -	char *p = (char *)cd; -	char *end = p + UGETW(cd->wTotalLength); -	usb_interface_descriptor_t *d; -	usb_endpoint_descriptor_t *e; -	int curidx; - -	d = usbd_find_idesc(cd, ifaceidx, altidx); -	if (!d) -		return (0); -	if (endptidx >= d->bNumEndpoints) /* quick exit */ -		return (0); - -	curidx = -1; -	for (p = (char *)d + d->bLength; p < end; ) { -		e = (usb_endpoint_descriptor_t *)p; -		if (e->bLength == 0) /* bad descriptor */ -			break; -		p += e->bLength; -		if (p <= end && e->bDescriptorType == UDESC_INTERFACE) -			return (0); -		if (p <= end && e->bDescriptorType == UDESC_ENDPOINT) { -			curidx++; -			if (curidx == endptidx) -				return (e); -		} -	} -	return (0); -} - -usbd_status -usbd_fill_iface_data(dev, ifaceidx, altidx) -	usbd_device_handle dev; -	int ifaceidx; -	int altidx; -{ -	usbd_interface_handle ifc = &dev->ifaces[ifaceidx]; -	char *p, *end; -	int endpt, nendpt; - -	DPRINTFN(4,("usbd_fill_iface_data: ifaceidx=%d altidx=%d\n", -		    ifaceidx, altidx)); -	ifc->device = dev; -	ifc->idesc = usbd_find_idesc(dev->cdesc, ifaceidx, altidx); -	if (ifc->idesc == 0) -		return (USBD_INVAL); -	ifc->index = ifaceidx; -	ifc->altindex = altidx; -	nendpt = ifc->idesc->bNumEndpoints; -	DPRINTFN(10,("usbd_fill_iface_data: found idesc n=%d\n", nendpt)); -	if (nendpt != 0) { -		ifc->endpoints = malloc(nendpt * sizeof(struct usbd_endpoint), -					M_USB, M_NOWAIT); -		if (ifc->endpoints == 0) -			return (USBD_NOMEM); -	} else -		ifc->endpoints = 0; -	ifc->priv = 0; -	p = (char *)ifc->idesc + ifc->idesc->bLength; -	end = (char *)dev->cdesc + UGETW(dev->cdesc->wTotalLength); -#define ed ((usb_endpoint_descriptor_t *)p) -	for (endpt = 0; endpt < nendpt; endpt++) { -		DPRINTFN(10,("usbd_fill_iface_data: endpt=%d\n", endpt)); -		for (; p < end; p += ed->bLength) { -			ed = (usb_endpoint_descriptor_t *)p; -			DPRINTFN(10,("usbd_fill_iface_data: p=%p end=%p " -				     "len=%d type=%d\n", -				 p, end, ed->bLength, ed->bDescriptorType)); -			if (p + ed->bLength <= end && ed->bLength != 0 && -			    ed->bDescriptorType == UDESC_ENDPOINT) -				goto found; -			if (ed->bDescriptorType == UDESC_INTERFACE || -			    ed->bLength == 0) -				break; -		} -		/* passed end, or bad desc */ -		goto bad; -	found: -		ifc->endpoints[endpt].edesc = ed; -		ifc->endpoints[endpt].state = USBD_ENDPOINT_ACTIVE; -		ifc->endpoints[endpt].refcnt = 0; -		ifc->endpoints[endpt].toggle = 0; -		p += ed->bLength; -	} -#undef ed -	LIST_INIT(&ifc->pipes); -	ifc->state = USBD_INTERFACE_ACTIVE; -	return (USBD_NORMAL_COMPLETION); - - bad: -	free(ifc->endpoints, M_USB); -	return (USBD_INVAL); -} - -void -usbd_free_iface_data(dev, ifcno) -	usbd_device_handle dev; -	int ifcno; -{ -	usbd_interface_handle ifc = &dev->ifaces[ifcno]; -	if (ifc->endpoints) -		free(ifc->endpoints, M_USB); -} - -static usbd_status -usbd_set_config(dev, conf) -	usbd_device_handle dev; -	int conf; -{ -	usb_device_request_t req; - -	req.bmRequestType = UT_WRITE_DEVICE; -	req.bRequest = UR_SET_CONFIG; -	USETW(req.wValue, conf); -	USETW(req.wIndex, 0); -	USETW(req.wLength, 0); -	return (usbd_do_request(dev, &req, 0)); -} - -usbd_status -usbd_set_config_no(dev, no, msg) -	usbd_device_handle dev; -	int no; -	int msg; -{ -	int index; -	usb_config_descriptor_t cd; -	usbd_status r; - -	DPRINTFN(5,("usbd_set_config_no: %d\n", no)); -	/* Figure out what config index to use. */ -	for (index = 0; index < dev->ddesc.bNumConfigurations; index++) { -		r = usbd_get_config_desc(dev, index, &cd); -		if (r != USBD_NORMAL_COMPLETION) -			return (r); -		if (cd.bConfigurationValue == no) -			return (usbd_set_config_index(dev, index, msg)); -	} -	return (USBD_INVAL); -} - -usbd_status -usbd_set_config_index(dev, index, msg) -	usbd_device_handle dev; -	int index; -	int msg; -{ -	usb_status_t ds; -	usb_hub_status_t hs; -	usb_config_descriptor_t cd, *cdp; -	usbd_status r; -	int ifcidx, nifc, len, selfpowered, power; - -	DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index)); - -	/* XXX check that all interfaces are idle */ -	if (dev->config != 0) { -		DPRINTF(("usbd_set_config_index: free old config\n")); -		/* Free all configuration data structures. */ -		nifc = dev->cdesc->bNumInterface; -		for (ifcidx = 0; ifcidx < nifc; ifcidx++) -			usbd_free_iface_data(dev, ifcidx); -		free(dev->ifaces, M_USB); -		free(dev->cdesc, M_USB); -		dev->ifaces = 0; -		dev->cdesc = 0; -		dev->config = 0; -		dev->state = USBD_DEVICE_ADDRESSED; -	} - -	/* Figure out what config number to use. */ -	r = usbd_get_config_desc(dev, index, &cd); -	if (r != USBD_NORMAL_COMPLETION) -		return (r); -	len = UGETW(cd.wTotalLength); -	cdp = malloc(len, M_USB, M_NOWAIT); -	if (cdp == 0) -		return (USBD_NOMEM); -	r = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp); -	if (r != USBD_NORMAL_COMPLETION) -		goto bad; -	if (cdp->bDescriptorType != UDESC_CONFIG) { -		DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n", -			     cdp->bDescriptorType)); -		r = USBD_INVAL; -		goto bad; -	} -	selfpowered = 0; -	if (cdp->bmAttributes & UC_SELF_POWERED) { -		/* May be self powered. */ -		if (cdp->bmAttributes & UC_BUS_POWERED) { -			/* Must ask device. */ -			if (dev->quirks->uq_flags & UQ_HUB_POWER) { -				/* Buggy hub, use hub descriptor. */ -				r = usbd_get_hub_status(dev, &hs); -				if (r == USBD_NORMAL_COMPLETION &&  -				    !(UGETW(hs.wHubStatus) & UHS_LOCAL_POWER)) -					selfpowered = 1; -			} else { -				r = usbd_get_device_status(dev, &ds); -				if (r == USBD_NORMAL_COMPLETION &&  -				    (UGETW(ds.wStatus) & UDS_SELF_POWERED)) -					selfpowered = 1; -			} -			DPRINTF(("usbd_set_config_index: status=0x%04x, " -				 "error=%d(%s)\n", -				 UGETW(ds.wStatus), r, usbd_error_strs[r])); -		} else -			selfpowered = 1; -	} -	DPRINTF(("usbd_set_config_index: (addr %d) attr=0x%02x, " -		 "selfpowered=%d, power=%d, powerquirk=%x\n",  -		 dev->address, cdp->bmAttributes,  -		 selfpowered, cdp->bMaxPower * 2, -		 dev->quirks->uq_flags & UQ_HUB_POWER)); -#ifdef USB_DEBUG -	if (!dev->powersrc) { -		printf("usbd_set_config_index: No power source?\n"); -		return (USBD_IOERROR); -	} -#endif -	power = cdp->bMaxPower * 2; -	if (power > dev->powersrc->power) { -		/* XXX print nicer message. */ -		if (msg) -			printf("%s: device addr %d (config %d) exceeds power " -				 "budget, %d mA > %d mA\n", -			       USBDEVNAME(dev->bus->bdev), dev->address,  -			       cdp->bConfigurationValue,  -			       power, dev->powersrc->power); -		r = USBD_NO_POWER; -		goto bad; -	} -	dev->power = power; -	dev->self_powered = selfpowered; - -	DPRINTF(("usbd_set_config_index: set config %d\n", -		 cdp->bConfigurationValue)); -	r = usbd_set_config(dev, cdp->bConfigurationValue); -	if (r != USBD_NORMAL_COMPLETION) { -		DPRINTF(("usbd_set_config_index: setting config=%d failed, " -			 "error=%d(%s)\n", -			 cdp->bConfigurationValue, r, usbd_error_strs[r])); -		goto bad; -	} -	DPRINTF(("usbd_set_config_index: setting new config %d\n", -		 cdp->bConfigurationValue)); -	nifc = cdp->bNumInterface; -	dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),  -			     M_USB, M_NOWAIT); -	if (dev->ifaces == 0) { -		r = USBD_NOMEM; -		goto bad; -	} -	DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp)); -	dev->cdesc = cdp; -	dev->config = cdp->bConfigurationValue; -	dev->state = USBD_DEVICE_CONFIGURED; -	for (ifcidx = 0; ifcidx < nifc; ifcidx++) { -		r = usbd_fill_iface_data(dev, ifcidx, 0); -		if (r != USBD_NORMAL_COMPLETION) { -			while (--ifcidx >= 0) -				usbd_free_iface_data(dev, ifcidx); -			goto bad; -		} -	} - -	return (USBD_NORMAL_COMPLETION); - - bad: -	free(cdp, M_USB); -	return (r); -} - -/* XXX add function for alternate settings */ - -usbd_status -usbd_setup_pipe(dev, iface, ep, pipe) -	usbd_device_handle dev; -	usbd_interface_handle iface;  -	struct usbd_endpoint *ep; -	usbd_pipe_handle *pipe; -{ -	usbd_pipe_handle p; -	usbd_status r; - -	DPRINTFN(1,("usbd_setup_pipe: dev=%p iface=%p ep=%p pipe=%p\n", -		    dev, iface, ep, pipe)); -	p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT); -	if (p == 0) -		return (USBD_NOMEM); -	p->device = dev; -	p->iface = iface; -	p->state = USBD_PIPE_ACTIVE; -	p->endpoint = ep; -	ep->refcnt++; -	p->refcnt = 1; -	p->intrreqh = 0; -	p->running = 0; -	SIMPLEQ_INIT(&p->queue); -	r = dev->bus->open_pipe(p); -	if (r != USBD_NORMAL_COMPLETION) { -		DPRINTFN(-1,("usbd_setup_pipe: endpoint=0x%x failed, error=%d" -			 "(%s)\n", -			 ep->edesc->bEndpointAddress, r, usbd_error_strs[r])); -		free(p, M_USB); -		return (r); -	} -	*pipe = p; -	return (USBD_NORMAL_COMPLETION); -} - -/* Abort the device control pipe. */ -void -usbd_kill_pipe(pipe) -	usbd_pipe_handle pipe; -{ -	pipe->methods->close(pipe); -	pipe->endpoint->refcnt--; -	free(pipe, M_USB); -} - -int -usbd_getnewaddr(bus) -	usbd_bus_handle bus; -{ -	int addr; - -	for (addr = 1; addr < USB_MAX_DEVICES; addr++) -		if (bus->devices[addr] == 0) -			return (addr); -	return (-1); -} - - -usbd_status -usbd_probe_and_attach(parent, dev, port, addr) -	bdevice *parent; -	usbd_device_handle dev; -	int port; -	int addr; -{ -	struct usb_attach_arg uaa; -	usb_device_descriptor_t *dd = &dev->ddesc; -	int r, found, i, confi, nifaces; -	usbd_interface_handle ifaces[256]; /* 256 is the absolute max */ - -#if defined(__FreeBSD__) -/* XXX uaa is a static var. Not a problem as it _should_ be used only - * during probe and attach. Should be changed however - */ -	bdevice bdev; -	bdev = device_add_child(*parent, NULL, -1, &uaa); -	if (!bdev) { -	    printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev)); -	    return (USBD_INVAL); -	} -#endif - -	uaa.device = dev; -	uaa.iface = 0; -	uaa.ifaces = 0; -	uaa.nifaces = 0; -	uaa.usegeneric = 0; -	uaa.port = port; -	uaa.configno = UHUB_UNK_CONFIGURATION; -	uaa.ifaceno = UHUB_UNK_INTERFACE; - -	/* First try with device specific drivers. */ -	if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch)) -		return (USBD_NORMAL_COMPLETION); - -	DPRINTF(("usbd_probe_and_attach: no device specific driver found\n")); - -	/* Next try with interface drivers. */ -	for (confi = 0; confi < dd->bNumConfigurations; confi++) { -		DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n", -			    confi)); -		r = usbd_set_config_index(dev, confi, 1); -		if (r != USBD_NORMAL_COMPLETION) { -#ifdef USB_DEBUG -			DPRINTF(("%s: port %d, set config at addr %d failed, " -				 "error=%d(%s)\n", USBDEVNAME(*parent), port, -				 addr, r, usbd_error_strs[r])); -#else -			printf("%s: port %d, set config at addr %d failed\n", -			       USBDEVNAME(*parent), port, addr); -#endif -#if defined(__FreeBSD__) -			device_delete_child(*parent, bdev); -#endif -			return (r); -		} -		nifaces = dev->cdesc->bNumInterface; -		uaa.configno = dev->cdesc->bConfigurationValue; -		for (i = 0; i < nifaces; i++) -			ifaces[i] = &dev->ifaces[i]; -		uaa.ifaces = ifaces; -		uaa.nifaces = nifaces; -		for (found = i = 0; i < nifaces; i++) { -			if (!ifaces[i]) -				continue; /* interface already claimed */ -			uaa.iface = ifaces[i]; -			uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber; -			if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print,  -					  usbd_submatch)) { -				found++; -				ifaces[i] = 0; /* consumed */ -			} -		} -		if (found != 0) -			return (USBD_NORMAL_COMPLETION); -	} -	/* No interfaces were attached in any of the configurations. */ -	if (dd->bNumConfigurations > 1)/* don't change if only 1 config */ -		usbd_set_config_index(dev, 0, 0); - -	DPRINTF(("usbd_probe_and_attach: no interface drivers found\n")); - -	/* Finally try the generic driver. */ -	uaa.iface = 0; -	uaa.usegeneric = 1; -	uaa.configno = UHUB_UNK_CONFIGURATION; -	uaa.ifaceno = UHUB_UNK_INTERFACE; -	if (USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch)) -		return (USBD_NORMAL_COMPLETION); - -	/*  -	 * The generic attach failed, but leave the device as it is. -	 * We just did not find any drivers, that's all.  The device is -	 * fully operational and not harming anyone. -	 */ -	DPRINTF(("usbd_probe_and_attach: generic attach failed\n")); -#if defined(__FreeBSD__) -/* - * XXX should we delete the child again? Left for now to avoid dangling - * references. -	device_delete_child(*parent, bdev); -*/ -#endif -	return (USBD_NORMAL_COMPLETION); -} - - - -/* - * Called when a new device has been put in the powered state, - * but not yet in the addressed state. - * Get initial descriptor, set the address, get full descriptor, - * and attach a driver. - */ -usbd_status -usbd_new_device(parent, bus, depth, lowspeed, port, up) -	bdevice *parent; -	usbd_bus_handle bus; -	int depth; -	int lowspeed; -	int port; -	struct usbd_port *up; -{ -	usbd_device_handle dev; -	usb_device_descriptor_t *dd; -	usbd_status r; -	int addr; -	int i; - -	DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n", -		 bus, depth, lowspeed)); -	addr = usbd_getnewaddr(bus); -	if (addr < 0) { -		printf("%s: No free USB addresses, new device ignored.\n",  -		       USBDEVNAME(bus->bdev)); -		return (USBD_NO_ADDR); -	} - -	dev = malloc(sizeof *dev, M_USB, M_NOWAIT); -	if (dev == 0) -		return (USBD_NOMEM); -	memset(dev, 0, sizeof(*dev)); - -	dev->bus = bus; - -	/* Set up default endpoint handle. */ -	dev->def_ep.edesc = &dev->def_ep_desc; -	dev->def_ep.state = USBD_ENDPOINT_ACTIVE; - -	/* Set up default endpoint descriptor. */ -	dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE; -	dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT; -	dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT; -	dev->def_ep_desc.bmAttributes = UE_CONTROL; -	USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET); -	dev->def_ep_desc.bInterval = 0; - -	dev->state = USBD_DEVICE_DEFAULT; -	dev->quirks = &usbd_no_quirk; -	dev->address = USB_START_ADDR; -	dev->ddesc.bMaxPacketSize = 0; -	dev->lowspeed = lowspeed != 0; -	dev->depth = depth; -	dev->powersrc = up; -	dev->langid = USBD_NOLANG; - -	/* Establish the the default pipe. */ -	r = usbd_setup_pipe(dev, 0, &dev->def_ep, &dev->default_pipe); -	if (r != USBD_NORMAL_COMPLETION) { -		usbd_remove_device(dev, up); -		return (r); -	} - -	up->device = dev; -	dd = &dev->ddesc; -	/* Try a few times in case the device is slow (i.e. outside specs.) */ -	for (i = 0; i < 5; i++) { -		/* Get the first 8 bytes of the device descriptor. */ -		r = usbd_get_desc(dev, UDESC_DEVICE, 0, USB_MAX_IPACKET, dd); -		if (r == USBD_NORMAL_COMPLETION) -			break; -		usbd_delay_ms(dev, 200); -	} -	if (r != USBD_NORMAL_COMPLETION) { -		DPRINTFN(-1, ("usbd_new_device: addr=%d, getting first desc " -			      "failed\n", -			      addr)); -		usbd_remove_device(dev, up); -		return (r); -	} - -	if (dd->bDescriptorType != UDESC_DEVICE) { -		/* Illegal device descriptor */ -		DPRINTFN(-1,("usbd_new_device: illegal descriptor %d\n", -			     dd->bDescriptorType)); -		usbd_remove_device(dev, up); -		return (USBD_INVAL); -	} - -	DPRINTF(("usbd_new_device: adding unit addr=%d, rev=%02x, class=%d, " -		 "subclass=%d, protocol=%d, maxpacket=%d, ls=%d\n",  -		 addr,UGETW(dd->bcdUSB), dd->bDeviceClass, dd->bDeviceSubClass, -		 dd->bDeviceProtocol, dd->bMaxPacketSize, dev->lowspeed)); - -	USETW(dev->def_ep_desc.wMaxPacketSize, dd->bMaxPacketSize); - -	/* Get the full device descriptor. */ -	r = usbd_get_device_desc(dev, dd); -	if (r != USBD_NORMAL_COMPLETION) { -		DPRINTFN(-1, ("usbd_new_device: addr=%d, getting full desc " -			      "failed\n", addr)); -		usbd_remove_device(dev, up); -		return (r); -	} - -	/* Figure out what's wrong with this device. */ -	dev->quirks = usbd_find_quirk(dd); - -	/* Set the address */ -	r = usbd_set_address(dev, addr); -	if (r != USBD_NORMAL_COMPLETION) { -		DPRINTFN(-1,("usb_new_device: set address %d failed\n",addr)); -		r = USBD_SET_ADDR_FAILED; -		usbd_remove_device(dev, up); -		return (r); -	} -	/* Allow device time to set new address */ -	usbd_delay_ms(dev, USB_SET_ADDRESS_SETTLE); - -	dev->address = addr;	/* New device address now */ -	dev->state = USBD_DEVICE_ADDRESSED; -	bus->devices[addr] = dev; - -	/* Assume 100mA bus powered for now. Changed when configured. */ -	dev->power = USB_MIN_POWER; -	dev->self_powered = 0; - -	DPRINTF(("usbd_new_device: new dev (addr %d), dev=%p, parent=%p\n",  -		 addr, dev, parent)); - -	r = usbd_probe_and_attach(parent, dev, port, addr); -	if (r != USBD_NORMAL_COMPLETION) { -		usbd_remove_device(dev, up); -		return (r); -  	} -   -  	return (USBD_NORMAL_COMPLETION); -} - -void -usbd_remove_device(dev, up) -	usbd_device_handle dev; -	struct usbd_port *up; -{ -	DPRINTF(("usbd_remove_device: %p\n", dev)); -   -	if (dev->default_pipe) -		usbd_kill_pipe(dev->default_pipe); -	up->device = 0; -	dev->bus->devices[dev->address] = 0; - -	free(dev, M_USB); -} - -#if defined(__NetBSD__)   -int -usbd_print(aux, pnp) -	void *aux; -	const char *pnp; -{ -	struct usb_attach_arg *uaa = aux; -	char devinfo[1024]; - -	DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device)); -	if (pnp) { -		if (!uaa->usegeneric) -			return (QUIET); -		usbd_devinfo(uaa->device, 1, devinfo); -		printf("%s, %s", devinfo, pnp); -	} -	if (uaa->port != 0) -		printf(" port %d", uaa->port); -	if (uaa->configno != UHUB_UNK_CONFIGURATION) -		printf(" configuration %d", uaa->configno); -	if (uaa->ifaceno != UHUB_UNK_INTERFACE) -		printf(" interface %d", uaa->ifaceno); -	return (UNCONF); -} - -int -usbd_submatch(parent, cf, aux) -	struct device *parent; -	struct cfdata *cf; -	void *aux; -{ -	struct usb_attach_arg *uaa = aux; - -	if ((uaa->port != 0 && -	     cf->uhubcf_port != UHUB_UNK_PORT && -	     cf->uhubcf_port != uaa->port) || -	    (uaa->configno != UHUB_UNK_CONFIGURATION && -	     cf->uhubcf_configuration != UHUB_UNK_CONFIGURATION && -	     cf->uhubcf_configuration != uaa->configno) || -	    (uaa->ifaceno != UHUB_UNK_INTERFACE && -	     cf->uhubcf_interface != UHUB_UNK_INTERFACE && -	     cf->uhubcf_interface != uaa->ifaceno)) -		return 0; -	return ((*cf->cf_attach->ca_match)(parent, cf, aux)); -} -#endif - -usbd_status -usb_insert_transfer(reqh) -	usbd_request_handle reqh; -{ -	usbd_pipe_handle pipe = reqh->pipe; -	usbd_interface_handle iface = pipe->iface; - -	if (pipe->state == USBD_PIPE_IDLE || -	    (iface && iface->state == USBD_INTERFACE_IDLE)) -		return (USBD_IS_IDLE); -	SIMPLEQ_INSERT_TAIL(&pipe->queue, reqh, next); -	if (pipe->state != USBD_PIPE_ACTIVE || -	    (iface && iface->state != USBD_INTERFACE_ACTIVE)) -		return (USBD_NOT_STARTED); -	if (pipe->running) -		return (USBD_IN_PROGRESS); -	pipe->running = 1; -	return (USBD_NORMAL_COMPLETION); -} - -void -usb_start_next(pipe) -	usbd_pipe_handle pipe; -{ -	usbd_request_handle reqh; -	usbd_status r; - -#ifdef DIAGNOSTIC -	if (SIMPLEQ_FIRST(&pipe->queue) == 0) { -		printf("usb_start_next: empty\n"); -		return; -	} -#endif - -	/* First remove remove old */ -	SIMPLEQ_REMOVE_HEAD(&pipe->queue, SIMPLEQ_FIRST(&pipe->queue), next); -	if (pipe->state != USBD_PIPE_ACTIVE) { -		pipe->running = 0; -		return; -	} -	reqh = SIMPLEQ_FIRST(&pipe->queue); -	DPRINTFN(5, ("usb_start_next: start reqh=%p\n", reqh)); -	if (!reqh) -		pipe->running = 0; -	else { -		r = pipe->methods->start(reqh); -		if (r != USBD_IN_PROGRESS) { -			printf("usb_start_next: error=%d\n", r); -			pipe->running = 0; -			/* XXX do what? */ -		} -	} -} - -void -usbd_fill_deviceinfo(dev, di) -	usbd_device_handle dev; -	struct usb_device_info *di; -{ -	struct usbd_port *p; -	int i, r, s; - -	di->config = dev->config; -	usbd_devinfo_vp(dev, di->vendor, di->product); -	usbd_printBCD(di->revision, UGETW(dev->ddesc.bcdDevice)); -	di->vendorNo = UGETW(dev->ddesc.idVendor); -	di->productNo = UGETW(dev->ddesc.idProduct); -	di->class = dev->ddesc.bDeviceClass; -	di->power = dev->self_powered ? 0 : dev->power; -	di->lowspeed = dev->lowspeed; -	di->addr = dev->address; -	if (dev->hub) { -		for (i = 0;  -		     i < sizeof(di->ports) / sizeof(di->ports[0]) && -			     i < dev->hub->hubdesc.bNbrPorts; -		     i++) { -			p = &dev->hub->ports[i]; -			if (p->device) -				r = p->device->address; -			else { -				s = UGETW(p->status.wPortStatus); -				if (s & UPS_PORT_ENABLED) -					r = USB_PORT_ENABLED; -				else if (s & UPS_SUSPEND) -					r = USB_PORT_SUSPENDED; -				else if (s & UPS_PORT_POWER) -					r = USB_PORT_POWERED; -				else -					r = USB_PORT_DISABLED; -			} -			di->ports[i] = r; -		} -		di->nports = dev->hub->hubdesc.bNbrPorts; -	} else -		di->nports = 0; -} | 
