static int cdce_attach(device_t dev) { struct cdce_softc *sc = device_get_softc(dev); struct usb_ether *ue = &sc->sc_ue; struct usb_attach_arg *uaa = device_get_ivars(dev); struct usb_interface *iface; const struct usb_cdc_union_descriptor *ud; const struct usb_interface_descriptor *id; const struct usb_cdc_ethernet_descriptor *ued; const struct usb_config *pcfg; int error; uint8_t i; uint8_t data_iface_no; char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ sc->sc_flags = USB_GET_DRIVER_INFO(uaa); sc->sc_ue.ue_udev = uaa->device; device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); ud = usbd_find_descriptor (uaa->device, NULL, uaa->info.bIfaceIndex, UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_UNION, 0xFF); if ((ud == NULL) || (ud->bLength < sizeof(*ud)) || (sc->sc_flags & CDCE_FLAG_NO_UNION)) { DPRINTFN(1, "No union descriptor!\n"); sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; goto alloc_transfers; } data_iface_no = ud->bSlaveInterface[0]; for (i = 0;; i++) { iface = usbd_get_iface(uaa->device, i); if (iface) { id = usbd_get_interface_descriptor(iface); if (id && (id->bInterfaceNumber == data_iface_no)) { sc->sc_ifaces_index[0] = i; sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); break; } } else { device_printf(dev, "no data interface found\n"); goto detach; } } /* * <quote> * * The Data Class interface of a networking device shall have * a minimum of two interface settings. The first setting * (the default interface setting) includes no endpoints and * therefore no networking traffic is exchanged whenever the * default interface setting is selected. One or more * additional interface settings are used for normal * operation, and therefore each includes a pair of endpoints * (one IN, and one OUT) to exchange network traffic. Select * an alternate interface setting to initialize the network * aspects of the device and to enable the exchange of * network traffic. * * </quote> * * Some devices, most notably cable modems, include interface * settings that have no IN or OUT endpoint, therefore loop * through the list of all available interface settings * looking for one with both IN and OUT endpoints. */ alloc_transfers: pcfg = cdce_config; /* Default Configuration */ for (i = 0; i != 32; i++) { error = usbd_set_alt_interface_index(uaa->device, sc->sc_ifaces_index[0], i); if (error) break; #if CDCE_HAVE_NCM if ((i == 0) && (cdce_ncm_init(sc) == 0)) pcfg = cdce_ncm_config; #endif error = usbd_transfer_setup(uaa->device, sc->sc_ifaces_index, sc->sc_xfer, pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx); if (error == 0) break; } if (error || (i == 32)) { device_printf(dev, "No valid alternate " "setting found\n"); goto detach; } ued = usbd_find_descriptor (uaa->device, NULL, uaa->info.bIfaceIndex, UDESC_CS_INTERFACE, 0xFF, UDESCSUB_CDC_ENF, 0xFF); if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { error = USB_ERR_INVAL; } else { error = usbd_req_get_string_any(uaa->device, NULL, eaddr_str, sizeof(eaddr_str), ued->iMacAddress); } if (error) { /* fake MAC address */ device_printf(dev, "faking MAC address\n"); sc->sc_ue.ue_eaddr[0] = 0x2a; memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t)); sc->sc_ue.ue_eaddr[5] = device_get_unit(dev); } else { memset(sc->sc_ue.ue_eaddr, 0, sizeof(sc->sc_ue.ue_eaddr)); for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) { char c = eaddr_str[i]; if ('0' <= c && c <= '9') c -= '0'; else if (c != 0) c -= 'A' - 10; else break; c &= 0xf; if ((i & 1) == 0) c <<= 4; sc->sc_ue.ue_eaddr[i / 2] |= c; } if (uaa->usb_mode == USB_MODE_DEVICE) { /* * Do not use the same MAC address like the peer ! */ sc->sc_ue.ue_eaddr[5] ^= 0xFF; } } ue->ue_sc = sc; ue->ue_dev = dev; ue->ue_udev = uaa->device; ue->ue_mtx = &sc->sc_mtx; ue->ue_methods = &cdce_ue_methods; error = uether_ifattach(ue); if (error) { device_printf(dev, "could not attach interface\n"); goto detach; } return (0); /* success */ detach: cdce_detach(dev); return (ENXIO); /* failure */ }
void uticom_attach(struct device *parent, struct device *self, void *aux) { struct uticom_softc *sc = (struct uticom_softc *)self; struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usb_config_descriptor_t *cdesc; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_status err; int status, i; usb_device_descriptor_t *dd; struct ucom_attach_args uca; sc->sc_udev = dev; sc->sc_iface = uaa->iface; /* Initialize endpoints. */ uca.bulkin = uca.bulkout = -1; sc->sc_intr_number = -1; sc->sc_intr_pipe = NULL; dd = usbd_get_device_descriptor(dev); DPRINTF(("%s: uticom_attach: num of configurations %d\n", sc->sc_dev.dv_xname, dd->bNumConfigurations)); /* The device without firmware has single configuration with single * bulk out interface. */ if (dd->bNumConfigurations > 1) goto fwload_done; /* Loading firmware. */ DPRINTF(("%s: uticom_attach: starting loading firmware\n", sc->sc_dev.dv_xname)); err = usbd_set_config_index(dev, UTICOM_CONFIG_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); sc->sc_dying = 1; return; } /* Get the config descriptor. */ cdesc = usbd_get_config_descriptor(sc->sc_udev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("%s: failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); sc->sc_dying = 1; return; } /* Find the bulk out interface used to upload firmware. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); sc->sc_dying = 1; return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; DPRINTF(("%s: uticom_attach: data bulk out num: %d\n", sc->sc_dev.dv_xname, ed->bEndpointAddress)); } if (uca.bulkout == -1) { printf("%s: could not find data bulk out\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } } status = uticom_download_fw(sc, uca.bulkout, dev); if (status) { printf("%s: firmware download failed\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } else { printf("%s: firmware download succeeded\n", sc->sc_dev.dv_xname); } status = usbd_reload_device_desc(dev); if (status) { printf("%s: error reloading device descriptor\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } fwload_done: dd = usbd_get_device_descriptor(dev); DPRINTF(("%s: uticom_attach: num of configurations %d\n", sc->sc_dev.dv_xname, dd->bNumConfigurations)); err = usbd_set_config_index(dev, UTICOM_ACTIVE_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); sc->sc_dying = 1; return; } /* Get the config descriptor. */ cdesc = usbd_get_config_descriptor(sc->sc_udev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } /* Get the interface (XXX: multiport chips are not supported yet). */ err = usbd_device2interface_handle(dev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); sc->sc_dying = 1; return; } /* Find the interrupt endpoints. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); sc->sc_dying = 1; return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->sc_intr_number = ed->bEndpointAddress; sc->sc_isize = UGETW(ed->wMaxPacketSize); } } if (sc->sc_intr_number == -1) { printf("%s: could not find interrupt in\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } /* Keep interface for interrupt. */ sc->sc_intr_iface = sc->sc_iface; /* Find the bulk{in,out} endpoints. */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); sc->sc_dying = 1; return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } } if (uca.bulkin == -1) { printf("%s: could not find data bulk in\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } if (uca.bulkout == -1) { printf("%s: could not find data bulk out\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } sc->sc_dtr = sc->sc_rts = -1; uca.portno = UCOM_UNK_PORTNO; uca.ibufsize = UTICOM_IBUFSZ; uca.obufsize = UTICOM_OBUFSZ; uca.ibufsizepad = UTICOM_IBUFSZ; uca.device = dev; uca.iface = iface; uca.opkthdrlen = 0; uca.methods = &uticom_methods; uca.arg = sc; uca.info = NULL; err = uticom_reset(sc); if (err) { printf("%s: reset failed: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); sc->sc_dying = 1; return; } DPRINTF(("%s: uticom_attach: in = 0x%x, out = 0x%x, intr = 0x%x\n", sc->sc_dev.dv_xname, uca.bulkin, uca.bulkout, sc->sc_intr_number)); sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); }
void kue_attachhook(void *xsc) { struct kue_softc *sc = xsc; int s; struct ifnet *ifp; usbd_device_handle dev = sc->kue_udev; usbd_interface_handle iface; usbd_status err; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; int i; /* Load the firmware into the NIC. */ if (kue_load_fw(sc)) { printf("%s: loading firmware failed\n", USBDEVNAME(sc->kue_dev)); USB_ATTACH_ERROR_RETURN; } err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &iface); if (err) { printf("%s: getting interface handle failed\n", USBDEVNAME(sc->kue_dev)); USB_ATTACH_ERROR_RETURN; } sc->kue_iface = iface; id = usbd_get_interface_descriptor(iface); /* Find endpoints. */ for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { printf("%s: couldn't get ep %d\n", USBDEVNAME(sc->kue_dev), i); USB_ATTACH_ERROR_RETURN; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress; } } if (sc->kue_ed[KUE_ENDPT_RX] == 0 || sc->kue_ed[KUE_ENDPT_TX] == 0) { printf("%s: missing endpoint\n", USBDEVNAME(sc->kue_dev)); USB_ATTACH_ERROR_RETURN; } /* Read ethernet descriptor */ err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, 0, &sc->kue_desc, sizeof(sc->kue_desc)); if (err) { printf("%s: could not read Ethernet descriptor\n", USBDEVNAME(sc->kue_dev)); USB_ATTACH_ERROR_RETURN; } sc->kue_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, M_USBDEV, M_NOWAIT); if (sc->kue_mcfilters == NULL) { printf("%s: no memory for multicast filter buffer\n", USBDEVNAME(sc->kue_dev)); USB_ATTACH_ERROR_RETURN; } s = splnet(); /* * A KLSI chip was detected. Inform the world. */ printf("%s: address %s\n", USBDEVNAME(sc->kue_dev), ether_sprintf(sc->kue_desc.kue_macaddr)); #if defined(__OpenBSD__) bcopy(sc->kue_desc.kue_macaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); #endif /* Initialize interface info.*/ ifp = GET_IFP(sc); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = kue_ioctl; ifp->if_start = kue_start; ifp->if_watchdog = kue_watchdog; strlcpy(ifp->if_xname, USBDEVNAME(sc->kue_dev), IFNAMSIZ); IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); Ether_ifattach(ifp, sc->kue_desc.kue_macaddr); sc->kue_attached = 1; splx(s); }
static int send_bulkmsg(usbd_device_handle dev, char *cmd, size_t cmdlen) { usbd_interface_handle iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_pipe_handle pipe; usbd_xfer_handle xfer; int err, i; /* Move the device into the configured state. */ err = usbd_set_config_index(dev, 0, 0); if (err) { aprint_error("u3g: failed to set configuration index\n"); return UMATCH_NONE; } err = usbd_device2interface_handle(dev, 0, &iface); if (err != 0) { aprint_error("u3ginit: failed to get interface\n"); return UMATCH_NONE; } id = usbd_get_interface_descriptor(iface); ed = NULL; for (i = 0 ; i < id->bNumEndpoints ; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) continue; if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT) continue; if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK) break; } if (i == id->bNumEndpoints) return UMATCH_NONE; err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE, &pipe); if (err != 0) { aprint_error("u3ginit: failed to open bulk transfer pipe %d\n", ed->bEndpointAddress); return UMATCH_NONE; } xfer = usbd_alloc_xfer(dev); if (xfer != NULL) { usbd_setup_xfer(xfer, pipe, NULL, cmd, cmdlen, USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL); err = usbd_transfer(xfer); #if 0 /* XXXpooka: at least my huawei "fails" this always, but still detaches */ if (err) aprint_error("u3ginit: transfer failed\n"); #else err = 0; #endif usbd_free_xfer(xfer); } else { aprint_error("u3ginit: failed to allocate xfer\n"); err = USBD_NOMEM; } usbd_abort_pipe(pipe); usbd_close_pipe(pipe); return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE); }
static void u3g_attach(device_t parent, device_t self, void *aux) { struct u3g_softc *sc = device_private(self); struct usbif_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct ucom_attach_args uca; usbd_status error; int n, intr_address, intr_size; aprint_naive("\n"); aprint_normal("\n"); sc->sc_dev = self; sc->sc_dying = false; sc->sc_udev = dev; error = usbd_device2interface_handle(dev, uaa->ifaceno, &iface); if (error) { aprint_error_dev(self, "failed to get interface, err=%s\n", usbd_errstr(error)); return; } id = usbd_get_interface_descriptor(iface); uca.info = "3G Modem"; uca.ibufsize = U3G_BUFF_SIZE; uca.obufsize = U3G_BUFF_SIZE; uca.ibufsizepad = U3G_BUFF_SIZE; uca.portno = uaa->ifaceno; uca.opkthdrlen = 0; uca.device = dev; uca.iface = iface; uca.methods = &u3g_methods; uca.arg = sc; uca.bulkin = uca.bulkout = -1; sc->sc_outpins = 0; sc->sc_msr = UMSR_DSR | UMSR_CTS | UMSR_DCD; sc->sc_ifaceno = uaa->ifaceno; sc->sc_open = false; sc->sc_purging = false; intr_address = -1; intr_size = 0; for (n = 0; n < id->bNumEndpoints; n++) { ed = usbd_interface2endpoint_descriptor(iface, n); if (ed == NULL) { aprint_error_dev(self, "no endpoint descriptor " "for %d (interface: %d)\n", n, sc->sc_ifaceno); sc->sc_dying = true; return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { intr_address = ed->bEndpointAddress; intr_size = UGETW(ed->wMaxPacketSize); } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } } if (uca.bulkin == -1) { aprint_error_dev(self, "Missing bulk in for interface %d\n", sc->sc_ifaceno); sc->sc_dying = true; return; } if (uca.bulkout == -1) { aprint_error_dev(self, "Missing bulk out for interface %d\n", sc->sc_ifaceno); sc->sc_dying = true; return; } sc->sc_ucom = config_found_sm_loc(self, "ucombus", NULL, &uca, ucomprint, ucomsubmatch); /* * If the interface has an interrupt pipe, open it immediately so * that we can track input pin state changes regardless of whether * the tty(4) device is open or not. */ if (intr_address != -1) { sc->sc_intr_buff = malloc(intr_size, M_USBDEV, M_WAITOK); error = usbd_open_pipe_intr(iface, intr_address, USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buff, intr_size, u3g_intr, 100); if (error) { aprint_error_dev(self, "cannot open interrupt pipe " "(addr %d)\n", intr_address); return; } } else { sc->sc_intr_pipe = NULL; sc->sc_intr_buff = NULL; } if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); }
static usbd_status alloc_all_endpoints_yamaha(struct umidi_softc *sc) { /* This driver currently supports max 1in/1out bulk endpoints */ usb_descriptor_t *desc; usb_endpoint_descriptor_t *epd; int out_addr, in_addr, in_packetsize, i, dir; size_t remain, descsize; out_addr = in_addr = 0; /* detect endpoints */ desc = TO_D(usbd_get_interface_descriptor(sc->sc_iface)); for (i=(int)TO_IFD(desc)->bNumEndpoints-1; i>=0; i--) { epd = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (UE_GET_XFERTYPE(epd->bmAttributes) == UE_BULK) { dir = UE_GET_DIR(epd->bEndpointAddress); if (dir==UE_DIR_OUT && !out_addr) out_addr = epd->bEndpointAddress; else if (dir==UE_DIR_IN && !in_addr) { in_addr = epd->bEndpointAddress; in_packetsize = UGETW(epd->wMaxPacketSize); } } } desc = NEXT_D(desc); /* count jacks */ if (!(desc->bDescriptorType==UDESC_CS_INTERFACE && desc->bDescriptorSubtype==UMIDI_MS_HEADER)) return USBD_INVAL; remain = (size_t)UGETW(TO_CSIFD(desc)->wTotalLength) - (size_t)desc->bLength; desc = NEXT_D(desc); while (remain>=sizeof(usb_descriptor_t)) { descsize = desc->bLength; if (descsize>remain || descsize==0) break; if (desc->bDescriptorType==UDESC_CS_INTERFACE && remain>=UMIDI_JACK_DESCRIPTOR_SIZE) { if (desc->bDescriptorSubtype==UMIDI_OUT_JACK) sc->sc_out_num_jacks++; else if (desc->bDescriptorSubtype==UMIDI_IN_JACK) sc->sc_in_num_jacks++; } desc = NEXT_D(desc); remain-=descsize; } /* validate some parameters */ if (sc->sc_out_num_jacks>UMIDI_MAX_EPJACKS) sc->sc_out_num_jacks = UMIDI_MAX_EPJACKS; if (sc->sc_in_num_jacks>UMIDI_MAX_EPJACKS) sc->sc_in_num_jacks = UMIDI_MAX_EPJACKS; if (sc->sc_out_num_jacks && out_addr) sc->sc_out_num_endpoints = 1; else { sc->sc_out_num_endpoints = 0; sc->sc_out_num_jacks = 0; } if (sc->sc_in_num_jacks && in_addr) sc->sc_in_num_endpoints = 1; else { sc->sc_in_num_endpoints = 0; sc->sc_in_num_jacks = 0; } sc->sc_endpoints = mallocarray(sc->sc_out_num_endpoints + sc->sc_in_num_endpoints, sizeof(struct umidi_endpoint), M_USBDEV, M_WAITOK | M_CANFAIL); if (!sc->sc_endpoints) return USBD_NOMEM; if (sc->sc_out_num_endpoints) { sc->sc_out_ep = sc->sc_endpoints; sc->sc_out_ep->sc = sc; sc->sc_out_ep->addr = out_addr; sc->sc_out_ep->packetsize = UGETW(epd->wMaxPacketSize); sc->sc_out_ep->num_jacks = sc->sc_out_num_jacks; sc->sc_out_ep->num_open = 0; memset(sc->sc_out_ep->jacks, 0, sizeof(sc->sc_out_ep->jacks)); } else sc->sc_out_ep = NULL; if (sc->sc_in_num_endpoints) { sc->sc_in_ep = sc->sc_endpoints+sc->sc_out_num_endpoints; sc->sc_in_ep->sc = sc; sc->sc_in_ep->addr = in_addr; sc->sc_in_ep->packetsize = in_packetsize; sc->sc_in_ep->num_jacks = sc->sc_in_num_jacks; sc->sc_in_ep->num_open = 0; memset(sc->sc_in_ep->jacks, 0, sizeof(sc->sc_in_ep->jacks)); } else sc->sc_in_ep = NULL; return USBD_NORMAL_COMPLETION; }
/* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ void wi_usb_attach(struct device *parent, struct device *self, void *aux) { struct wi_usb_softc *sc = (struct wi_usb_softc *)self; struct usb_attach_arg *uaa = aux; /* int s; */ usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usbd_status err; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; int i; DPRINTFN(5,(" : wi_usb_attach: sc=%p", sc)); err = usbd_set_config_no(dev, WI_USB_CONFIG_NO, 1); if (err) { printf("%s: setting config no failed\n", sc->wi_usb_dev.dv_xname); return; } /* XXX - any tasks? */ err = usbd_device2interface_handle(dev, WI_USB_IFACE_IDX, &iface); if (err) { printf("%s: getting interface handle failed\n", sc->wi_usb_dev.dv_xname); return; } /* XXX - flags? */ sc->wi_usb_udev = dev; sc->wi_usb_iface = iface; sc->wi_usb_product = uaa->product; sc->wi_usb_vendor = uaa->vendor; sc->sc_wi.wi_usb_cdata = sc; sc->sc_wi.wi_flags |= WI_FLAGS_BUS_USB; sc->wi_lock = 0; sc->wi_lockwait = 0; sc->wi_resetonce = 0; id = usbd_get_interface_descriptor(iface); /* Find endpoints. */ for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { printf("%s: couldn't get endpoint descriptor %d\n", sc->wi_usb_dev.dv_xname, i); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->wi_usb_ed[WI_USB_ENDPT_RX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->wi_usb_ed[WI_USB_ENDPT_TX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->wi_usb_ed[WI_USB_ENDPT_INTR] = ed->bEndpointAddress; } } sc->wi_usb_nummem = 0; /* attach wi device */ if (wi_usb_rx_list_init(sc)) { printf("%s: rx list init failed\n", sc->wi_usb_dev.dv_xname); return; } if (wi_usb_tx_list_init(sc)) { printf("%s: tx list init failed\n", sc->wi_usb_dev.dv_xname); return; } if (wi_usb_open_pipes(sc)){ printf("%s: open pipes failed\n", sc->wi_usb_dev.dv_xname); return; } sc->wi_usb_attached = 1; kthread_create_deferred(wi_usb_start_thread, sc); }
void uslcom_attach(struct device *parent, struct device *self, void *aux) { struct uslcom_softc *sc = (struct uslcom_softc *)self; struct usb_attach_arg *uaa = aux; struct ucom_attach_args uca; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_status error; int i; bzero(&uca, sizeof(uca)); sc->sc_udev = uaa->device; if (usbd_set_config_index(sc->sc_udev, USLCOM_CONFIG_NO, 1) != 0) { printf("%s: could not set configuration no\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } /* get the first interface handle */ error = usbd_device2interface_handle(sc->sc_udev, USLCOM_IFACE_NO, &sc->sc_iface); if (error != 0) { printf("%s: could not get interface handle\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } id = usbd_get_interface_descriptor(sc->sc_iface); uca.bulkin = uca.bulkout = -1; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor found for %d\n", sc->sc_dev.dv_xname, i); sc->sc_dying = 1; return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) uca.bulkin = ed->bEndpointAddress; else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) uca.bulkout = ed->bEndpointAddress; } if (uca.bulkin == -1 || uca.bulkout == -1) { printf("%s: missing endpoint\n", sc->sc_dev.dv_xname); sc->sc_dying = 1; return; } uca.ibufsize = USLCOMBUFSZ; uca.obufsize = USLCOMBUFSZ; uca.ibufsizepad = USLCOMBUFSZ; uca.opkthdrlen = 0; uca.device = sc->sc_udev; uca.iface = sc->sc_iface; uca.methods = &uslcom_methods; uca.arg = sc; uca.info = NULL; sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); }
static int usie_attach(device_t self) { struct usie_softc *sc = device_get_softc(self); struct usb_attach_arg *uaa = device_get_ivars(self); struct ifnet *ifp; struct usb_interface *iface; struct usb_interface_descriptor *id; struct usb_device_request req; int err; uint16_t fwattr; uint8_t iface_index; uint8_t ifidx; uint8_t start; device_set_usb_desc(self); sc->sc_udev = uaa->device; sc->sc_dev = self; mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF); ucom_ref(&sc->sc_super_ucom); TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc); TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc); usb_callout_init_mtx(&sc->sc_if_sync_ch, &sc->sc_mtx, 0); mtx_lock(&sc->sc_mtx); /* set power mode to D0 */ req.bmRequestType = UT_WRITE_VENDOR_DEVICE; req.bRequest = USIE_POWER; USETW(req.wValue, 0); USETW(req.wIndex, 0); USETW(req.wLength, 0); if (usie_do_request(sc, &req, NULL)) { mtx_unlock(&sc->sc_mtx); goto detach; } /* read fw attr */ fwattr = 0; req.bmRequestType = UT_READ_VENDOR_DEVICE; req.bRequest = USIE_FW_ATTR; USETW(req.wValue, 0); USETW(req.wIndex, 0); USETW(req.wLength, sizeof(fwattr)); if (usie_do_request(sc, &req, &fwattr)) { mtx_unlock(&sc->sc_mtx); goto detach; } mtx_unlock(&sc->sc_mtx); /* check DHCP supports */ DPRINTF("fwattr=%x\n", fwattr); if (!(fwattr & USIE_FW_DHCP)) { device_printf(self, "DHCP is not supported. A firmware upgrade might be needed.\n"); } /* find available interfaces */ sc->sc_nucom = 0; for (ifidx = 0; ifidx < USIE_IFACE_MAX; ifidx++) { iface = usbd_get_iface(uaa->device, ifidx); if (iface == NULL) break; id = usbd_get_interface_descriptor(iface); if ((id == NULL) || (id->bInterfaceClass != UICLASS_VENDOR)) continue; /* setup Direct IP transfer */ if (id->bInterfaceNumber >= 7 && id->bNumEndpoints == 3) { sc->sc_if_ifnum = id->bInterfaceNumber; iface_index = ifidx; DPRINTF("ifnum=%d, ifidx=%d\n", sc->sc_if_ifnum, ifidx); err = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_if_xfer, usie_if_config, USIE_IF_N_XFER, sc, &sc->sc_mtx); if (err == 0) continue; device_printf(self, "could not allocate USB transfers on " "iface_index=%d, err=%s\n", iface_index, usbd_errstr(err)); goto detach; } /* setup ucom */ if (sc->sc_nucom >= USIE_UCOM_MAX) continue; usbd_set_parent_iface(uaa->device, ifidx, uaa->info.bIfaceIndex); DPRINTF("NumEndpoints=%d bInterfaceNumber=%d\n", id->bNumEndpoints, id->bInterfaceNumber); if (id->bNumEndpoints == 2) { sc->sc_uc_xfer[sc->sc_nucom][0] = NULL; start = 1; } else start = 0; err = usbd_transfer_setup(uaa->device, &ifidx, sc->sc_uc_xfer[sc->sc_nucom] + start, usie_uc_config + start, USIE_UC_N_XFER - start, &sc->sc_ucom[sc->sc_nucom], &sc->sc_mtx); if (err != 0) { DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err)); continue; } mtx_lock(&sc->sc_mtx); for (; start < USIE_UC_N_XFER; start++) usbd_xfer_set_stall(sc->sc_uc_xfer[sc->sc_nucom][start]); mtx_unlock(&sc->sc_mtx); sc->sc_uc_ifnum[sc->sc_nucom] = id->bInterfaceNumber; sc->sc_nucom++; /* found a port */ } if (sc->sc_nucom == 0) { device_printf(self, "no comports found\n"); goto detach; } err = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_nucom, sc, &usie_uc_callback, &sc->sc_mtx); if (err != 0) { DPRINTF("ucom_attach failed\n"); goto detach; } DPRINTF("Found %d interfaces.\n", sc->sc_nucom); /* setup ifnet (Direct IP) */ sc->sc_ifp = ifp = if_alloc(IFT_OTHER); if (ifp == NULL) { device_printf(self, "Could not allocate a network interface\n"); goto detach; } if_initname(ifp, "usie", device_get_unit(self)); ifp->if_softc = sc; ifp->if_mtu = USIE_MTU_MAX; ifp->if_flags |= IFF_NOARP; ifp->if_init = usie_if_init; ifp->if_ioctl = usie_if_ioctl; ifp->if_start = usie_if_start; ifp->if_output = usie_if_output; IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); bpfattach(ifp, DLT_RAW, 0); if (fwattr & USIE_PM_AUTO) { usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE); DPRINTF("enabling automatic suspend and resume\n"); } else { usbd_set_power_mode(uaa->device, USB_POWER_MODE_ON); DPRINTF("USB power is always ON\n"); } DPRINTF("device attached\n"); return (0); detach: usie_detach(self); return (ENOMEM); }
static int u3g_novatel_reinit(struct usb_attach_arg *uaa) { unsigned char cmd[31]; usbd_interface_handle iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_pipe_handle pipe; usbd_xfer_handle xfer; int err, i; memset(cmd, 0, sizeof(cmd)); /* Byte 0..3: Command Block Wrapper (CBW) signature */ cmd[0] = 0x55; cmd[1] = 0x53; cmd[2] = 0x42; cmd[3] = 0x43; /* 4..7: CBW Tag, has to unique, but only a single transfer used. */ cmd[4] = 0x01; /* 8..11: CBW Transfer Length, no data here */ /* 12: CBW Flag: output, so 0 */ /* 13: CBW Lun: 0 */ /* 14: CBW Length */ cmd[14] = 0x06; /* Rest is the SCSI payload */ /* 0: SCSI START/STOP opcode */ cmd[15] = 0x1b; /* 1..3 unused */ /* 4 Load/Eject command */ cmd[19] = 0x02; /* 5: unused */ /* Move the device into the configured state. */ err = usbd_set_config_index(uaa->device, 0, 0); if (err) { aprint_error("u3g: failed to set configuration index\n"); return UMATCH_NONE; } err = usbd_device2interface_handle(uaa->device, 0, &iface); if (err != 0) { aprint_error("u3g: failed to get interface\n"); return UMATCH_NONE; } id = usbd_get_interface_descriptor(iface); ed = NULL; for (i = 0 ; i < id->bNumEndpoints ; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) continue; if (UE_GET_DIR(ed->bEndpointAddress) != UE_DIR_OUT) continue; if ((ed->bmAttributes & UE_XFERTYPE) == UE_BULK) break; } if (i == id->bNumEndpoints) return UMATCH_NONE; err = usbd_open_pipe(iface, ed->bEndpointAddress, USBD_EXCLUSIVE_USE, &pipe); if (err != 0) { aprint_error("u3g: failed to open bulk transfer pipe %d\n", ed->bEndpointAddress); return UMATCH_NONE; } xfer = usbd_alloc_xfer(uaa->device); if (xfer != NULL) { usbd_setup_xfer(xfer, pipe, NULL, cmd, sizeof(cmd), USBD_SYNCHRONOUS, USBD_DEFAULT_TIMEOUT, NULL); err = usbd_transfer(xfer); if (err) aprint_error("u3g: transfer failed\n"); usbd_free_xfer(xfer); } else { aprint_error("u3g: failed to allocate xfer\n"); err = USBD_NOMEM; } usbd_abort_pipe(pipe); usbd_close_pipe(pipe); return (err == USBD_NORMAL_COMPLETION ? UMATCH_HIGHEST : UMATCH_NONE); }
static void u3g_attach(device_t parent, device_t self, void *aux) { struct u3g_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_status error; int i, n; usb_config_descriptor_t *cdesc; aprint_naive("\n"); aprint_normal("\n"); if (uaa->vendor == USB_VENDOR_NOVATEL2 && uaa->product == USB_PRODUCT_NOVATEL2_MC950D_DRIVER) { /* About to disappear... */ sc->sc_pseudodev = true; return; } sc->sc_dev = self; #ifdef U3G_DEBUG sc->sc_intr_number = -1; sc->sc_intr_pipe = NULL; #endif /* Move the device into the configured state. */ error = usbd_set_config_index(dev, 0, 1); if (error) { aprint_error_dev(self, "failed to set configuration: %s\n", usbd_errstr(error)); return; } /* get the config descriptor */ cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL) { aprint_error_dev(self, "failed to get configuration descriptor\n"); return; } if (uaa->vendor == USB_VENDOR_HUAWEI && cdesc->bNumInterface > 1) { /* About to disappear... */ sc->sc_pseudodev = true; return; } if (uaa->vendor == USB_VENDOR_SIERRA && uaa->product == USB_PRODUCT_SIERRA_INSTALLER) { /* About to disappear... */ sc->sc_pseudodev = true; return; } sc->sc_udev = dev; sc->numports = (cdesc->bNumInterface <= U3G_MAXPORTS)?cdesc->bNumInterface:U3G_MAXPORTS; for ( i = 0; i < sc->numports; i++ ) { struct ucom_attach_args uca; error = usbd_device2interface_handle(dev, i, &iface); if (error) { aprint_error_dev(self, "failed to get interface, err=%s\n", usbd_errstr(error)); return; } id = usbd_get_interface_descriptor(iface); uca.info = "Generic 3G Serial Device"; uca.ibufsize = U3GBUFSZ; uca.obufsize = U3GBUFSZ; uca.ibufsizepad = U3GBUFSZ; uca.portno = i; uca.opkthdrlen = 0; uca.device = dev; uca.iface = iface; uca.methods = &u3g_methods; uca.arg = sc; uca.bulkin = uca.bulkout = -1; for (n = 0; n < id->bNumEndpoints; n++) { ed = usbd_interface2endpoint_descriptor(iface, n); if (ed == NULL) { aprint_error_dev(self, "could not read endpoint descriptor\n"); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) uca.bulkin = ed->bEndpointAddress; else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) uca.bulkout = ed->bEndpointAddress; } if (uca.bulkin == -1 || uca.bulkout == -1) { aprint_error_dev(self, "missing endpoint\n"); return; } sc->sc_ucom[i] = config_found_sm_loc(self, "ucombus", NULL, &uca, ucomprint, ucomsubmatch); } #ifdef U3G_DEBUG if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL) { sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); error = usbd_open_pipe_intr(sc->sc_intr_iface, sc->sc_intr_number, USBD_SHORT_XFER_OK, &sc->sc_intr_pipe, sc, sc->sc_intr_buf, sc->sc_isize, u3g_intr, 100); if (error) { aprint_error_dev(self, "cannot open interrupt pipe (addr %d)\n", sc->sc_intr_number); return; } } #endif if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); }
void umct_attach(struct device *parent, struct device *self, void *aux) { struct umct_softc *sc = (struct umct_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->device; usb_config_descriptor_t *cdesc; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devname = sc->sc_dev.dv_xname; usbd_status err; int i; struct ucom_attach_args uca; sc->sc_udev = dev; sc->sc_product = uaa->product; DPRINTF(("\n\numct attach: sc=%p\n", sc)); /* initialize endpoints */ uca.bulkin = uca.bulkout = -1; sc->sc_intr_number = -1; sc->sc_intr_pipe = NULL; /* Move the device into the configured state. */ err = usbd_set_config_index(dev, UMCT_CONFIG_INDEX, 1); if (err) { printf("\n%s: failed to set configuration, err=%s\n", devname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* get the config descriptor */ cdesc = usbd_get_config_descriptor(sc->sc_udev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } /* get the interface */ err = usbd_device2interface_handle(dev, UMCT_IFACE_INDEX, &sc->sc_iface); if (err) { printf("\n%s: failed to get interface, err=%s\n", devname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); return; } /* Find the bulk{in,out} and interrupt endpoints */ id = usbd_get_interface_descriptor(sc->sc_iface); sc->sc_iface_number = id->bInterfaceNumber; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); usbd_deactivate(sc->sc_udev); return; } /* * The Bulkin endpoint is marked as an interrupt. Since * we can't rely on the endpoint descriptor order, we'll * check the wMaxPacketSize field to differentiate. */ if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT && UGETW(ed->wMaxPacketSize) != 0x2) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->sc_intr_number = ed->bEndpointAddress; sc->sc_isize = UGETW(ed->wMaxPacketSize); } } if (uca.bulkin == -1) { printf("%s: Could not find data bulk in\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } if (uca.bulkout == -1) { printf("%s: Could not find data bulk out\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } if (sc->sc_intr_number== -1) { printf("%s: Could not find interrupt in\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } sc->sc_dtr = sc->sc_rts = 0; uca.portno = UCOM_UNK_PORTNO; /* bulkin, bulkout set above */ uca.ibufsize = UMCTIBUFSIZE; if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232) uca.obufsize = 16; /* device is broken */ else uca.obufsize = UMCTOBUFSIZE; uca.ibufsizepad = UMCTIBUFSIZE; uca.opkthdrlen = 0; uca.device = dev; uca.iface = sc->sc_iface; uca.methods = &umct_methods; uca.arg = sc; uca.info = NULL; umct_init(sc); DPRINTF(("umct: in=0x%x out=0x%x intr=0x%x\n", uca.bulkin, uca.bulkout, sc->sc_intr_number )); sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); }
void umodem_attach(struct device *parent, struct device *self, void *aux) { struct umodem_softc *sc = (struct umodem_softc *)self; struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usb_cdc_cm_descriptor_t *cmd; usb_interface_descriptor_t *idesc; const usb_cdc_acm_descriptor_t *acmd; const usb_cdc_union_descriptor_t *uniond; const usb_descriptor_t *desc; usbd_desc_iter_t iter; usbd_status err; int current_iface_no = -1; int i; struct ucom_attach_args uca; sc->sc_udev = dev; sc->sc_ctl_iface = uaa->iface; id = usbd_get_interface_descriptor(sc->sc_ctl_iface); //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname, // id->bInterfaceClass, id->bInterfaceSubClass); sc->sc_ctl_iface_no = id->bInterfaceNumber; /* Get the data interface no. and capabilities */ sc->sc_cm_cap = 0; sc->sc_data_iface_no = 0; sc->sc_acm_cap = 0; usb_desc_iter_init(dev, &iter); desc = usb_desc_iter_next(&iter); while (desc) { if (desc->bDescriptorType == UDESC_INTERFACE) { idesc = (usb_interface_descriptor_t *)desc; current_iface_no = idesc->bInterfaceNumber; } if (current_iface_no == sc->sc_ctl_iface_no && desc->bDescriptorType == UDESC_CS_INTERFACE) { switch(desc->bDescriptorSubtype) { case UDESCSUB_CDC_CM: cmd = (usb_cdc_cm_descriptor_t *)desc; sc->sc_cm_cap = cmd->bmCapabilities; sc->sc_data_iface_no = cmd->bDataInterface; break; case UDESCSUB_CDC_ACM: acmd = (usb_cdc_acm_descriptor_t *)desc; sc->sc_acm_cap = acmd->bmCapabilities; break; case UDESCSUB_CDC_UNION: uniond = (usb_cdc_union_descriptor_t *)desc; sc->sc_data_iface_no = uniond->bSlaveInterface[0]; break; } } desc = usb_desc_iter_next(&iter); } if (sc->sc_data_iface_no == 0) { printf("%s: no pointer to data interface\n", sc->sc_dev.dv_xname); goto bad; } printf("%s: data interface %d, has %sCM over data, has %sbreak\n", sc->sc_dev.dv_xname, sc->sc_data_iface_no, sc->sc_cm_cap & USB_CDC_CM_OVER_DATA ? "" : "no ", sc->sc_acm_cap & USB_CDC_ACM_HAS_BREAK ? "" : "no "); /* Get the data interface too. */ for (i = 0; i < uaa->nifaces; i++) { if (uaa->ifaces[i] != NULL) { id = usbd_get_interface_descriptor(uaa->ifaces[i]); if (id != NULL && id->bInterfaceNumber == sc->sc_data_iface_no) { sc->sc_data_iface = uaa->ifaces[i]; uaa->ifaces[i] = NULL; } } } if (sc->sc_data_iface == NULL) { printf("%s: no data interface\n", sc->sc_dev.dv_xname); goto bad; } /* * Find the bulk endpoints. * Iterate over all endpoints in the data interface and take note. */ uca.bulkin = uca.bulkout = -1; id = usbd_get_interface_descriptor(sc->sc_data_iface); for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_data_iface, i); if (ed == NULL) { printf("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); goto bad; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { uca.bulkin = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { uca.bulkout = ed->bEndpointAddress; } } if (uca.bulkin == -1) { printf("%s: Could not find data bulk in\n", sc->sc_dev.dv_xname); goto bad; } if (uca.bulkout == -1) { printf("%s: Could not find data bulk out\n", sc->sc_dev.dv_xname); goto bad; } if (usbd_get_quirks(sc->sc_udev)->uq_flags & UQ_ASSUME_CM_OVER_DATA) { sc->sc_cm_over_data = 1; } else { if (sc->sc_cm_cap & USB_CDC_CM_OVER_DATA) { if (sc->sc_acm_cap & USB_CDC_ACM_HAS_FEATURE) err = umodem_set_comm_feature(sc, UCDC_ABSTRACT_STATE, UCDC_DATA_MULTIPLEXED); else err = 0; if (err) { printf("%s: could not set data multiplex mode\n", sc->sc_dev.dv_xname); goto bad; } sc->sc_cm_over_data = 1; } } /* * The standard allows for notification messages (to indicate things * like a modem hangup) to come in via an interrupt endpoint * off of the control interface. Iterate over the endpoints on * the control interface and see if there are any interrupt * endpoints; if there are, then register it. */ sc->sc_ctl_notify = -1; sc->sc_notify_pipe = NULL; id = usbd_get_interface_descriptor(sc->sc_ctl_iface); for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_ctl_iface, i); if (ed == NULL) continue; if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { printf("%s: status change notification available\n", sc->sc_dev.dv_xname); sc->sc_ctl_notify = ed->bEndpointAddress; } } sc->sc_dtr = -1; uca.portno = UCOM_UNK_PORTNO; /* bulkin, bulkout set above */ uca.ibufsize = UMODEMIBUFSIZE; uca.obufsize = UMODEMOBUFSIZE; uca.ibufsizepad = UMODEMIBUFSIZE; uca.opkthdrlen = 0; uca.device = sc->sc_udev; uca.iface = sc->sc_data_iface; uca.methods = &umodem_methods; uca.arg = sc; uca.info = NULL; usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, &sc->sc_dev); DPRINTF(("umodem_attach: sc=%p\n", sc)); sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); return; bad: sc->sc_dying = 1; }
static usbd_status alloc_all_endpoints_genuine(struct umidi_softc *sc) { usb_interface_descriptor_t *interface_desc; usb_config_descriptor_t *config_desc; usb_descriptor_t *desc; size_t remain, descsize; struct umidi_endpoint *p, *q, *lowest, *endep, tmpep; int epaddr, eppacketsize, num_ep; interface_desc = usbd_get_interface_descriptor(sc->sc_iface); num_ep = interface_desc->bNumEndpoints; sc->sc_endpoints = p = mallocarray(num_ep, sizeof(struct umidi_endpoint), M_USBDEV, M_WAITOK | M_CANFAIL); if (!p) return USBD_NOMEM; sc->sc_out_num_endpoints = sc->sc_in_num_endpoints = 0; epaddr = -1; /* get the list of endpoints for midi stream */ config_desc = usbd_get_config_descriptor(sc->sc_udev); desc = (usb_descriptor_t *) config_desc; remain = (size_t)UGETW(config_desc->wTotalLength); while (remain>=sizeof(usb_descriptor_t)) { descsize = desc->bLength; if (descsize>remain || descsize==0) break; if (desc->bDescriptorType==UDESC_ENDPOINT && remain>=USB_ENDPOINT_DESCRIPTOR_SIZE && UE_GET_XFERTYPE(TO_EPD(desc)->bmAttributes) == UE_BULK) { epaddr = TO_EPD(desc)->bEndpointAddress; eppacketsize = UGETW(TO_EPD(desc)->wMaxPacketSize); } else if (desc->bDescriptorType==UDESC_CS_ENDPOINT && remain>=UMIDI_CS_ENDPOINT_DESCRIPTOR_SIZE && epaddr!=-1) { if (num_ep>0) { num_ep--; p->sc = sc; p->addr = epaddr; p->packetsize = eppacketsize; p->num_jacks = TO_CSEPD(desc)->bNumEmbMIDIJack; if (UE_GET_DIR(epaddr)==UE_DIR_OUT) { sc->sc_out_num_endpoints++; sc->sc_out_num_jacks += p->num_jacks; } else { sc->sc_in_num_endpoints++; sc->sc_in_num_jacks += p->num_jacks; } p++; } } else epaddr = -1; desc = NEXT_D(desc); remain-=descsize; } /* sort endpoints */ num_ep = sc->sc_out_num_endpoints + sc->sc_in_num_endpoints; p = sc->sc_endpoints; endep = p + num_ep; while (p<endep) { lowest = p; for (q=p+1; q<endep; q++) { if ((UE_GET_DIR(lowest->addr)==UE_DIR_IN && UE_GET_DIR(q->addr)==UE_DIR_OUT) || ((UE_GET_DIR(lowest->addr)== UE_GET_DIR(q->addr)) && (UE_GET_ADDR(lowest->addr)> UE_GET_ADDR(q->addr)))) lowest = q; } if (lowest != p) { memcpy((void *)&tmpep, (void *)p, sizeof(tmpep)); memcpy((void *)p, (void *)lowest, sizeof(tmpep)); memcpy((void *)lowest, (void *)&tmpep, sizeof(tmpep)); } p->num_open = 0; p++; } sc->sc_out_ep = sc->sc_out_num_endpoints ? sc->sc_endpoints : NULL; sc->sc_in_ep = sc->sc_in_num_endpoints ? sc->sc_endpoints+sc->sc_out_num_endpoints : NULL; return USBD_NORMAL_COMPLETION; }
void ulpt_attach(struct device *parent, struct device *self, void *aux) { struct ulpt_softc *sc = (struct ulpt_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->device; struct usbd_interface *iface = uaa->iface; usb_interface_descriptor_t *ifcd = usbd_get_interface_descriptor(iface); usb_interface_descriptor_t *id, *iend; usb_config_descriptor_t *cdesc; usbd_status err; usb_endpoint_descriptor_t *ed; u_int8_t epcount; int i, altno; DPRINTFN(10,("ulpt_attach: sc=%p\n", sc)); //printf("%s: iclass %d/%d\n", sc->sc_dev.dv_xname, // ifcd->bInterfaceClass, ifcd->bInterfaceSubClass); /* XXX * Stepping through the alternate settings needs to be abstracted out. */ cdesc = usbd_get_config_descriptor(dev); if (cdesc == NULL) { printf("%s: failed to get configuration descriptor\n", sc->sc_dev.dv_xname); return; } iend = (usb_interface_descriptor_t *) ((char *)cdesc + UGETW(cdesc->wTotalLength)); #ifdef DIAGNOSTIC if (ifcd < (usb_interface_descriptor_t *)cdesc || ifcd >= iend) panic("ulpt: iface desc out of range"); #endif /* Step through all the descriptors looking for bidir mode */ for (id = ifcd, altno = 0; id < iend; id = (void *)((char *)id + id->bLength)) { if (id->bDescriptorType == UDESC_INTERFACE && id->bInterfaceNumber == ifcd->bInterfaceNumber) { if (id->bInterfaceClass == UICLASS_PRINTER && id->bInterfaceSubClass == UISUBCLASS_PRINTER && (id->bInterfaceProtocol == UIPROTO_PRINTER_BI /*|| id->bInterfaceProtocol == UIPROTO_PRINTER_1284*/)) goto found; altno++; } } id = ifcd; /* not found, use original */ found: if (id != ifcd) { /* Found a new bidir setting */ DPRINTF(("ulpt_attach: set altno = %d\n", altno)); err = usbd_set_interface(iface, altno); if (err) { printf("%s: setting alternate interface failed\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } } epcount = 0; (void)usbd_endpoint_count(iface, &epcount); sc->sc_in = -1; sc->sc_out = -1; for (i = 0; i < epcount; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { printf("%s: couldn't get ep %d\n", sc->sc_dev.dv_xname, i); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_in = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->sc_out = ed->bEndpointAddress; } } if (sc->sc_out == -1) { printf("%s: could not find bulk out endpoint\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } if (usbd_get_quirks(dev)->uq_flags & UQ_BROKEN_BIDIR) { /* This device doesn't handle reading properly. */ sc->sc_in = -1; } printf("%s: using %s-directional mode\n", sc->sc_dev.dv_xname, sc->sc_in >= 0 ? "bi" : "uni"); DPRINTFN(10, ("ulpt_attach: bulk=%d\n", sc->sc_out)); sc->sc_iface = iface; sc->sc_ifaceno = id->bInterfaceNumber; sc->sc_udev = dev; /* maybe the device needs firmware */ sc->sc_fwdev = ulpt_lookup(uaa->vendor, uaa->product); if (sc->sc_fwdev) { if (rootvp == NULL) mountroothook_establish(ulpt_load_firmware, sc); else ulpt_load_firmware(sc); } #if 0 /* * This code is disabled because for some mysterious reason it causes * printing not to work. But only sometimes, and mostly with * UHCI and less often with OHCI. *sigh* */ { usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev); usb_device_request_t req; int len, alen; req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_DEVICE_ID; USETW(req.wValue, cd->bConfigurationValue); USETW2(req.wIndex, id->bInterfaceNumber, id->bAlternateSetting); USETW(req.wLength, DEVINFOSIZE - 1); err = usbd_do_request_flags(dev, &req, devinfop, USBD_SHORT_XFER_OK, &alen, USBD_DEFAULT_TIMEOUT); if (err) { printf("%s: cannot get device id\n", sc->sc_dev.dv_xname); } else if (alen <= 2) { printf("%s: empty device id, no printer connected?\n", sc->sc_dev.dv_xname); } else { /* devinfop now contains an IEEE-1284 device ID */ len = ((devinfop[0] & 0xff) << 8) | (devinfop[1] & 0xff); if (len > DEVINFOSIZE - 3) len = DEVINFOSIZE - 3; devinfo[len] = 0; printf("%s: device id <", sc->sc_dev.dv_xname); ieee1284_print_id(devinfop+2); printf(">\n"); } } #endif }
/* * Attach the interface. Allocate softc structures, do * setup and ethernet/BPF attach. */ void kue_attach(device_t parent, device_t self, void *aux) { struct kue_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; char *devinfop; int s; struct ifnet *ifp; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usbd_status err; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; int i; DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev)); sc->kue_dev = self; aprint_naive("\n"); aprint_normal("\n"); devinfop = usbd_devinfo_alloc(dev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); err = usbd_set_config_no(dev, KUE_CONFIG_NO, 1); if (err) { aprint_error_dev(self, "failed to set configuration" ", err=%s\n", usbd_errstr(err)); return; } sc->kue_udev = dev; sc->kue_product = uaa->product; sc->kue_vendor = uaa->vendor; /* Load the firmware into the NIC. */ if (kue_load_fw(sc)) { aprint_error_dev(self, "loading firmware failed\n"); return; } err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &iface); if (err) { aprint_error_dev(self, "getting interface handle failed\n"); return; } sc->kue_iface = iface; id = usbd_get_interface_descriptor(iface); /* Find endpoints. */ for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { aprint_error_dev(self, "couldn't get ep %d\n", i); return; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) { sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) { sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress; } } if (sc->kue_ed[KUE_ENDPT_RX] == 0 || sc->kue_ed[KUE_ENDPT_TX] == 0) { aprint_error_dev(self, "missing endpoint\n"); return; } /* Read ethernet descriptor */ err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR, 0, &sc->kue_desc, sizeof(sc->kue_desc)); if (err) { aprint_error_dev(self, "could not read Ethernet descriptor\n"); return; } sc->kue_mcfilters = malloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, M_USBDEV, M_NOWAIT); if (sc->kue_mcfilters == NULL) { aprint_error_dev(self, "no memory for multicast filter buffer\n"); return; } s = splnet(); /* * A KLSI chip was detected. Inform the world. */ aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(sc->kue_desc.kue_macaddr)); /* Initialize interface info.*/ ifp = GET_IFP(sc); ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = kue_ioctl; ifp->if_start = kue_start; ifp->if_watchdog = kue_watchdog; strncpy(ifp->if_xname, device_xname(sc->kue_dev), IFNAMSIZ); IFQ_SET_READY(&ifp->if_snd); /* Attach the interface. */ if_attach(ifp); ether_ifattach(ifp, sc->kue_desc.kue_macaddr); rnd_attach_source(&sc->rnd_source, device_xname(sc->kue_dev), RND_TYPE_NET, 0); sc->kue_attached = true; splx(s); usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->kue_udev, sc->kue_dev); return; }
void uhidev_attach(struct device *parent, struct device *self, void *aux) { struct uhidev_softc *sc = (struct uhidev_softc *)self; struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; struct uhidev_attach_arg uha; int size, nrepid, repid, repsz; int i, repsizes[256]; void *desc = NULL; struct device *dev; sc->sc_udev = uaa->device; sc->sc_iface = uaa->iface; sc->sc_ifaceno = uaa->ifaceno; id = usbd_get_interface_descriptor(sc->sc_iface); usbd_set_idle(sc->sc_udev, sc->sc_ifaceno, 0, 0); sc->sc_iep_addr = sc->sc_oep_addr = -1; for (i = 0; i < id->bNumEndpoints; i++) { ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); if (ed == NULL) { printf("%s: could not read endpoint descriptor\n", DEVNAME(sc)); return; } DPRINTFN(10,("uhidev_attach: bLength=%d bDescriptorType=%d " "bEndpointAddress=%d-%s bmAttributes=%d wMaxPacketSize=%d" " bInterval=%d\n", ed->bLength, ed->bDescriptorType, ed->bEndpointAddress & UE_ADDR, UE_GET_DIR(ed->bEndpointAddress)==UE_DIR_IN? "in" : "out", ed->bmAttributes & UE_XFERTYPE, UGETW(ed->wMaxPacketSize), ed->bInterval)); if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->sc_iep_addr = ed->bEndpointAddress; } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->sc_oep_addr = ed->bEndpointAddress; } else { printf("%s: unexpected endpoint\n", DEVNAME(sc)); return; } } /* * Check that we found an input interrupt endpoint. * The output interrupt endpoint is optional */ if (sc->sc_iep_addr == -1) { printf("%s: no input interrupt endpoint\n", DEVNAME(sc)); return; } #ifndef SMALL_KERNEL if (uhidev_use_rdesc(sc, id, uaa->vendor, uaa->product, &desc, &size)) return; #endif /* !SMALL_KERNEL */ if (desc == NULL) { struct usb_hid_descriptor *hid; hid = usbd_get_hid_descriptor(sc->sc_udev, id); if (hid == NULL) { printf("%s: no HID descriptor\n", DEVNAME(sc)); return; } size = UGETW(hid->descrs[0].wDescriptorLength); desc = malloc(size, M_USBDEV, M_NOWAIT); if (desc == NULL) { printf("%s: no memory\n", DEVNAME(sc)); return; } if (usbd_get_report_descriptor(sc->sc_udev, sc->sc_ifaceno, desc, size)) { printf("%s: no report descriptor\n", DEVNAME(sc)); free(desc, M_USBDEV, 0); return; } } sc->sc_repdesc = desc; sc->sc_repdesc_size = size; nrepid = uhidev_maxrepid(desc, size); if (nrepid < 0) return; printf("%s: iclass %d/%d", DEVNAME(sc), id->bInterfaceClass, id->bInterfaceSubClass); if (nrepid > 0) printf(", %d report id%s", nrepid, nrepid > 1 ? "s" : ""); printf("\n"); nrepid++; sc->sc_subdevs = mallocarray(nrepid, sizeof(struct uhidev *), M_USBDEV, M_NOWAIT | M_ZERO); if (sc->sc_subdevs == NULL) { printf("%s: no memory\n", DEVNAME(sc)); return; } sc->sc_nrepid = nrepid; sc->sc_isize = 0; for (repid = 0; repid < nrepid; repid++) { repsz = hid_report_size(desc, size, hid_input, repid); DPRINTF(("uhidev_match: repid=%d, repsz=%d\n", repid, repsz)); repsizes[repid] = repsz; if (repsz > sc->sc_isize) sc->sc_isize = repsz; } sc->sc_isize += (nrepid != 1); /* one byte for the report ID */ DPRINTF(("uhidev_attach: isize=%d\n", sc->sc_isize)); uha.uaa = uaa; uha.parent = sc; uha.reportid = UHIDEV_CLAIM_ALLREPORTID; /* Look for a driver claiming all report IDs first. */ dev = config_found_sm(self, &uha, NULL, uhidevsubmatch); if (dev != NULL) { for (repid = 0; repid < nrepid; repid++) sc->sc_subdevs[repid] = (struct uhidev *)dev; return; } for (repid = 0; repid < nrepid; repid++) { DPRINTF(("%s: try repid=%d\n", __func__, repid)); if (hid_report_size(desc, size, hid_input, repid) == 0 && hid_report_size(desc, size, hid_output, repid) == 0 && hid_report_size(desc, size, hid_feature, repid) == 0) continue; uha.reportid = repid; dev = config_found_sm(self, &uha, uhidevprint, uhidevsubmatch); sc->sc_subdevs[repid] = (struct uhidev *)dev; } }
static int ubt_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct ubt_softc *sc = device_get_softc(dev); struct usb_endpoint_descriptor *ed; struct usb_interface_descriptor *id; struct usb_interface *iface; uint16_t wMaxPacketSize; uint8_t alt_index, i, j; uint8_t iface_index[2] = { 0, 1 }; device_set_usb_desc(dev); sc->sc_dev = dev; sc->sc_debug = NG_UBT_WARN_LEVEL; /* * Create Netgraph node */ if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) { UBT_ALERT(sc, "could not create Netgraph node\n"); return (ENXIO); } /* Name Netgraph node */ if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) { UBT_ALERT(sc, "could not name Netgraph node\n"); NG_NODE_UNREF(sc->sc_node); return (ENXIO); } NG_NODE_SET_PRIVATE(sc->sc_node, sc); NG_NODE_FORCE_WRITER(sc->sc_node); /* * Initialize device softc structure */ /* initialize locks */ lockinit(&sc->sc_ng_lock, "ubt ng", 0, 0); lockinit(&sc->sc_if_lock, "ubt if", 0, LK_CANRECURSE); /* initialize packet queues */ NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN); /* initialize glue task */ TASK_INIT(&sc->sc_task, 0, ubt_task, sc); /* * Configure Bluetooth USB device. Discover all required USB * interfaces and endpoints. * * USB device must present two interfaces: * 1) Interface 0 that has 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 * * 2) Interface 1 then has 2 endpoints * 1) Isochronous IN endpoint to receive SCO data * 2) Isochronous OUT endpoint to send SCO data * * Interface 1 (with isochronous endpoints) has several alternate * configurations with different packet size. */ /* * For interface #1 search alternate settings, and find * the descriptor with the largest wMaxPacketSize */ wMaxPacketSize = 0; alt_index = 0; i = 0; j = 0; ed = NULL; /* * Search through all the descriptors looking for the largest * packet size: */ while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach( usbd_get_config_descriptor(uaa->device), (struct usb_descriptor *)ed))) { if ((ed->bDescriptorType == UDESC_INTERFACE) && (ed->bLength >= sizeof(*id))) { id = (struct usb_interface_descriptor *)ed; i = id->bInterfaceNumber; j = id->bAlternateSetting; } if ((ed->bDescriptorType == UDESC_ENDPOINT) && (ed->bLength >= sizeof(*ed)) && (i == 1)) { uint16_t temp; temp = UGETW(ed->wMaxPacketSize); if (temp > wMaxPacketSize) { wMaxPacketSize = temp; alt_index = j; } } } /* Set alt configuration on interface #1 only if we found it */ if (wMaxPacketSize > 0 && usbd_set_alt_interface_index(uaa->device, 1, alt_index)) { UBT_ALERT(sc, "could not set alternate setting %d " \ "for interface 1!\n", alt_index); goto detach; } /* Setup transfers for both interfaces */ if (usbd_transfer_setup(uaa->device, iface_index, sc->sc_xfer, ubt_config, UBT_N_TRANSFER, sc, &sc->sc_if_lock)) { UBT_ALERT(sc, "could not allocate transfers\n"); goto detach; } /* Claim all interfaces belonging to the Bluetooth part */ for (i = 1;; i++) { iface = usbd_get_iface(uaa->device, i); if (iface == NULL) break; id = usbd_get_interface_descriptor(iface); if ((id != NULL) && (id->bInterfaceClass == UICLASS_WIRELESS) && (id->bInterfaceSubClass == UISUBCLASS_RF) && (id->bInterfaceProtocol == UIPROTO_BLUETOOTH)) { usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); } } return (0); /* success */ detach: ubt_detach(dev); return (ENXIO); } /* ubt_attach */