summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usb_subr.c
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2000-08-13 18:39:24 +0000
committern_hibma <n_hibma@FreeBSD.org>2000-08-13 18:39:24 +0000
commit17d5aba6f2ac45c2fc102114f1a02a62a94c6bbe (patch)
tree6000c938bb7a8dfddd2c1d8371e6a377a6757bda /sys/dev/usb/usb_subr.c
parent2424c7393a2a912ab1e3678c643b613766634171 (diff)
downloadFreeBSD-src-17d5aba6f2ac45c2fc102114f1a02a62a94c6bbe.zip
FreeBSD-src-17d5aba6f2ac45c2fc102114f1a02a62a94c6bbe.tar.gz
From NetBSD:
Make it possible to move a device to its unconfigured state by using config #0. Add some comments. Change error reporting in port reset function. usbd_devinfo_vp(): search the know devs array also if the device doesn't return product description (e.g. Kye's Genius NetScroll mouse returns vendor, but not product); the strings returned by device are still preferred to those in the array, though
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r--sys/dev/usb/usb_subr.c71
1 files changed, 49 insertions, 22 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 22a5741..8b467f3 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_subr.c,v 1.63 2000/01/19 00:23:58 augustss Exp $ */
+/* $NetBSD: usb_subr.c,v 1.76 2000/04/27 15:26:50 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -233,7 +233,7 @@ usbd_devinfo_vp(dev, v, p)
vendor = usbd_get_string(dev, udd->iManufacturer, v);
product = usbd_get_string(dev, udd->iProduct, p);
#ifdef USBVERBOSE
- if (vendor == NULL) {
+ if (vendor == NULL || product == NULL) {
for(kdp = usb_knowndevs;
kdp->vendorname != NULL;
kdp++) {
@@ -242,10 +242,10 @@ usbd_devinfo_vp(dev, v, p)
(kdp->flags & USB_KNOWNDEV_NOPROD) != 0))
break;
}
- if (kdp->vendorname == NULL)
- vendor = product = NULL;
- else {
+ if (kdp->vendorname != NULL) {
+ if (!vendor)
vendor = kdp->vendorname;
+ if (!product)
product = (kdp->flags & USB_KNOWNDEV_NOPROD) == 0 ?
kdp->productname : NULL;
}
@@ -348,10 +348,8 @@ usbd_reset_port(dev, port, ps)
return (err);
}
} while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
- if (n == 0) {
- printf("usbd_reset_port: timeout\n");
- return (USBD_IOERROR);
- }
+ if (n == 0)
+ return (USBD_TIMEOUT);
err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
#ifdef USB_DEBUG
if (err)
@@ -535,6 +533,9 @@ usbd_set_config_no(dev, no, msg)
usb_config_descriptor_t cd;
usbd_status err;
+ if (no == USB_UNCONFIG_NO)
+ return (usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg));
+
DPRINTFN(5,("usbd_set_config_no: %d\n", no));
/* Figure out what config index to use. */
for (index = 0; index < dev->ddesc.bNumConfigurations; index++) {
@@ -561,7 +562,7 @@ usbd_set_config_index(dev, index, msg)
DPRINTFN(5,("usbd_set_config_index: dev=%p index=%d\n", dev, index));
/* XXX check that all interfaces are idle */
- if (dev->config != 0) {
+ if (dev->config != USB_UNCONFIG_NO) {
DPRINTF(("usbd_set_config_index: free old config\n"));
/* Free all configuration data structures. */
nifc = dev->cdesc->bNumInterface;
@@ -571,10 +572,20 @@ usbd_set_config_index(dev, index, msg)
free(dev->cdesc, M_USB);
dev->ifaces = NULL;
dev->cdesc = NULL;
- dev->config = 0;
+ dev->config = USB_UNCONFIG_NO;
+ }
+
+ if (index == USB_UNCONFIG_INDEX) {
+ /* We are unconfiguring the device, so leave unallocated. */
+ DPRINTF(("usbd_set_config_index: set config 0\n"));
+ err = usbd_set_config(dev, USB_UNCONFIG_NO);
+ if (err)
+ DPRINTF(("usbd_set_config_index: setting config=0 "
+ "failed, error=%s\n", usbd_errstr(err)));
+ return (err);
}
- /* Figure out what config number to use. */
+ /* Get the short descriptor. */
err = usbd_get_config_desc(dev, index, &cd);
if (err)
return (err);
@@ -582,6 +593,7 @@ usbd_set_config_index(dev, index, msg)
cdp = malloc(len, M_USB, M_NOWAIT);
if (cdp == NULL)
return (USBD_NOMEM);
+ /* Get the full descriptor. */
err = usbd_get_desc(dev, UDESC_CONFIG, index, len, cdp);
if (err)
goto bad;
@@ -591,9 +603,11 @@ usbd_set_config_index(dev, index, msg)
err = USBD_INVAL;
goto bad;
}
+
+ /* Figure out if the device is self or bus powered. */
selfpowered = 0;
if (!(dev->quirks->uq_flags & UQ_BUS_POWERED) &&
- cdp->bmAttributes & UC_SELF_POWERED) {
+ (cdp->bmAttributes & UC_SELF_POWERED)) {
/* May be self powered. */
if (cdp->bmAttributes & UC_BUS_POWERED) {
/* Must ask device. */
@@ -610,6 +624,8 @@ usbd_set_config_index(dev, index, msg)
"selfpowered=%d, power=%d\n",
dev->address, cdp->bmAttributes,
selfpowered, cdp->bMaxPower * 2));
+
+ /* Check if we have enough power. */
#ifdef USB_DEBUG
if (dev->powersrc == NULL) {
DPRINTF(("usbd_set_config_index: No power source?\n"));
@@ -631,6 +647,7 @@ usbd_set_config_index(dev, index, msg)
dev->power = power;
dev->self_powered = selfpowered;
+ /* Set the actual configuration value. */
DPRINTF(("usbd_set_config_index: set config %d\n",
cdp->bConfigurationValue));
err = usbd_set_config(dev, cdp->bConfigurationValue);
@@ -640,8 +657,8 @@ usbd_set_config_index(dev, index, msg)
cdp->bConfigurationValue, usbd_errstr(err)));
goto bad;
}
- DPRINTF(("usbd_set_config_index: setting new config %d\n",
- cdp->bConfigurationValue));
+
+ /* Allocate and fill interface data. */
nifc = cdp->bNumInterface;
dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
M_USB, M_NOWAIT);
@@ -764,8 +781,8 @@ usbd_probe_and_attach(parent, dev, port, addr)
#endif
uaa.device = dev;
- uaa.iface = 0;
- uaa.ifaces = 0;
+ uaa.iface = NULL;
+ uaa.ifaces = NULL;
uaa.nifaces = 0;
uaa.usegeneric = 0;
uaa.port = port;
@@ -869,7 +886,7 @@ usbd_probe_and_attach(parent, dev, port, addr)
DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
/* Finally try the generic driver. */
- uaa.iface = 0;
+ uaa.iface = NULL;
uaa.usegeneric = 1;
uaa.configno = UHUB_UNK_CONFIGURATION;
uaa.ifaceno = UHUB_UNK_INTERFACE;
@@ -920,8 +937,8 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
int addr;
int i;
- DPRINTF(("usbd_new_device bus=%p depth=%d lowspeed=%d\n",
- bus, depth, lowspeed));
+ DPRINTF(("usbd_new_device bus=%p port=%d depth=%d lowspeed=%d\n",
+ bus, port, depth, lowspeed));
addr = usbd_getnewaddr(bus);
if (addr < 0) {
printf("%s: No free USB addresses, new device ignored.\n",
@@ -956,7 +973,7 @@ usbd_new_device(parent, bus, depth, lowspeed, port, up)
dev->langid = USBD_NOLANG;
dev->cookie.cookie = ++usb_cookie_no;
- /* Establish the the default pipe. */
+ /* Establish the default pipe. */
err = usbd_setup_pipe(dev, 0, &dev->def_ep, USBD_DEFAULT_INTERVAL,
&dev->default_pipe);
if (err) {
@@ -1131,7 +1148,16 @@ usbd_submatch(parent, match, aux)
#endif
struct usb_attach_arg *uaa = aux;
- if ((uaa->port != 0 &&
+ DPRINTFN(5,("usbd_submatch port=%d,%d configno=%d,%d "
+ "ifaceno=%d,%d vendor=%d,%d product=%d,%d release=%d,%d\n",
+ uaa->port, cf->uhubcf_port,
+ uaa->configno, cf->uhubcf_configuration,
+ uaa->ifaceno, cf->uhubcf_interface,
+ uaa->vendor, cf->uhubcf_vendor,
+ uaa->product, cf->uhubcf_product,
+ uaa->release, cf->uhubcf_release));
+ if (uaa->port != 0 && /* root hub has port 0, it should match */
+ ((uaa->port != 0 &&
cf->uhubcf_port != UHUB_UNK_PORT &&
cf->uhubcf_port != uaa->port) ||
(uaa->configno != UHUB_UNK_CONFIGURATION &&
@@ -1150,6 +1176,7 @@ usbd_submatch(parent, match, aux)
cf->uhubcf_release != UHUB_UNK_RELEASE &&
cf->uhubcf_release != uaa->release)
)
+ )
return 0;
return ((*cf->cf_attach->ca_match)(parent, cf, aux));
}
OpenPOWER on IntegriCloud