diff options
author | n_hibma <n_hibma@FreeBSD.org> | 2000-08-13 18:39:24 +0000 |
---|---|---|
committer | n_hibma <n_hibma@FreeBSD.org> | 2000-08-13 18:39:24 +0000 |
commit | 17d5aba6f2ac45c2fc102114f1a02a62a94c6bbe (patch) | |
tree | 6000c938bb7a8dfddd2c1d8371e6a377a6757bda /sys/dev/usb/usb_subr.c | |
parent | 2424c7393a2a912ab1e3678c643b613766634171 (diff) | |
download | FreeBSD-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.c | 71 |
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)); } |