diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2011-01-16 22:35:30 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2011-01-16 22:35:30 +0000 |
commit | bf7dd43b0ff651c5b7ba593bceb215dc29ad45d7 (patch) | |
tree | 45e6e943d25ebc8148bddd5d6a8250fbb43a6d85 /sys/dev/usb/ugen.c | |
parent | 3ea785dfac3b842c38d5b36eb3a32b8af8086460 (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.c | 42 |
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); |