summaryrefslogtreecommitdiff
path: root/sys/dev/usb/ugen.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/ugen.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/ugen.c')
-rw-r--r--sys/dev/usb/ugen.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c
index 457b77cd894..8261bbe9c2d 100644
--- a/sys/dev/usb/ugen.c
+++ b/sys/dev/usb/ugen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ugen.c,v 1.62 2010/09/24 08:33:59 yuo Exp $ */
+/* $OpenBSD: ugen.c,v 1.63 2011/01/16 22:35:29 jakemsr Exp $ */
/* $NetBSD: ugen.c,v 1.63 2002/11/26 18:49:48 christos Exp $ */
/* $FreeBSD: src/sys/dev/usb/ugen.c,v 1.26 1999/11/17 22:33:41 n_hibma Exp $ */
@@ -103,6 +103,7 @@ struct ugen_softc {
int sc_refcnt;
u_char sc_dying;
+ u_char sc_secondary;
};
void ugenintr(usbd_xfer_handle xfer, usbd_private_handle addr,
@@ -166,13 +167,18 @@ ugen_attach(struct device *parent, struct device *self, void *aux)
sc->sc_udev = udev = uaa->device;
- /* First set configuration index 0, the default one for ugen. */
- err = usbd_set_config_index(udev, 0, 0);
- if (err) {
- printf("%s: setting configuration index 0 failed\n",
- sc->sc_dev.dv_xname);
- sc->sc_dying = 1;
- return;
+ if (usbd_get_devcnt(udev) > 0)
+ sc->sc_secondary = 1;
+
+ if (!sc->sc_secondary) {
+ /* First set configuration index 0, the default one for ugen. */
+ err = usbd_set_config_index(udev, 0, 0);
+ if (err) {
+ printf("%s: setting configuration index 0 failed\n",
+ sc->sc_dev.dv_xname);
+ sc->sc_dying = 1;
+ return;
+ }
}
conf = usbd_get_config_descriptor(udev)->bConfigurationValue;
@@ -220,9 +226,15 @@ ugen_set_config(struct ugen_softc *sc, int configno)
/* Avoid setting the current value. */
cdesc = usbd_get_config_descriptor(dev);
if (!cdesc || cdesc->bConfigurationValue != configno) {
- err = usbd_set_config_no(dev, configno, 1);
- if (err)
- return (err);
+ if (sc->sc_secondary) {
+ printf("%s: secondary, not changing config to %d\n",
+ __func__, configno);
+ return (USBD_IN_USE);
+ } else {
+ err = usbd_set_config_no(dev, configno, 1);
+ if (err)
+ return (err);
+ }
}
err = usbd_interface_count(dev, &niface);
@@ -231,6 +243,11 @@ ugen_set_config(struct ugen_softc *sc, int configno)
memset(sc->sc_endpoints, 0, sizeof sc->sc_endpoints);
for (ifaceno = 0; ifaceno < niface; ifaceno++) {
DPRINTFN(1,("ugen_set_config: ifaceno %d\n", ifaceno));
+ if (usbd_iface_claimed(sc->sc_udev, ifaceno)) {
+ DPRINTF(("%s: iface %d not available\n", __func__,
+ ifaceno));
+ continue;
+ }
err = usbd_device2interface_handle(dev, ifaceno, &iface);
if (err)
return (err);
@@ -897,7 +914,8 @@ ugen_set_interface(struct ugen_softc *sc, int ifaceidx, int altno)
err = usbd_interface_count(sc->sc_udev, &niface);
if (err)
return (err);
- if (ifaceidx < 0 || ifaceidx >= niface)
+ if (ifaceidx < 0 || ifaceidx >= niface ||
+ usbd_iface_claimed(sc->sc_udev, ifaceidx))
return (USBD_INVAL);
err = usbd_device2interface_handle(sc->sc_udev, ifaceidx, &iface);