static bool btbc_resume(device_t self, const pmf_qual_t *qual) { struct btbc_softc *sc = device_private(self); KASSERT(sc->sc_unit == NULL); sc->sc_unit = hci_attach(&btbc_hci, sc->sc_dev, 0); if (sc->sc_unit == NULL) return false; return true; }
/* ARGSUSED */ static void btbc_attach(device_t parent, device_t self, void *aux) { struct btbc_softc *sc = device_private(self); struct pcmcia_attach_args *pa = aux; struct pcmcia_config_entry *cfe; int error; sc->sc_dev = self; sc->sc_pf = pa->pf; MBUFQ_INIT(&sc->sc_cmdq); MBUFQ_INIT(&sc->sc_aclq); MBUFQ_INIT(&sc->sc_scoq); if ((error = pcmcia_function_configure(pa->pf, btbc_pcmcia_validate_config)) != 0) { aprint_error_dev(self, "configure failed, error=%d\n", error); return; } cfe = pa->pf->cfe; sc->sc_pcioh = cfe->iospace[0].handle; /* Attach Bluetooth unit */ sc->sc_unit = hci_attach(&btbc_hci, self, 0); if (sc->sc_unit == NULL) aprint_error_dev(self, "HCI attach failed\n"); if (!pmf_device_register(self, btbc_suspend, btbc_resume)) aprint_error_dev(self, "couldn't establish power handler\n"); callout_init(&sc->sc_ledch, 0); callout_setfunc(&sc->sc_ledch, btbc_activity_led_timeout, sc); return; }
static int ubt_attach(device_t self) { struct ubt_softc *sc = device_get_softc(self); struct usb_attach_arg *uaa = device_get_ivars(self); usb_config_descriptor_t *cd; usb_endpoint_descriptor_t *ed; int err; uint8_t count, i; DPRINTFN(50, "ubt_attach: sc=%p\n", sc); sc->sc_udev = uaa->device; sc->sc_dev = self; /* * Move the device into the configured state */ err = usbd_set_config_index(sc->sc_udev, 0, 1); if (err) { kprintf("%s: failed to set configuration idx 0: %s\n", device_get_nameunit(sc->sc_dev), usbd_errstr(err)); return ENXIO; } /* * Interface 0 must have 3 endpoints * 1) Interrupt endpoint to receive HCI events * 2) Bulk IN endpoint to receive ACL data * 3) Bulk OUT endpoint to send ACL data */ err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0); if (err) { kprintf("%s: Could not get interface 0 handle %s (%d)\n", device_get_nameunit(sc->sc_dev), usbd_errstr(err), err); return ENXIO; } sc->sc_evt_addr = -1; sc->sc_aclrd_addr = -1; sc->sc_aclwr_addr = -1; count = 0; (void)usbd_endpoint_count(sc->sc_iface0, &count); for (i = 0 ; i < count ; i++) { int dir, type; ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i); if (ed == NULL) { kprintf("%s: could not read endpoint descriptor %d\n", device_get_nameunit(sc->sc_dev), i); return ENXIO; } dir = UE_GET_DIR(ed->bEndpointAddress); type = UE_GET_XFERTYPE(ed->bmAttributes); if (dir == UE_DIR_IN && type == UE_INTERRUPT) sc->sc_evt_addr = ed->bEndpointAddress; else if (dir == UE_DIR_IN && type == UE_BULK) sc->sc_aclrd_addr = ed->bEndpointAddress; else if (dir == UE_DIR_OUT && type == UE_BULK) sc->sc_aclwr_addr = ed->bEndpointAddress; } if (sc->sc_evt_addr == -1) { kprintf("%s: missing INTERRUPT endpoint on interface 0\n", device_get_nameunit(sc->sc_dev)); return ENXIO; } if (sc->sc_aclrd_addr == -1) { kprintf("%s: missing BULK IN endpoint on interface 0\n", device_get_nameunit(sc->sc_dev)); return ENXIO; } if (sc->sc_aclwr_addr == -1) { kprintf("%s: missing BULK OUT endpoint on interface 0\n", device_get_nameunit(sc->sc_dev)); return ENXIO; } /* * Interface 1 must have 2 endpoints * 1) Isochronous IN endpoint to receive SCO data * 2) Isochronous OUT endpoint to send SCO data * * and will have several configurations, which can be selected * 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, &sc->sc_iface1); if (err) { kprintf("%s: Could not get interface 1 handle %s (%d)\n", device_get_nameunit(sc->sc_dev), usbd_errstr(err), err); return ENXIO; } cd = usbd_get_config_descriptor(sc->sc_udev); if (cd == NULL) { kprintf("%s: could not get config descriptor\n", device_get_nameunit(sc->sc_dev)); return ENXIO; } sc->sc_alt_config = usbd_get_no_alts(cd, 1); /* set initial config */ err = ubt_set_isoc_config(sc); if (err) { kprintf("%s: ISOC config failed\n", device_get_nameunit(sc->sc_dev)); return ENXIO; } /* Attach HCI */ sc->sc_unit = hci_attach(&ubt_hci, sc->sc_dev, 0); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); sc->sc_ok = 1; sysctl_ctx_init(&sc->sysctl_ctx); sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_nameunit(sc->sc_dev), CTLFLAG_RD, 0, ""); if (sc->sysctl_tree == NULL) { /* Failure isn't fatal */ device_printf(sc->sc_dev, "Unable to create sysctl tree\n"); return 0; } SYSCTL_ADD_PROC(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "config", CTLTYPE_INT|CTLFLAG_RW, (void *)sc, 0, ubt_sysctl_config, "I", "Configuration number"); SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "alt_config", CTLFLAG_RD, &sc->sc_alt_config, 0, "Number of alternate configurations"); SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "sco_rxsize", CTLFLAG_RD, &sc->sc_scord_size, 0, "Max SCO receive size"); SYSCTL_ADD_INT(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, "sco_wrsize", CTLFLAG_RD, &sc->sc_scowr_size, 0, "Max SCO transmit size"); return 0; }