tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
USB autoconf rework, updated patches
Here are the patches again, updated for -current after the last
device_t etc cleanups.
All drivers which don't attach to the whole device but to
interfaces use a "udev" helper device now, so a kernel
config file should include:
udev* at uhub? port ?
uhidev* at udev?
etc -- the kernel config(8) program will complain where
necessary.
I hope that this framework will make loadable USB
drivers more straightforward, and that it will allow
to access single interfaces of a multifunction device
to be accessed by the generic "ugen" driver.
Please review and comment.
best regards
Matthias
-------------------------------------------------------------------
-------------------------------------------------------------------
Forschungszentrum Juelich GmbH
52425 Juelich
Sitz der Gesellschaft: Juelich
Eingetragen im Handelsregister des Amtsgerichts Dueren Nr. HR B 3498
Vorsitzende des Aufsichtsrats: MinDir'in Baerbel Brumme-Bothe
Geschaeftsfuehrung: Prof. Dr. Achim Bachem (Vorsitzender),
Dr. Ulrich Krafft (stellv. Vorsitzender), Prof. Dr. Harald Bolt,
Dr. Sebastian M. Schmidt
-------------------------------------------------------------------
-------------------------------------------------------------------
#
#
# add_file "sys/dev/usb/udev.c"
# content [23147124ea5b88485292bd5b1cc2f78850e76ed2]
#
# add_file "sys/dev/usb/udev_ugen.c"
# content [6d9db30d8029c4610d4e201e8f6953a208aab6f4]
#
# add_file "sys/dev/usb/udevvar.h"
# content [74d091553b93202dd54c25e08fc7c3a827a6d9ed]
#
# add_file "sys/dev/usb/usbfunction.h"
# content [2bd3396fefb32af2b2dec61f26237f8ecef48c05]
#
# add_file "sys/dev/usb/usbiadreg.h"
# content [9bf158738f9406942171989748462e30ca213ae4]
#
# patch "sys/dev/usb/files.usb"
# from [27a8673fba807146c4a3084b06ca2ecb34a34a5b]
# to [2655b0ffc9f928e4d090e67a8b79f2c70998ca10]
#
# patch "sys/dev/usb/uaudio.c"
# from [5abb92f27d812ca7874ece4b315a30fba814f05f]
# to [bb1a24d95a6da0476ebaec20db49714deb060e43]
#
# patch "sys/dev/usb/ugen.c"
# from [886fadd3c361883d19a0f9eaa47bf36459447da8]
# to [cc9fc12f9de117bc531e196d4f7413cc6340c041]
#
# patch "sys/dev/usb/uhub.c"
# from [abf3f4739bd6526ebaaff9a74f30930463409368]
# to [3a52f88cc8b7762f0a563b90813cd6d2c0ba9699]
#
# patch "sys/dev/usb/usb.c"
# from [baec30d7b668d7cf3bbd524c02dfb3cbf419c4a7]
# to [7f1eec27c3342ca4ae28105ca8ccf80238b97ade]
#
# patch "sys/dev/usb/usb.h"
# from [572dc8d893c531cf62045994fcde0d59b80935c7]
# to [9fc7925ca6786f49e560b52787e6069152d32d59]
#
# patch "sys/dev/usb/usb_subr.c"
# from [1fa1e08204f9bee75e9c9c02cde89c00af1f234f]
# to [5185dec78577f35c713201070097a20f32ef636f]
#
# patch "sys/dev/usb/usbdi.h"
# from [be5af7b140f06fc59cf93bac23beb29b4375bb22]
# to [5895a90b548c10073af09eb416eda0788ceb5bd0]
#
# patch "sys/dev/usb/usbdivar.h"
# from [6b9a9d672cd3d7efddc7fba805ba08420ea69f75]
# to [72189560a2de33ba34088cb2a540f66c3fed2127]
#
============================================================
--- sys/dev/usb/udev.c 23147124ea5b88485292bd5b1cc2f78850e76ed2
+++ sys/dev/usb/udev.c 23147124ea5b88485292bd5b1cc2f78850e76ed2
@@ -0,0 +1,455 @@
+/* $NetBSD$ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <sys/device.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <sys/bus.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usbiadreg.h>
+#include <dev/usb/usbfunction.h>
+#include <dev/usb/udevvar.h>
+
+static int udev_match(device_t, struct cfdata *, void *);
+static void udev_attach(device_t, device_t, void *);
+static int udev_detach(device_t, int);
+static void udev_childdetached(device_t, device_t);
+static int ucmp_ifprint(void *, const char *);
+static int ucmp_fifprint(void *, const char *);
+
+CFATTACH_DECL2_NEW(udev, sizeof(struct udev_softc),
+ udev_match, udev_attach, udev_detach,
+ NULL,
+ NULL, udev_childdetached);
+
+static int
+udev_match(device_t parent, struct cfdata *match, void *aux)
+{
+ /* struct usb_attach_arg *uaa = aux; */
+
+ /* match all at a priority lower than device specific drivers */
+ return 1;
+}
+
+/*
+ * The historical way of attaching drivers which attach to an interface.
+ * This does not handle drivers well which access multiple interfaces.
+ * Needs to be kept until all drivers are converted.
+ */
+static void
+udev_compat_attachinterfaces(struct udev_softc *sc)
+{
+ usbd_device_handle dev = sc->sc_udev;
+ usb_device_descriptor_t *dd = &dev->ddesc;
+ struct usbif_attach_arg uiaa;
+ int locs[USBIFIFCF_NLOCS];
+ int i;
+ device_t dv;
+
+ KASSERT(sc->sc_configlock);
+
+ uiaa.device = dev;
+ uiaa.port = sc->sc_port;
+ uiaa.vendor = UGETW(dd->idVendor);
+ uiaa.product = UGETW(dd->idProduct);
+ uiaa.release = UGETW(dd->bcdDevice);
+ uiaa.configno = dev->cdesc->bConfigurationValue;
+ uiaa.nifaces = sc->sc_nifaces;
+ uiaa.ifaces = sc->sc_ifaces;
+ locs[USBIFIFCF_PORT] = uiaa.port;
+ locs[USBIFIFCF_VENDOR] = uiaa.vendor;
+ locs[USBIFIFCF_PRODUCT] = uiaa.product;
+ locs[USBIFIFCF_RELEASE] = uiaa.release;
+ locs[USBIFIFCF_CONFIGURATION] = uiaa.configno;
+
+ for (i = 0; i < sc->sc_nifaces; i++) {
+ if (sc->sc_subdevs[i])
+ continue; /* interface already claimed */
+ uiaa.iface = sc->sc_ifaces[i];
+ uiaa.class = sc->sc_ifaces[i]->idesc->bInterfaceClass;
+ uiaa.subclass = sc->sc_ifaces[i]->idesc->bInterfaceSubClass;
+ uiaa.proto = sc->sc_ifaces[i]->idesc->bInterfaceProtocol;
+ /* ifaceno should be i, else we have a strange device */
+ uiaa.ifaceno = sc->sc_ifaces[i]->idesc->bInterfaceNumber;
+ locs[USBIFIFCF_INTERFACE] = uiaa.ifaceno;
+ dv = config_found_sm_loc(sc->sc_dev, "usbifif", locs, &uiaa,
+ ucmp_ifprint, config_stdsubmatch);
+ if (dv) {
+ sc->sc_subdevs[i] = dv;
+ sc->sc_nifaces_claimed++;
+ }
+ }
+}
+
+static int
+ucmp_ifprint(void *aux, const char *pnp)
+{
+ struct usbif_attach_arg *uaa = aux;
+
+ if (pnp)
+ return (QUIET);
+ aprint_normal(" configuration %d interface %d",
+ uaa->configno, uaa->ifaceno);
+ return (UNCONF);
+}
+
+static void
+udev_attachinterfaces(struct udev_softc *sc)
+{
+ usbd_device_handle dev = sc->sc_udev;
+ struct usbfunction_attach_args ufaa;
+ int locs[USBFIFCF_NLOCS];
+ int i;
+ device_t dv;
+
+ KASSERT(sc->sc_configlock);
+
+ ufaa.device = dev;
+ ufaa.type = USBF_INTERFACE;
+
+ for (i = 0; i < sc->sc_nifaces; i++) {
+ if (sc->sc_subdevs[i])
+ continue; /* interface already claimed */
+ ufaa.ifaces = &sc->sc_ifaces[i];
+ ufaa.nifaces = 1;
+ ufaa.class = sc->sc_ifaces[i]->idesc->bInterfaceClass;
+ ufaa.subclass = sc->sc_ifaces[i]->idesc->bInterfaceSubClass;
+ ufaa.proto = sc->sc_ifaces[i]->idesc->bInterfaceProtocol;
+ /* ifaceno should be i, else we have a strange device */
+ ufaa.ifaceno = sc->sc_ifaces[i]->idesc->bInterfaceNumber;
+ locs[USBFIFCF_INTERFACE] = ufaa.ifaceno;
+ dv = config_found_sm_loc(sc->sc_dev, "usbfif", locs, &ufaa,
+ ucmp_fifprint, config_stdsubmatch);
+ if (dv) {
+ sc->sc_subdevs[i] = dv;
+ sc->sc_nifaces_claimed++;
+ }
+ }
+}
+
+/*
+ * attach by IADs
+ */
+static void
+udev_scaniads(struct udev_softc *sc)
+{
+ usbd_device_handle dev = sc->sc_udev;
+ usbd_desc_iter_t di;
+ const usb_descriptor_t *d;
+ const usb_interface_association_descriptor_t *iad;
+ struct usbfunction_attach_args ufaa;
+ usbd_interface_handle *ifs;
+ int ifbusy, i;
+ int locs[USBFIFCF_NLOCS];
+ device_t dv;
+
+ KASSERT(sc->sc_configlock);
+
+ usb_desc_iter_init(dev, &di);
+ while ((d = usb_desc_iter_next(&di))) {
+ if (d->bDescriptorType != UDESC_INTERFACE_ASSOCIATION)
+ continue;
+ iad = (const usb_interface_association_descriptor_t *)d;
+
+ if (iad->bFirstInterface + iad->bInterfaceCount
+ > sc->sc_nifaces) {
+ printf("%s: invalid iad\n", device_xname(sc->sc_dev));
+ return;
+ }
+
+ ifbusy = 0;
+ for (i = 0; i < iad->bInterfaceCount; i++) {
+ if (sc->sc_subdevs[iad->bFirstInterface + i]) {
+ ifbusy++;
+ break;
+ }
+ }
+ if (ifbusy)
+ continue;
+
+ ifs = malloc(iad->bInterfaceCount
+ * sizeof(usbd_interface_handle *),
+ M_USBDEV, M_NOWAIT);
+ if (!ifs)
+ return;
+ for (i = 0; i < iad->bInterfaceCount; i++)
+ ifs[i] = sc->sc_ifaces[iad->bFirstInterface + i];
+ ufaa.ifaces = ifs;
+ ufaa.nifaces = iad->bInterfaceCount;
+ ufaa.class = iad->bFunctionClass;
+ ufaa.subclass = iad->bFunctionSubClass;
+ ufaa.proto = iad->bFunctionProtocol;
+ ufaa.device = dev;
+ ufaa.ifaceno = iad->bFirstInterface;
+ ufaa.type = USBF_IAD;
+ locs[USBFIFCF_INTERFACE] = ufaa.ifaceno;
+ dv = config_found_sm_loc(sc->sc_dev, "usbfif", locs, &ufaa,
+ ucmp_fifprint, config_stdsubmatch);
+ if (dv) {
+ for (i = 0; i < iad->bInterfaceCount; i++)
+ sc->sc_subdevs[iad->bFirstInterface + i] = dv;
+ sc->sc_nifaces_claimed += iad->bInterfaceCount;
+ }
+ free(ifs, M_USBDEV);
+ }
+}
+
+/*
+ * handle audio devices without IADs: look for multiple audio interfaces
+ * (need at least one control and one streaming interface)
+ */
+static void
+udev_scanaudio(struct udev_softc *sc)
+{
+ usbd_device_handle dev = sc->sc_udev;
+ struct usbfunction_attach_args ufaa;
+ usbd_interface_handle *ifs;
+ int *ifacenrs;
+ int locs[USBFIFCF_NLOCS];
+ int naudioif, i, j;
+ device_t dv;
+
+ KASSERT(sc->sc_configlock);
+
+ naudioif = 0;
+ for (i = 0; i < sc->sc_nifaces; i++) {
+ if (sc->sc_subdevs[i])
+ continue; /* interface already claimed */
+ if (sc->sc_ifaces[i]->idesc->bInterfaceClass == UICLASS_AUDIO)
+ naudioif++;
+ }
+ if (naudioif < 2)
+ return;
+
+ ifs = malloc(naudioif * sizeof(usbd_interface_handle *),
+ M_USBDEV, M_NOWAIT);
+ if (!ifs)
+ return;
+ ifacenrs = malloc(naudioif * sizeof(int), M_USBDEV, M_NOWAIT);
+ if (!ifacenrs) {
+ free(ifs, M_USBDEV);
+ return;
+ }
+ j = 0;
+ for (i = 0; i < sc->sc_nifaces; i++) {
+ if (sc->sc_subdevs[i])
+ continue; /* interface already claimed */
+ if (sc->sc_ifaces[i]->idesc->bInterfaceClass == UICLASS_AUDIO) {
+ ifs[j] = sc->sc_ifaces[i];
+ ifacenrs[j] = i;
+ j++;
+ if (j == naudioif)
+ break;
+ }
+ }
+ if (j != naudioif) {
+ printf("udev_scanaudio: lost interface\n");
+ free(ifs, M_USBDEV);
+ return;
+ }
+
+ ufaa.device = dev;
+ ufaa.type = USBF_LEGACYAUDIO;
+ ufaa.class = UICLASS_AUDIO;
+ ufaa.subclass = 0;
+ ufaa.proto = 0;
+ ufaa.ifaces = ifs;
+ ufaa.nifaces = naudioif;
+ ufaa.ifaceno = ifacenrs[0];
+ locs[USBFIFCF_INTERFACE] = ufaa.ifaceno;
+ dv = config_found_sm_loc(sc->sc_dev, "usbfif", locs, &ufaa,
+ ucmp_fifprint, config_stdsubmatch);
+ if (dv) {
+ for (i = 0; i < naudioif; i++)
+ sc->sc_subdevs[ifacenrs[i]] = dv;
+ sc->sc_nifaces_claimed += naudioif;
+ }
+ free(ifs, M_USBDEV);
+ free(ifacenrs, M_USBDEV);
+}
+
+
+static int
+ucmp_fifprint(void *aux, const char *pnp)
+{
+ struct usbfunction_attach_args *uaa = aux;
+
+ if (pnp) {
+ if (uaa->type == USBF_IAD)
+ aprint_normal("IAD device (class=%d) at %s",
+ uaa->class, pnp);
+ else if (uaa->type == USBF_LEGACYAUDIO)
+ aprint_normal("legacy audio device at %s", pnp);
+ else
+ return (QUIET);
+ }
+ aprint_normal(" interface %d", uaa->ifaceno);
+ return (UNCONF);
+}
+
+static int
+udev_setconfig(struct udev_softc *sc, int configidx)
+{
+ usbd_device_handle dev = sc->sc_udev;
+ usbd_status err;
+ int nifaces, i;
+
+ if (sc->sc_configlock) {
+ if (configidx == dev->cdesc->iConfiguration)
+ return 0;
+ else
+ return EAGAIN;
+ }
+ sc->sc_configlock = 1;
+ KASSERT(sc->sc_nifaces_claimed == 0);
+
+ err = usbd_set_config_index(dev, configidx, 1);
+ if (err) {
+ printf("set config failed\n");
+ sc->sc_configlock = 0;
+ return EIO;
+ }
+
+ nifaces = dev->cdesc->bNumInterface;
+ sc->sc_ifaces = malloc(nifaces * sizeof(usbd_interface_handle),
+ M_USBDEV, M_NOWAIT);
+ if (!sc->sc_ifaces) {
+ sc->sc_configlock = 0;
+ return ENOMEM;
+ }
+ for (i = 0; i < nifaces; i++)
+ sc->sc_ifaces[i] = &dev->ifaces[i];
+ sc->sc_nifaces = nifaces;
+
+ sc->sc_subdevs = malloc(nifaces * sizeof(device_t),
+ M_USBDEV, M_NOWAIT | M_ZERO);
+ if (!sc->sc_subdevs) {
+ free(sc->sc_ifaces, M_USBDEV);
+ sc->sc_ifaces = 0;
+ sc->sc_configlock = 0;
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+static void
+udev_freeconfig(struct udev_softc *sc)
+{
+
+ KASSERT(sc->sc_nifaces_claimed == 0);
+ KASSERT(sc->sc_configlock);
+ KASSERT(sc->sc_subdevs && sc->sc_ifaces);
+
+ free(sc->sc_ifaces, M_USBDEV);
+ sc->sc_ifaces = 0;
+ free(sc->sc_subdevs, M_USBDEV);
+ sc->sc_subdevs = 0;
+
+ sc->sc_configlock = 0;
+}
+
+static void
+udev_attach(device_t parent, device_t self, void *aux)
+{
+ struct udev_softc *sc = device_private(self);
+ struct usb_attach_arg *uaa = aux;
+ char *devinfop;
+ int res, confi;
+ usbd_device_handle dev = uaa->device;
+ usb_device_descriptor_t *dd = &dev->ddesc;
+
+ sc->sc_dev = self;
+ sc->sc_udev = uaa->device;
+ sc->sc_port = uaa->port;
+
+ devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
+ printf(": %s\n", devinfop);
+ usbd_devinfo_free(devinfop);
+
+ if (!pmf_device_register(self, NULL, NULL))
+ aprint_error_dev(self, "couldn't establish power handler\n");
+
+ if ((uaa->class == UDCLASS_MISC) &&
+ (uaa->subclass == UDSUBCLASS_COMMON) &&
+ (uaa->proto == UDPROTO_IAD)) {
+ res = udev_setconfig(sc, 0);
+ if (!res) {
+ udev_scaniads(sc);
+ if (!sc->sc_nifaces_claimed)
+ udev_freeconfig(sc);
+ }
+ }
+
+ for (confi = 0; confi < dd->bNumConfigurations; confi++) {
+ res = udev_setconfig(sc, confi);
+ if (res) {
+ /*
+ * should catch the case that devices were attached
+ * with other configurations
+ */
+ continue;
+ }
+
+ udev_scanaudio(sc);
+ udev_attachinterfaces(sc);
+ udev_compat_attachinterfaces(sc);
+
+ if (sc->sc_nifaces_claimed != 0) {
+ /*
+ * no point in trying other configs, we are not allowed
+ * to switch anyway
+ */
+ break;
+ } else
+ udev_freeconfig(sc);
+ }
+
+ KASSERT(sc->sc_configlock == (sc->sc_nifaces_claimed != 0));
+
+ udev_ugen_attachcheck(sc);
+}
+
+static int
+udev_detach(device_t self, int flags)
+{
+ struct udev_softc *sc = device_private(self);
+ int res;
+
+ res = config_detach_children(self, flags);
+ if (res)
+ return res;
+
+ KASSERT(sc->sc_nifaces_claimed == 0);
+ KASSERT(!sc->sc_configlock);
+ KASSERT(!sc->sc_subdevs && !sc->sc_ifaces);
+ return 0;
+}
+
+static void
+udev_childdetached(device_t self, device_t dev)
+{
+ struct udev_softc *sc = device_private(self);
+ int i;
+
+ udev_ugen_detachcheck(sc, dev);
+
+ if (sc->sc_configlock) {
+ for (i = 0; i < sc->sc_nifaces; i++) {
+ if (sc->sc_subdevs[i] == dev) {
+ sc->sc_subdevs[i] = 0;
+ sc->sc_nifaces_claimed--;
+ }
+ }
+ if (!sc->sc_nifaces_claimed)
+ udev_freeconfig(sc);
+ }
+
+#if 0 /* XXX allow interfaces now free, check not dying */
+ udev_ugen_attachcheck(sc);
+#endif
+}
============================================================
--- sys/dev/usb/udev_ugen.c 6d9db30d8029c4610d4e201e8f6953a208aab6f4
+++ sys/dev/usb/udev_ugen.c 6d9db30d8029c4610d4e201e8f6953a208aab6f4
@@ -0,0 +1,55 @@
+/* $NetBSD$ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <sys/bus.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/udevvar.h>
+
+/*
+ * XXX compatibility for now: only attach if no interface claimed,
+ * and keep attach args from usbdevif
+ */
+
+static int
+ugen_print(void *aux, const char *pnp)
+{
+
+ return (UNCONF);
+}
+
+void
+udev_ugen_attachcheck(struct udev_softc *sc)
+{
+ usbd_device_handle udev;
+ usb_device_descriptor_t *dd;
+ struct usb_attach_arg uaa;
+
+ if (sc->sc_ugendev || sc->sc_nifaces_claimed)
+ return;
+
+ udev = sc->sc_udev;
+ dd = &udev->ddesc;
+ uaa.device = udev;
+ uaa.port = sc->sc_port;
+ uaa.vendor = UGETW(dd->idVendor);
+ uaa.product = UGETW(dd->idProduct);
+ uaa.release = UGETW(dd->bcdDevice);
+ uaa.class = dd->bDeviceClass;
+ uaa.subclass = dd->bDeviceSubClass;
+ uaa.proto = dd->bDeviceProtocol;
+
+ sc->sc_ugendev = config_found_sm_loc(sc->sc_dev, "usbgenif", NULL,
+ &uaa, ugen_print, NULL);
+}
+
+void
+udev_ugen_detachcheck(struct udev_softc *sc, device_t child)
+{
+
+ if (child == sc->sc_ugendev)
+ sc->sc_ugendev = 0;
+}
============================================================
--- sys/dev/usb/udevvar.h 74d091553b93202dd54c25e08fc7c3a827a6d9ed
+++ sys/dev/usb/udevvar.h 74d091553b93202dd54c25e08fc7c3a827a6d9ed
@@ -0,0 +1,19 @@
+/* $NetBSD$ */
+
+struct udev_softc {
+ device_t sc_dev;
+ usbd_device_handle sc_udev;
+ int sc_port; /* XXX only for historical attach arg */
+
+ int sc_configlock; /* set config disallowed */
+
+ int sc_nifaces; /* array length for following two */
+ usbd_interface_handle *sc_ifaces;
+ device_t *sc_subdevs; /* owner per interface */
+ int sc_nifaces_claimed;
+
+ device_t sc_ugendev;
+};
+
+void udev_ugen_attachcheck(struct udev_softc *);
+void udev_ugen_detachcheck(struct udev_softc *, device_t);
============================================================
--- sys/dev/usb/usbfunction.h 2bd3396fefb32af2b2dec61f26237f8ecef48c05
+++ sys/dev/usb/usbfunction.h 2bd3396fefb32af2b2dec61f26237f8ecef48c05
@@ -0,0 +1,15 @@
+
+struct usbfunction_attach_args {
+ usbd_device_handle device;
+ int type;
+#define USBF_INTERFACE 1 /* just a single interface */
+#define USBF_IAD 2 /* interface group described by an IAD */
+#define USBF_LEGACYAUDIO 3 /* group of audio interfaces */
+#define USBF_CDC 4 /* CDC UFC (not implemented yet) */
+
+ int class, subclass, proto;
+
+ usbd_interface_handle *ifaces;
+ int nifaces;
+ int ifaceno; /* first one, as locator */
+};
============================================================
--- sys/dev/usb/usbiadreg.h 9bf158738f9406942171989748462e30ca213ae4
+++ sys/dev/usb/usbiadreg.h 9bf158738f9406942171989748462e30ca213ae4
@@ -0,0 +1,14 @@
+/* $NetBSD$ */
+
+typedef struct {
+ uByte bLength;
+ uByte bDescriptorType;
+ uByte bFirstInterface;
+ uByte bInterfaceCount;
+ uByte bFunctionClass;
+ uByte bFunctionSubClass;
+ uByte bFunctionProtocol;
+ uByte iFunction;
+} UPACKED usb_interface_association_descriptor_t;
+
+#define UDESC_INTERFACE_ASSOCIATION 11
============================================================
--- sys/dev/usb/files.usb 27a8673fba807146c4a3084b06ca2ecb34a34a5b
+++ sys/dev/usb/files.usb 2655b0ffc9f928e4d090e67a8b79f2c70998ca10
@@ -10,6 +10,8 @@ define usbifif { [port = -1], [configura
[vendor = -1], [product = -1], [release = -1] }
define usbifif { [port = -1], [configuration = -1], [interface = -1],
[vendor = -1], [product = -1], [release = -1] }
+define usbfif { [interface = -1] }
+define usbgenif { }
device usb: usbdevif
attach usb at usbus
@@ -21,10 +23,15 @@ file dev/usb/usb_quirks.c usb
file dev/usb/usb_quirks.c usb
# Hub driver
-device uhub: usbdevif, usbifif
+device uhub: usbdevif
attach uhub at usbdevif
file dev/usb/uhub.c usb
+device udev: usbfif, usbifif, usbgenif
+attach udev at usbdevif
+file dev/usb/udev.c udev
+file dev/usb/udev_ugen.c udev
+
# Modem and com serial port "bus"
define ucombus {[ portno = -1 ]}
@@ -34,7 +41,7 @@ device uaudio: audiobus, auconv, mulaw,
# Audio devices
device uaudio: audiobus, auconv, mulaw, aurateconv
-attach uaudio at usbifif
+attach uaudio at usbfif
file dev/usb/uaudio.c uaudio
# MIDI devices
@@ -52,8 +59,8 @@ device ugen
# Generic devices
defflag UGEN_BULK_RA_WB
device ugen
-attach ugen at usbdevif
-file dev/usb/ugen.c ugen needs-flag
+attach ugen at usbgenif
+file dev/usb/ugen.c ugen
# HID
============================================================
--- sys/dev/usb/uaudio.c 5abb92f27d812ca7874ece4b315a30fba814f05f
+++ sys/dev/usb/uaudio.c bb1a24d95a6da0476ebaec20db49714deb060e43
@@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: uaudio.c,v 1
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include <dev/usb/usb_quirks.h>
+#include <dev/usb/usbfunction.h>
#include <dev/usb/uaudioreg.h>
@@ -162,7 +163,6 @@ struct uaudio_softc {
USBBASEDEVICE sc_dev; /* base device */
usbd_device_handle sc_udev; /* USB device */
int sc_ac_iface; /* Audio Control interface */
- usbd_interface_handle sc_ac_ifaceh;
struct chan sc_playchan; /* play channel */
struct chan sc_recchan; /* record channel */
int sc_nullalt;
@@ -224,9 +224,9 @@ Static usbd_status uaudio_identify_ac
#endif
Static usbd_status uaudio_identify_ac
- (struct uaudio_softc *, const usb_config_descriptor_t *);
+ (struct uaudio_softc *, const usb_config_descriptor_t *, int);
Static usbd_status uaudio_identify_as
- (struct uaudio_softc *, const usb_config_descriptor_t *);
+ (struct uaudio_softc *, const usb_config_descriptor_t *, int);
Static usbd_status uaudio_process_as
(struct uaudio_softc *, const char *, int *, int,
const usb_interface_descriptor_t *);
@@ -272,7 +272,8 @@ Static usbd_status uaudio_identify
Static struct terminal_list *uaudio_io_terminaltype
(int, struct io_terminal *, int);
Static usbd_status uaudio_identify
- (struct uaudio_softc *, const usb_config_descriptor_t *);
+ (struct uaudio_softc *, const usb_config_descriptor_t *,
+ usbd_interface_handle *, int);
Static int uaudio_signext(int, int);
Static int uaudio_value2bsd(struct mixerctl *, int);
@@ -376,11 +377,9 @@ USB_MATCH(uaudio)
USB_MATCH(uaudio)
{
- USB_IFMATCH_START(uaudio, uaa);
+ struct usbfunction_attach_args *uaa = aux;
- /* Trigger on the control interface. */
if (uaa->class != UICLASS_AUDIO ||
- uaa->subclass != UISUBCLASS_AUDIOCONTROL ||
(usbd_get_quirks(uaa->device)->uq_flags & UQ_BAD_AUDIO))
return UMATCH_NONE;
@@ -389,7 +388,8 @@ USB_ATTACH(uaudio)
USB_ATTACH(uaudio)
{
- USB_IFATTACH_START(uaudio, sc, uaa);
+ struct uaudio_softc *sc = (struct uaudio_softc *)self;
+ struct usbfunction_attach_args *uaa = aux;
usb_interface_descriptor_t *id;
usb_config_descriptor_t *cdesc;
char *devinfop;
@@ -409,14 +409,13 @@ USB_ATTACH(uaudio)
USB_ATTACH_ERROR_RETURN;
}
- err = uaudio_identify(sc, cdesc);
+ err = uaudio_identify(sc, cdesc, uaa->ifaces, uaa->nifaces);
if (err) {
printf("%s: audio descriptors make no sense, error=%d\n",
USBDEVNAME(sc->sc_dev), err);
USB_ATTACH_ERROR_RETURN;
}
- sc->sc_ac_ifaceh = uaa->iface;
/* Pick up the AS interface. */
for (i = 0; i < uaa->nifaces; i++) {
if (uaa->ifaces[i] == NULL)
@@ -543,7 +542,7 @@ Static const usb_interface_descriptor_t
}
Static const usb_interface_descriptor_t *
-uaudio_find_iface(const char *tbuf, int size, int *offsp, int subtype)
+uaudio_find_iface(const char *tbuf, int size, int *offsp, int number)
{
const usb_interface_descriptor_t *d;
@@ -552,7 +551,7 @@ uaudio_find_iface(const char *tbuf, int
*offsp += d->bLength;
if (d->bDescriptorType == UDESC_INTERFACE &&
d->bInterfaceClass == UICLASS_AUDIO &&
- d->bInterfaceSubClass == subtype)
+ d->bInterfaceNumber == number)
return d;
}
return NULL;
@@ -1487,14 +1486,29 @@ Static usbd_status
}
Static usbd_status
-uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc)
+uaudio_identify(struct uaudio_softc *sc, const usb_config_descriptor_t *cdesc,
+ usbd_interface_handle *ifaces, int nifaces)
{
+ int i;
+ usb_interface_descriptor_t *d;
usbd_status err;
- err = uaudio_identify_ac(sc, cdesc);
- if (err)
- return err;
- return uaudio_identify_as(sc, cdesc);
+ for (i = 0; i < nifaces; i++) {
+ d = usbd_get_interface_descriptor(ifaces[i]);
+ if (d->bInterfaceSubClass == UISUBCLASS_AUDIOCONTROL) {
+ err = uaudio_identify_ac(sc, cdesc,
+ d->bInterfaceNumber);
+ if (err)
+ return err;
+ }
+ }
+ for (i = 0; i < nifaces; i++) {
+ d = usbd_get_interface_descriptor(ifaces[i]);
+ if (d->bInterfaceSubClass == UISUBCLASS_AUDIOSTREAM)
+ return uaudio_identify_as(sc, cdesc,
+ d->bInterfaceNumber);
+ }
+ return USBD_INVAL;
}
Static void
@@ -1737,7 +1751,8 @@ uaudio_identify_as(struct uaudio_softc *
Static usbd_status
uaudio_identify_as(struct uaudio_softc *sc,
- const usb_config_descriptor_t *cdesc)
+ const usb_config_descriptor_t *cdesc,
+ int ifaceno)
{
const usb_interface_descriptor_t *id;
const char *tbuf;
@@ -1751,7 +1766,7 @@ uaudio_identify_as(struct uaudio_softc *
/* Locate the AudioStreaming interface descriptor. */
offs = 0;
- id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOSTREAM);
+ id = uaudio_find_iface(tbuf, size, &offs, ifaceno);
if (id == NULL)
return USBD_INVAL;
@@ -1777,7 +1792,7 @@ uaudio_identify_as(struct uaudio_softc *
USBDEVNAME(sc->sc_dev), id->bNumEndpoints);
break;
}
- id = uaudio_find_iface(tbuf, size,
&offs,UISUBCLASS_AUDIOSTREAM);
+ id = uaudio_find_iface(tbuf, size, &offs, ifaceno);
if (id == NULL)
break;
}
@@ -1839,7 +1854,9 @@ Static usbd_status
}
Static usbd_status
-uaudio_identify_ac(struct uaudio_softc *sc, const usb_config_descriptor_t
*cdesc)
+uaudio_identify_ac(struct uaudio_softc *sc,
+ const usb_config_descriptor_t *cdesc,
+ int ifaceno)
{
struct io_terminal* iot;
const usb_interface_descriptor_t *id;
@@ -1855,7 +1872,7 @@ uaudio_identify_ac(struct uaudio_softc *
/* Locate the AudioControl interface descriptor. */
offs = 0;
- id = uaudio_find_iface(tbuf, size, &offs, UISUBCLASS_AUDIOCONTROL);
+ id = uaudio_find_iface(tbuf, size, &offs, ifaceno);
if (id == NULL)
return USBD_INVAL;
if (offs + sizeof *acdp > size)
============================================================
--- sys/dev/usb/ugen.c 886fadd3c361883d19a0f9eaa47bf36459447da8
+++ sys/dev/usb/ugen.c cc9fc12f9de117bc531e196d4f7413cc6340c041
@@ -214,14 +214,8 @@ USB_MATCH(ugen)
USB_MATCH(ugen)
{
- USB_MATCH_START(ugen, uaa);
- if (match->cf_flags & 1)
- return (UMATCH_HIGHEST);
- else if (uaa->usegeneric)
- return (UMATCH_GENERIC);
- else
- return (UMATCH_NONE);
+ return 1;
}
USB_ATTACH(ugen)
============================================================
--- sys/dev/usb/uhub.c abf3f4739bd6526ebaaff9a74f30930463409368
+++ sys/dev/usb/uhub.c 3a52f88cc8b7762f0a563b90813cd6d2c0ba9699
@@ -542,7 +542,7 @@ uhub_activate(device_ptr_t self, enum de
struct uhub_softc *sc = (struct uhub_softc *)self;
struct usbd_hub *hub = sc->sc_hub->hub;
usbd_device_handle dev;
- int nports, port, i;
+ int nports, port;
switch (act) {
case DVACT_ACTIVATE:
@@ -554,10 +554,8 @@ uhub_activate(device_ptr_t self, enum de
nports = hub->hubdesc.bNbrPorts;
for(port = 0; port < nports; port++) {
dev = hub->ports[port].device;
- if (dev != NULL && dev->subdevs != NULL) {
- for (i = 0; dev->subdevs[i] != NULL; i++)
- config_deactivate(dev->subdevs[i]);
- }
+ if (dev != NULL && dev->subdev)
+ config_deactivate(dev->subdev);
}
break;
}
@@ -620,7 +618,6 @@ uhub_childdet(device_t self, device_t ch
usbd_device_handle dev;
int nports;
int port;
- int i;
if (!devhub->hub)
/* should never happen; children are only created after init */
@@ -629,14 +626,10 @@ uhub_childdet(device_t self, device_t ch
nports = devhub->hub->hubdesc.bNbrPorts;
for (port = 0; port < nports; port++) {
dev = devhub->hub->ports[port].device;
- if (dev == NULL || dev->subdevs == NULL)
+ if (dev == NULL || dev->subdev != child)
continue;
- for (i = 0; dev->subdevs[i]; i++) {
- if (dev->subdevs[i] == child) {
- dev->subdevs[i] = NULL;
- return;
- }
- }
+ dev->subdev = NULL;
+ return;
}
KASSERT(false);
}
============================================================
--- sys/dev/usb/usb.c baec30d7b668d7cf3bbd524c02dfb3cbf419c4a7
+++ sys/dev/usb/usb.c 7f1eec27c3342ca4ae28105ca8ccf80238b97ade
@@ -901,7 +901,7 @@ usb_activate(device_t self, enum devact
{
struct usb_softc *sc = device_private(self);
usbd_device_handle dev = sc->sc_port.device;
- int i, rv = 0;
+ int rv = 0;
switch (act) {
case DVACT_ACTIVATE:
@@ -909,10 +909,8 @@ usb_activate(device_t self, enum devact
case DVACT_DEACTIVATE:
sc->sc_dying = 1;
- if (dev != NULL && dev->cdesc != NULL && dev->subdevs != NULL) {
- for (i = 0; dev->subdevs[i]; i++)
- rv |= config_deactivate(dev->subdevs[i]);
- }
+ if (dev != NULL && dev->cdesc != NULL && dev->subdev)
+ rv = config_deactivate(dev->subdev);
break;
}
return (rv);
@@ -921,22 +919,13 @@ usb_childdet(device_t self, device_t chi
void
usb_childdet(device_t self, device_t child)
{
- int i, last = -1;
struct usb_softc *sc = device_private(self);
struct usbd_device *dev;
- if ((dev = sc->sc_port.device) == NULL || dev->subdevs == NULL)
- return;
-
- for (i = 0; dev->subdevs[i] != NULL; i++)
- last = i;
-
- for (i = 0; dev->subdevs[i] != NULL; i++) {
- if (dev->subdevs[i] == child) {
- dev->subdevs[i] = dev->subdevs[last];
- dev->subdevs[last] = NULL;
- }
- }
+ KASSERT(sc->sc_port.device);
+ dev = sc->sc_port.device;
+ KASSERT(dev->subdev);
+ dev->subdev = NULL;
}
int
============================================================
--- sys/dev/usb/usb.h 572dc8d893c531cf62045994fcde0d59b80935c7
+++ sys/dev/usb/usb.h 9fc7925ca6786f49e560b52787e6069152d32d59
@@ -400,6 +400,9 @@ typedef struct {
#define UDCLASS_WIRELESS 0xe0
#define UDSUBCLASS_RF 0x01
#define UDPROTO_BLUETOOTH 0x01
+#define UDCLASS_MISC 0xef
+#define UDSUBCLASS_COMMON 0x02
+#define UDPROTO_IAD 0x01
#define UDCLASS_VENDOR 0xff
/* Interface class codes */
============================================================
--- sys/dev/usb/usb_subr.c 1fa1e08204f9bee75e9c9c02cde89c00af1f234f
+++ sys/dev/usb/usb_subr.c 5185dec78577f35c713201070097a20f32ef636f
@@ -794,29 +794,9 @@ usbd_probe_and_attach(device_ptr_t paren
int port, int addr)
{
struct usb_attach_arg uaa;
- struct usbif_attach_arg uiaa;
usb_device_descriptor_t *dd = &dev->ddesc;
- int found, i, confi, nifaces;
- usbd_status err;
- device_ptr_t dv;
- usbd_interface_handle *ifaces;
-#if defined(__FreeBSD__)
- /*
- * XXX uaa is a static var. Not a problem as it _should_ be used only
- * during probe and attach. Should be changed however.
- */
- device_t bdev;
- bdev = device_add_child(parent, NULL, -1, &uaa);
- if (!bdev) {
- printf("%s: Device creation failed\n", USBDEVNAME(dev->bus->bdev));
- return (USBD_INVAL);
- }
- device_quiet(bdev);
-#endif
-
uaa.device = dev;
- uaa.usegeneric = 0;
uaa.port = port;
uaa.vendor = UGETW(dd->idVendor);
uaa.product = UGETW(dd->idProduct);
@@ -827,134 +807,9 @@ usbd_probe_and_attach(device_ptr_t paren
/* First try with device specific drivers. */
DPRINTF(("usbd_probe_and_attach: trying device specific drivers\n"));
- dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
- if (dv) {
- dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == NULL)
- return (USBD_NOMEM);
- dev->subdevs[0] = dv;
- dev->subdevs[1] = 0;
- return (USBD_NORMAL_COMPLETION);
- }
-
- DPRINTF(("usbd_probe_and_attach: no device specific driver found\n"));
-
- uiaa.device = dev;
- uiaa.port = port;
- uiaa.vendor = UGETW(dd->idVendor);
- uiaa.product = UGETW(dd->idProduct);
- uiaa.release = UGETW(dd->bcdDevice);
-
- DPRINTF(("usbd_probe_and_attach: looping over %d configurations\n",
- dd->bNumConfigurations));
- /* Next try with interface drivers. */
- for (confi = 0; confi < dd->bNumConfigurations; confi++) {
- DPRINTFN(1,("usbd_probe_and_attach: trying config idx=%d\n",
- confi));
- err = usbd_set_config_index(dev, confi, 1);
- if (err) {
-#ifdef USB_DEBUG
- DPRINTF(("%s: port %d, set config at addr %d failed, "
- "error=%s\n", USBDEVPTRNAME(parent), port,
- addr, usbd_errstr(err)));
-#else
- printf("%s: port %d, set config at addr %d failed\n",
- USBDEVPTRNAME(parent), port, addr);
-#endif
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
-
- return (err);
- }
- nifaces = dev->cdesc->bNumInterface;
- uiaa.configno = dev->cdesc->bConfigurationValue;
- ifaces = malloc(nifaces * sizeof(*ifaces), M_USB, M_NOWAIT);
- if (ifaces == NULL)
- goto nomem;
- for (i = 0; i < nifaces; i++)
- ifaces[i] = &dev->ifaces[i];
- uiaa.ifaces = ifaces;
- uiaa.nifaces = nifaces;
- dev->subdevs = malloc((nifaces+1) * sizeof dv, M_USB,M_NOWAIT);
- if (dev->subdevs == NULL) {
- free(ifaces, M_USB);
-nomem:
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
- return (USBD_NOMEM);
- }
-
- found = 0;
- for (i = 0; i < nifaces; i++) {
- if (ifaces[i] == NULL)
- continue; /* interface already claimed */
- uiaa.iface = ifaces[i];
- uiaa.class = ifaces[i]->idesc->bInterfaceClass;
- uiaa.subclass = ifaces[i]->idesc->bInterfaceSubClass;
- uiaa.proto = ifaces[i]->idesc->bInterfaceProtocol;
- uiaa.ifaceno = ifaces[i]->idesc->bInterfaceNumber;
- dv = USB_DO_IFATTACH(dev, bdev, parent, &uiaa,
usbd_ifprint,
- usbd_ifsubmatch);
- if (dv != NULL) {
- dev->subdevs[found++] = dv;
- dev->subdevs[found] = 0;
- ifaces[i] = 0; /* consumed */
-
-#if defined(__FreeBSD__)
- /* create another child for the next iface */
- bdev = device_add_child(parent, NULL, -1,&uaa);
- if (!bdev) {
- printf("%s: Device creation failed\n",
- USBDEVNAME(dev->bus->bdev));
- free(ifaces, M_USB);
- return (USBD_NORMAL_COMPLETION);
- }
- device_quiet(bdev);
-#endif
- }
- }
- if (found != 0) {
-#if defined(__FreeBSD__)
- /* remove the last created child again; it is unused */
- device_delete_child(parent, bdev);
-#endif
- free(ifaces, M_USB);
- return (USBD_NORMAL_COMPLETION);
- }
- free(ifaces, M_USB);
- free(dev->subdevs, M_USB);
- dev->subdevs = 0;
- }
- /* No interfaces were attached in any of the configurations. */
-
- if (dd->bNumConfigurations > 1) /* don't change if only 1 config */
- usbd_set_config_index(dev, 0, 0);
-
- DPRINTF(("usbd_probe_and_attach: no interface drivers found\n"));
-
- /* Finally try the generic driver. */
- uaa.usegeneric = 1;
- dv = USB_DO_ATTACH(dev, bdev, parent, &uaa, usbd_print, usbd_submatch);
- if (dv != NULL) {
- dev->subdevs = malloc(2 * sizeof dv, M_USB, M_NOWAIT);
- if (dev->subdevs == 0)
- return (USBD_NOMEM);
- dev->subdevs[0] = dv;
- dev->subdevs[1] = 0;
- return (USBD_NORMAL_COMPLETION);
- }
-
- /*
- * The generic attach failed, but leave the device as it is.
- * We just did not find any drivers, that's all. The device is
- * fully operational and not harming anyone.
- */
- DPRINTF(("usbd_probe_and_attach: generic attach failed\n"));
-#if defined(__FreeBSD__)
- device_delete_child(parent, bdev);
-#endif
+ dev->subdev = USB_DO_ATTACH(dev, bdev, parent, &uaa,
+ usbd_print, usbd_submatch);
+
return (USBD_NORMAL_COMPLETION);
}
@@ -1181,16 +1036,8 @@ usbd_print(void *aux, const char *pnp)
struct usb_attach_arg *uaa = aux;
DPRINTFN(15, ("usbd_print dev=%p\n", uaa->device));
- if (pnp) {
-#define USB_DEVINFO 1024
- char *devinfo;
- if (!uaa->usegeneric)
- return (QUIET);
- devinfo = malloc(USB_DEVINFO, M_TEMP, M_WAITOK);
- usbd_devinfo(uaa->device, 1, devinfo, USB_DEVINFO);
- aprint_normal("%s, %s", devinfo, pnp);
- free(devinfo, M_TEMP);
- }
+ if (pnp)
+ return (QUIET);
if (uaa->port != 0)
aprint_normal(" port %d", uaa->port);
#if 0
@@ -1343,13 +1190,11 @@ usbd_fill_deviceinfo(usbd_device_handle
di->udi_power = dev->self_powered ? 0 : dev->power;
di->udi_speed = dev->speed;
- if (dev->subdevs != NULL) {
- for (i = 0; dev->subdevs[i] &&
- i < USB_MAX_DEVNAMES; i++) {
- strncpy(di->udi_devnames[i],
USBDEVPTRNAME(dev->subdevs[i]),
- USB_MAX_DEVNAMELEN);
- di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
- }
+ if (dev->subdev) {
+ strncpy(di->udi_devnames[0], USBDEVPTRNAME(dev->subdev),
+ USB_MAX_DEVNAMELEN);
+ di->udi_devnames[0][USB_MAX_DEVNAMELEN-1] = '\0';
+ i = 1;
} else {
i = 0;
}
@@ -1406,13 +1251,11 @@ usbd_fill_deviceinfo_old(usbd_device_han
di->udi_power = dev->self_powered ? 0 : dev->power;
di->udi_speed = dev->speed;
- if (dev->subdevs != NULL) {
- for (i = 0; dev->subdevs[i] &&
- i < USB_MAX_DEVNAMES; i++) {
- strncpy(di->udi_devnames[i],
USBDEVPTRNAME(dev->subdevs[i]),
- USB_MAX_DEVNAMELEN);
- di->udi_devnames[i][USB_MAX_DEVNAMELEN-1] = '\0';
- }
+ if (dev->subdev) {
+ strncpy(di->udi_devnames[0], USBDEVPTRNAME(dev->subdev),
+ USB_MAX_DEVNAMELEN);
+ di->udi_devnames[0][USB_MAX_DEVNAMELEN-1] = '\0';
+ i = 1;
} else {
i = 0;
}
@@ -1462,8 +1305,6 @@ usb_free_device(usbd_device_handle dev)
}
if (dev->cdesc != NULL)
free(dev->cdesc, M_USB);
- if (dev->subdevs != NULL)
- free(dev->subdevs, M_USB);
free(dev, M_USB);
}
@@ -1489,7 +1330,6 @@ usb_disconnect_port(struct usbd_port *up
{
usbd_device_handle dev = up->device;
char *hubname = USBDEVPTRNAME(parent);
- int i;
DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
up, dev, up->portno));
@@ -1501,16 +1341,14 @@ usb_disconnect_port(struct usbd_port *up
}
#endif
- if (dev->subdevs != NULL) {
- DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
- for (i = 0; dev->subdevs[i]; i++) {
- printf("%s: at %s", USBDEVPTRNAME(dev->subdevs[i]),
- hubname);
- if (up->portno != 0)
- printf(" port %d", up->portno);
- printf(" (addr %d) disconnected\n", dev->address);
- config_detach(dev->subdevs[i], DETACH_FORCE);
- }
+ if (dev->subdev) {
+ DPRINTFN(3,("usb_disconnect_port: disconnect subdev\n"));
+ printf("%s: at %s", USBDEVPTRNAME(dev->subdev), hubname);
+ if (up->portno != 0)
+ printf(" port %d", up->portno);
+ printf(" (addr %d) disconnected\n", dev->address);
+ config_detach(dev->subdev, DETACH_FORCE);
+ dev->subdev = 0;
}
usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
============================================================
--- sys/dev/usb/usbdi.h be5af7b140f06fc59cf93bac23beb29b4375bb22
+++ sys/dev/usb/usbdi.h 5895a90b548c10073af09eb416eda0788ceb5bd0
@@ -235,7 +235,6 @@ struct usb_attach_arg {
int release;
usbd_device_handle device; /* current device */
int class, subclass, proto;
- int usegeneric;
};
struct usbif_attach_arg {
============================================================
--- sys/dev/usb/usbdivar.h 6b9a9d672cd3d7efddc7fba805ba08420ea69f75
+++ sys/dev/usb/usbdivar.h 72189560a2de33ba34088cb2a540f66c3fed2127
@@ -154,7 +154,7 @@ struct usbd_device {
usb_config_descriptor_t *cdesc; /* full config descr */
const struct usbd_quirks *quirks; /* device quirks, always set */
struct usbd_hub *hub; /* only if this is a hub */
- device_t *subdevs; /* sub-devices, 0 terminated */
+ device_t subdev; /* sub-device */
};
struct usbd_interface {
Home |
Main Index |
Thread Index |
Old Index