diff --git a/sys/dev/usb/ubt.c b/sys/dev/usb/ubt.c index a954bc194c63..b658f3df286c 100644 --- a/sys/dev/usb/ubt.c +++ b/sys/dev/usb/ubt.c @@ -1,4 +1,4 @@ -/* $NetBSD: ubt.c,v 1.22 2006/12/21 15:55:25 yamt Exp $ */ +/* $NetBSD: ubt.c,v 1.23 2007/03/12 20:32:00 plunky Exp $ */ /*- * Copyright (c) 2006 Itronix Inc. @@ -74,7 +74,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.22 2006/12/21 15:55:25 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.23 2007/03/12 20:32:00 plunky Exp $"); #include #include @@ -230,6 +230,9 @@ struct ubt_softc { /* Protocol structure */ struct hci_unit sc_unit; + + /* Successfully attached */ + int sc_ok; }; /******************************************************************************* @@ -278,11 +281,12 @@ static int ubt_sysctl_config(SYSCTLFN_PROTO); static void ubt_abortdealloc(struct ubt_softc *); /* - * If a device should be ignored then add + * Match against the whole device, since we want to take + * both interfaces. If a device should be ignored then add * * { VendorID, ProductID } * - * to this list. + * to the ubt_ignore list. */ static const struct usb_devno ubt_ignore[] = { { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033NF }, @@ -292,22 +296,22 @@ static const struct usb_devno ubt_ignore[] = { USB_MATCH(ubt) { USB_MATCH_START(ubt, uaa); - usb_interface_descriptor_t *id; + usb_device_descriptor_t *dd; DPRINTFN(50, "ubt_match\n"); - if (uaa->iface == NULL) + if (uaa->iface != NULL) return UMATCH_NONE; if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product)) return UMATCH_NONE; - id = usbd_get_interface_descriptor(uaa->iface); - if (id != NULL - && id->bInterfaceClass == UICLASS_WIRELESS - && id->bInterfaceSubClass == UISUBCLASS_RF - && id->bInterfaceProtocol == UIPROTO_BLUETOOTH) - return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; + dd = usbd_get_device_descriptor(uaa->device); + if (dd != NULL + && dd->bDeviceClass == UDCLASS_WIRELESS + && dd->bDeviceSubClass == UDSUBCLASS_RF + && dd->bDeviceProtocol == UDPROTO_BLUETOOTH) + return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO; return UMATCH_NONE; } @@ -315,7 +319,6 @@ USB_MATCH(ubt) USB_ATTACH(ubt) { USB_ATTACH_START(ubt, sc, uaa); - usbd_interface_handle iface; usb_config_descriptor_t *cd; usb_endpoint_descriptor_t *ed; const struct sysctlnode *node; @@ -333,11 +336,12 @@ USB_ATTACH(ubt) usbd_devinfo_free(devinfop); /* - * We must have at least 2 interfaces. + * Move the device into the configured state */ - if (uaa->nifaces < 2) { - aprint_error("%s: need 2 interfaces (got %d)\n", - USBDEVNAME(sc->sc_dev), uaa->nifaces); + err = usbd_set_config_index(sc->sc_udev, 0, 1); + if (err) { + aprint_error("%s: failed to set configuration idx 0: %s\n", + USBDEVNAME(sc->sc_dev), usbd_errstr(err)); USB_ATTACH_ERROR_RETURN; } @@ -348,7 +352,7 @@ USB_ATTACH(ubt) * 2) Bulk IN endpoint to receive ACL data * 3) Bulk OUT endpoint to send ACL data */ - err = usbd_device2interface_handle(sc->sc_udev, 0, &iface); + err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0); if (err) { aprint_error("%s: Could not get interface 0 handle %s (%d)\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err), err); @@ -361,12 +365,12 @@ USB_ATTACH(ubt) sc->sc_aclwr_addr = -1; count = 0; - (void)usbd_endpoint_count(iface, &count); + (void)usbd_endpoint_count(sc->sc_iface0, &count); for (i = 0 ; i < count ; i++) { int dir, type; - ed = usbd_interface2endpoint_descriptor(iface, i); + ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i); if (ed == NULL) { aprint_error("%s: could not read endpoint descriptor %d\n", USBDEVNAME(sc->sc_dev), i); @@ -404,10 +408,6 @@ USB_ATTACH(ubt) USB_ATTACH_ERROR_RETURN; } - /* Interface 0 Ok */ - sc->sc_iface0 = iface; - uaa->ifaces[0] = NULL; - /* * Interface 1 must have 2 endpoints * 1) Isochronous IN endpoint to receive SCO data @@ -417,7 +417,7 @@ USB_ATTACH(ubt) * via a sysctl variable. We select config 0 to start, which * means that no SCO data will be available. */ - err = usbd_device2interface_handle(sc->sc_udev, 1, &iface); + err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1); if (err) { aprint_error("%s: Could not get interface 1 handle %s (%d)\n", USBDEVNAME(sc->sc_dev), usbd_errstr(err), err); @@ -435,10 +435,6 @@ USB_ATTACH(ubt) sc->sc_alt_config = usbd_get_no_alts(cd, 1); - /* Interface 1 Ok */ - sc->sc_iface1 = iface; - uaa->ifaces[1] = NULL; - /* set initial config */ err = ubt_set_isoc_config(sc); if (err) { @@ -518,6 +514,7 @@ USB_ATTACH(ubt) CTL_CREATE, CTL_EOL); } + sc->sc_ok = 1; USB_ATTACH_SUCCESS_RETURN; } @@ -530,6 +527,9 @@ USB_DETACH(ubt) sc->sc_dying = 1; + if (!sc->sc_ok) + return 0; + /* delete sysctl nodes */ sysctl_teardown(&sc->sc_log);