summaryrefslogtreecommitdiff
path: root/sys/dev/usb/usb_subr.c
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2011-01-16 22:35:30 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2011-01-16 22:35:30 +0000
commitbf7dd43b0ff651c5b7ba593bceb215dc29ad45d7 (patch)
tree45e6e943d25ebc8148bddd5d6a8250fbb43a6d85 /sys/dev/usb/usb_subr.c
parent3ea785dfac3b842c38d5b36eb3a32b8af8086460 (diff)
* instead of NULLing pointers to interface descriptors in the uaa, mark
interfaces as being claimed in the usbd_device's copy of the interface descriptors * allow ugen(4) to be attached if there are unused interfaces in a configuration that has had drivers attached * make ugen(4) aware that it may be sharing a device with (an)other driver(s), and if so: * do not let ugen(4) change the configuration * do not let ugen(4) access the already claimed interfaces discussed with deraadt and miod
Diffstat (limited to 'sys/dev/usb/usb_subr.c')
-rw-r--r--sys/dev/usb/usb_subr.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/sys/dev/usb/usb_subr.c b/sys/dev/usb/usb_subr.c
index 498c579b4db..b46b0649a6a 100644
--- a/sys/dev/usb/usb_subr.c
+++ b/sys/dev/usb/usb_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: usb_subr.c,v 1.78 2011/01/15 23:58:43 jakemsr Exp $ */
+/* $OpenBSD: usb_subr.c,v 1.79 2011/01/16 22:35:29 jakemsr Exp $ */
/* $NetBSD: usb_subr.c,v 1.103 2003/01/10 11:19:13 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
@@ -777,7 +777,7 @@ usbd_set_config_index(usbd_device_handle dev, int index, int msg)
/* Allocate and fill interface data. */
nifc = cdp->bNumInterface;
dev->ifaces = malloc(nifc * sizeof(struct usbd_interface),
- M_USB, M_NOWAIT);
+ M_USB, M_NOWAIT | M_ZERO);
if (dev->ifaces == NULL) {
err = USBD_NOMEM;
goto bad;
@@ -859,14 +859,13 @@ usbd_getnewaddr(usbd_bus_handle bus)
return (-1);
}
-
usbd_status
usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
int addr)
{
struct usb_attach_arg uaa;
usb_device_descriptor_t *dd = &dev->ddesc;
- int found, i, confi, nifaces, len;
+ int i, confi, nifaces, len;
usbd_status err;
struct device *dv;
usbd_interface_handle *ifaces;
@@ -895,8 +894,8 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
err = USBD_NOMEM;
goto fail;
}
- dev->subdevs[0] = dv;
- dev->subdevs[1] = 0;
+ dev->subdevs[dev->ndevs++] = dv;
+ dev->subdevs[dev->ndevs] = 0;
err = USBD_NORMAL_COMPLETION;
goto fail;
}
@@ -934,7 +933,9 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
ifaces[i] = &dev->ifaces[i];
uaa.ifaces = ifaces;
uaa.nifaces = nifaces;
- len = (nifaces+1) * sizeof dv;
+
+ /* add 1 for possible ugen and 1 for NULL terminator */
+ len = (nifaces + 2) * sizeof dv;
dev->subdevs = malloc(len, M_USB, M_NOWAIT | M_ZERO);
if (dev->subdevs == NULL) {
free(ifaces, M_USB);
@@ -942,25 +943,31 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
goto fail;
}
- found = 0;
for (i = 0; i < nifaces; i++) {
- if (ifaces[i] == NULL)
- continue; /* interface already claimed */
+ if (usbd_iface_claimed(dev, i))
+ continue;
uaa.iface = ifaces[i];
uaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
dv = config_found_sm(parent, &uaa, usbd_print,
usbd_submatch);
-
if (dv != NULL) {
- dev->subdevs[found++] = dv;
- ifaces[i] = NULL; /* consumed */
+ dev->subdevs[dev->ndevs++] = dv;
+ usbd_claim_iface(dev, i);
}
}
free(ifaces, M_USB);
- if (found != 0) {
- err = USBD_NORMAL_COMPLETION;
- goto fail;
+
+ if (dev->ndevs > 0) {
+ for (i = 0; i < nifaces; i++) {
+ if (!usbd_iface_claimed(dev, i))
+ break;
+ }
+ if (i < nifaces)
+ goto generic;
+ else
+ goto fail;
}
+
free(dev->subdevs, M_USB);
dev->subdevs = 0;
}
@@ -971,20 +978,24 @@ usbd_probe_and_attach(struct device *parent, usbd_device_handle dev, int port,
DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
+generic:
/* Finally try the generic driver. */
uaa.iface = NULL;
uaa.usegeneric = 1;
- uaa.configno = UHUB_UNK_CONFIGURATION;
+ uaa.configno = dev->ndevs == 0 ? UHUB_UNK_CONFIGURATION :
+ dev->cdesc->bConfigurationValue;
uaa.ifaceno = UHUB_UNK_INTERFACE;
dv = config_found_sm(parent, &uaa, usbd_print, usbd_submatch);
if (dv != NULL) {
- dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0) {
- err = USBD_NOMEM;
- goto fail;
+ if (dev->ndevs == 0) {
+ dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
+ if (dev->subdevs == NULL) {
+ err = USBD_NOMEM;
+ goto fail;
+ }
}
- dev->subdevs[0] = dv;
- dev->subdevs[1] = 0;
+ dev->subdevs[dev->ndevs++] = dv;
+ dev->subdevs[dev->ndevs] = 0;
err = USBD_NORMAL_COMPLETION;
goto fail;
}