int utpms_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)uaa; usb_device_descriptor_t *udd; int i; uint16_t vendor, product; /* * We just check if the vendor and product IDs have the magic numbers * we expect. */ if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) { vendor = UGETW(udd->idVendor); product = UGETW(udd->idProduct); for (i = 0; i < nitems(utpms_devices); i++) { if (vendor == utpms_devices[i].vendor && product == utpms_devices[i].product) return (UMATCH_IFACECLASS); } } return (UMATCH_NONE); }
int umodem_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; usb_device_descriptor_t *dd; int ret; if (uaa->iface == NULL) return (UMATCH_NONE); id = usbd_get_interface_descriptor(uaa->iface); dd = usbd_get_device_descriptor(uaa->device); if (id == NULL || dd == NULL) return (UMATCH_NONE); ret = UMATCH_NONE; if (UGETW(dd->idVendor) == USB_VENDOR_KYOCERA && UGETW(dd->idProduct) == USB_PRODUCT_KYOCERA_AHK3001V && id->bInterfaceNumber == 0) ret = UMATCH_VENDOR_PRODUCT; if (ret == UMATCH_NONE && id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL && id->bInterfaceProtocol == UIPROTO_CDC_AT) ret = UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; return (ret); }
int uhub_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); /* * The subclass for hubs seems to be 0 for some and 1 for others, * so we just ignore the subclass. */ if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB) return (UMATCH_DEVCLASS_DEVSUBCLASS); return (UMATCH_NONE); }
static int uhub_match(device_t self) { struct usb_attach_arg *uaa = device_get_ivars(self); usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); DPRINTFN(5,("uhub_match, dd=%p\n", dd)); /* * The subclass for hubs seems to be 0 for some and 1 for others, * so we just ignore the subclass. */ if (uaa->iface == NULL && dd->bDeviceClass == UDCLASS_HUB) return (UMATCH_DEVCLASS_DEVSUBCLASS); return (UMATCH_NONE); }
Static void umass_fixup_yedata(struct umass_softc *sc) { usb_device_descriptor_t *dd; dd = usbd_get_device_descriptor(sc->sc_udev); /* * Revisions < 1.28 do not handle the interrupt endpoint very well. */ if (UGETW(dd->bcdDevice) < 0x128) sc->sc_wire = UMASS_WPROTO_CBI; else sc->sc_wire = UMASS_WPROTO_CBI_I; }
static int ubt_match(device_t self) { struct usb_attach_arg *uaa = device_get_ivars(self); usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device); DPRINTFN(50, "ubt_match\n"); if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product)) return UMATCH_NONE; if (dd->bDeviceClass == UDCLASS_WIRELESS && dd->bDeviceSubClass == UDSUBCLASS_RF && dd->bDeviceProtocol == UDPROTO_BLUETOOTH) return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO; return UMATCH_NONE; }
int umodem_match(struct device *parent, void *match, void *aux) { struct usb_attach_arg *uaa = aux; usb_interface_descriptor_t *id; usb_device_descriptor_t *dd; int data_iface_idx, cm_cap, acm_cap, ret = UMATCH_NONE; if (uaa->iface == NULL) return (ret); id = usbd_get_interface_descriptor(uaa->iface); dd = usbd_get_device_descriptor(uaa->device); if (id == NULL || dd == NULL) return (ret); ret = UMATCH_NONE; /* protocol of 0 so won't match the test below */ if (UGETW(dd->idVendor) == USB_VENDOR_ATMEL && UGETW(dd->idProduct) == USB_PRODUCT_ATMEL_AT91_CDC_ACM) ret = UMATCH_VENDOR_PRODUCT; if (UGETW(dd->idVendor) == USB_VENDOR_KYOCERA && UGETW(dd->idProduct) == USB_PRODUCT_KYOCERA_AHK3001V && id->bInterfaceNumber == 0) ret = UMATCH_VENDOR_PRODUCT; if (ret == UMATCH_NONE && id->bInterfaceClass == UICLASS_CDC && id->bInterfaceSubClass == UISUBCLASS_ABSTRACT_CONTROL_MODEL && id->bInterfaceProtocol == UIPROTO_CDC_AT) ret = UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO; if (ret == UMATCH_NONE) return (ret); /* umodem doesn't support devices without a data iface */ umodem_get_caps(uaa, id->bInterfaceNumber, &data_iface_idx, &cm_cap, &acm_cap); if (data_iface_idx == -1) ret = UMATCH_NONE; return (ret); }
Static void umass_fixup_yedata(struct umass_softc *sc) { usb_device_descriptor_t *dd; dd = usbd_get_device_descriptor(sc->sc_udev); /* * Revisions < 1.28 do not handle the interrupt endpoint very well. */ if (UGETW(dd->bcdDevice) < 0x128) sc->sc_wire = UMASS_WPROTO_CBI; else sc->sc_wire = UMASS_WPROTO_CBI_I; /* * Revisions < 1.28 do not have the TEST UNIT READY command * Revisions == 1.28 have a broken TEST UNIT READY */ if (UGETW(dd->bcdDevice) <= 0x128) sc->sc_busquirks |= PQUIRK_NOTUR; }
Static void umass_fixup_sony(struct umass_softc *sc) { usb_interface_descriptor_t *id; usb_device_descriptor_t *dd; id = usbd_get_interface_descriptor(sc->sc_iface); if (id->bInterfaceSubClass == 0xff) { dd = usbd_get_device_descriptor(sc->sc_udev); /* * Many Sony DSC cameras share the same product ID, so the * revision number is used to distinguish between them. */ switch (UGETW(dd->bcdDevice)) { case 0x611: /* Sony DSC-T10, rev 6.11 */ case 0x600: /* Sony DSC-W50, rev 6.00 */ case 0x500: /* Sony DSC-P41, rev 5.00 */ sc->sc_cmd = UMASS_CPROTO_UFI; break; default: sc->sc_cmd = UMASS_CPROTO_SCSI; } } }
static int ugen_ioctl_post(struct usb_fifo *f, u_long cmd, void *addr, int fflags) { union { struct usb_interface_descriptor *idesc; struct usb_alt_interface *ai; struct usb_device_descriptor *ddesc; struct usb_config_descriptor *cdesc; struct usb_device_stats *stat; struct usb_fs_init *pinit; struct usb_fs_uninit *puninit; uint32_t *ptime; void *addr; int *pint; } u; struct usb_device_descriptor *dtemp; struct usb_config_descriptor *ctemp; struct usb_interface *iface; int error = 0; uint8_t n; u.addr = addr; DPRINTFN(6, "cmd=0x%08lx\n", cmd); switch (cmd) { case USB_DISCOVER: usb_needs_explore_all(); break; case USB_SETDEBUG: if (!(fflags & FWRITE)) { error = EPERM; break; } usb_debug = *(int *)addr; break; case USB_GET_CONFIG: *(int *)addr = f->udev->curr_config_index; break; case USB_SET_CONFIG: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_set_config(f, *(int *)addr); break; case USB_GET_ALTINTERFACE: iface = usbd_get_iface(f->udev, u.ai->uai_interface_index); if (iface && iface->idesc) { u.ai->uai_alt_index = iface->alt_index; } else { error = EINVAL; } break; case USB_SET_ALTINTERFACE: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_set_interface(f, u.ai->uai_interface_index, u.ai->uai_alt_index); break; case USB_GET_DEVICE_DESC: dtemp = usbd_get_device_descriptor(f->udev); if (!dtemp) { error = EIO; break; } *u.ddesc = *dtemp; break; case USB_GET_CONFIG_DESC: ctemp = usbd_get_config_descriptor(f->udev); if (!ctemp) { error = EIO; break; } *u.cdesc = *ctemp; break; case USB_GET_FULL_DESC: error = ugen_get_cdesc(f, addr); break; case USB_GET_STRING_DESC: error = ugen_get_sdesc(f, addr); break; case USB_GET_IFACE_DRIVER: error = ugen_get_iface_driver(f, addr); break; case USB_REQUEST: case USB_DO_REQUEST: if (!(fflags & FWRITE)) { error = EPERM; break; } error = ugen_do_request(f, addr); break; case USB_DEVICEINFO: case USB_GET_DEVICEINFO: error = usb_gen_fill_deviceinfo(f, addr); break; case USB_DEVICESTATS: for (n = 0; n != 4; n++) { u.stat->uds_requests_fail[n] = f->udev->bus->stats_err.uds_requests[n]; u.stat->uds_requests_ok[n] = f->udev->bus->stats_ok.uds_requests[n]; } break; case USB_DEVICEENUMERATE: error = ugen_re_enumerate(f); break; case USB_GET_PLUGTIME: *u.ptime = f->udev->plugtime; break; case USB_CLAIM_INTERFACE: case USB_RELEASE_INTERFACE: /* TODO */ break; case USB_IFACE_DRIVER_ACTIVE: /* TODO */ *u.pint = 0; break; case USB_IFACE_DRIVER_DETACH: /* TODO */ error = priv_check(curthread, PRIV_DRIVER); if (error) { break; } error = EINVAL; break; case USB_SET_POWER_MODE: error = ugen_set_power_mode(f, *u.pint); break; case USB_GET_POWER_MODE: *u.pint = ugen_get_power_mode(f); break; case USB_SET_PORT_ENABLE: error = ugen_do_port_feature(f, *u.pint, 1, UHF_PORT_ENABLE); break; case USB_SET_PORT_DISABLE: error = ugen_do_port_feature(f, *u.pint, 0, UHF_PORT_ENABLE); break; case USB_FS_INIT: /* verify input parameters */ if (u.pinit->pEndpoints == NULL) { error = EINVAL; break; } if (u.pinit->ep_index_max > 127) { error = EINVAL; break; } if (u.pinit->ep_index_max == 0) { error = EINVAL; break; } if (f->fs_xfer != NULL) { error = EBUSY; break; } if (f->dev_ep_index != 0) { error = EINVAL; break; } if (ugen_fifo_in_use(f, fflags)) { error = EBUSY; break; } error = usb_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max); if (error) { break; } f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) * u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO); if (f->fs_xfer == NULL) { usb_fifo_free_buffer(f); error = ENOMEM; break; } f->fs_ep_max = u.pinit->ep_index_max; f->fs_ep_ptr = u.pinit->pEndpoints; break; case USB_FS_UNINIT: if (u.puninit->dummy != 0) { error = EINVAL; break; } error = ugen_fs_uninit(f); break; default: mtx_lock(f->priv_mtx); error = ugen_iface_ioctl(f, cmd, addr, fflags); mtx_unlock(f->priv_mtx); break; } DPRINTFN(6, "error=%d\n", error); return (error); }
void uticom_attach_hook(void *arg) { struct uticom_softc *sc = arg; 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; /* Initialize endpoints. */ uca.bulkin = uca.bulkout = -1; sc->sc_intr_number = -1; sc->sc_intr_pipe = NULL; dd = usbd_get_device_descriptor(sc->sc_udev); 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(sc->sc_udev, UTICOM_CONFIG_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, 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; } err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("%s: failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); 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); usbd_deactivate(sc->sc_udev); 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); usbd_deactivate(sc->sc_udev); return; } } status = uticom_download_fw(sc, uca.bulkout, sc->sc_udev); if (status) { printf("%s: firmware download failed\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } else { DPRINTF(("%s: firmware download succeeded\n", sc->sc_dev.dv_xname)); } status = usbd_reload_device_desc(sc->sc_udev); if (status) { printf("%s: error reloading device descriptor\n", sc->sc_dev.dv_xname); usbd_deactivate(sc->sc_udev); return; } fwload_done: dd = usbd_get_device_descriptor(sc->sc_udev); DPRINTF(("%s: uticom_attach: num of configurations %d\n", sc->sc_dev.dv_xname, dd->bNumConfigurations)); err = usbd_set_config_index(sc->sc_udev, UTICOM_ACTIVE_INDEX, 1); if (err) { printf("%s: failed to set configuration: %s\n", sc->sc_dev.dv_xname, 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 (XXX: multiport chips are not supported yet). */ err = usbd_device2interface_handle(sc->sc_udev, UTICOM_IFACE_INDEX, &sc->sc_iface); if (err) { printf("%s: failed to get interface: %s\n", sc->sc_dev.dv_xname, usbd_errstr(err)); usbd_deactivate(sc->sc_udev); 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("%s: no endpoint descriptor for %d\n", sc->sc_dev.dv_xname, i); usbd_deactivate(sc->sc_udev); 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); usbd_deactivate(sc->sc_udev); 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(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; } 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); 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; } 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 = sc->sc_udev; uca.iface = sc->sc_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)); usbd_deactivate(sc->sc_udev); 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((struct device *)sc, &uca, ucomprint, ucomsubmatch); }
void utpms_attach(struct device *parent, struct device *self, void *aux) { struct utpms_softc *sc = (struct utpms_softc *)self; struct uhidev_attach_arg *uha = (struct uhidev_attach_arg *)aux; struct wsmousedev_attach_args a; struct utpms_dev *pd; usb_device_descriptor_t *udd; int i; uint16_t vendor, product; sc->sc_datalen = UTPMS_DATA_LEN; sc->sc_hdev.sc_udev = uha->uaa->device; /* Fill in device-specific parameters. */ if ((udd = usbd_get_device_descriptor(uha->parent->sc_udev)) != NULL) { product = UGETW(udd->idProduct); vendor = UGETW(udd->idVendor); for (i = 0; i < nitems(utpms_devices); i++) { pd = &utpms_devices[i]; if (product == pd->product && vendor == pd->vendor) { switch (pd->type) { case FOUNTAIN: printf(": Fountain"); break; case GEYSER1: printf(": Geyser"); break; case GEYSER2: sc->sc_type = GEYSER2; sc->sc_datalen = 64; sc->sc_y_sensors = 9; printf(": Geyser 2"); break; } printf(" Trackpad\n"); sc->sc_noise = pd->noise; sc->sc_threshold = pd->threshold; sc->sc_x_factor = pd->x_factor; sc->sc_x_sensors = pd->x_sensors; sc->sc_y_factor = pd->y_factor; sc->sc_y_sensors = pd->y_sensors; break; } } } if (sc->sc_x_sensors <= 0 || sc->sc_x_sensors > UTPMS_X_SENSORS || sc->sc_y_sensors <= 0 || sc->sc_y_sensors > UTPMS_Y_SENSORS) { printf(": unexpected sensors configuration (%d:%d)\n", sc->sc_x_sensors, sc->sc_y_sensors); return; } sc->sc_hdev.sc_intr = utpms_intr; sc->sc_hdev.sc_parent = uha->parent; sc->sc_hdev.sc_report_id = uha->reportid; sc->sc_status = 0; a.accessops = &utpms_accessops; a.accesscookie = sc; sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); }
void uftdi_attach(device_t parent, device_t self, void *aux) { struct uftdi_softc *sc = device_private(self); struct usb_attach_arg *uaa = aux; usbd_device_handle dev = uaa->device; usbd_interface_handle iface; usb_device_descriptor_t *ddesc; usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; char *devinfop; const char *devname = device_xname(self); int i,idx; usbd_status err; struct ucom_attach_args uca; DPRINTFN(10,("\nuftdi_attach: sc=%p\n", sc)); aprint_naive("\n"); aprint_normal("\n"); devinfop = usbd_devinfo_alloc(dev, 0); aprint_normal_dev(self, "%s\n", devinfop); usbd_devinfo_free(devinfop); /* Move the device into the configured state. */ err = usbd_set_config_index(dev, UFTDI_CONFIG_INDEX, 1); if (err) { aprint_error("\n%s: failed to set configuration, err=%s\n", devname, usbd_errstr(err)); goto bad; } sc->sc_dev = self; sc->sc_udev = dev; sc->sc_numports = 1; sc->sc_type = UFTDI_TYPE_8U232AM; /* most devices are post-8U232AM */ sc->sc_hdrlen = 0; if (uaa->vendor == USB_VENDOR_FTDI && uaa->product == USB_PRODUCT_FTDI_SERIAL_8U100AX) { sc->sc_type = UFTDI_TYPE_SIO; sc->sc_hdrlen = 1; } ddesc = usbd_get_device_descriptor(dev); sc->sc_chiptype = UGETW(ddesc->bcdDevice); switch (sc->sc_chiptype) { case 0x500: /* 2232D */ case 0x700: /* 2232H */ sc->sc_numports = 2; break; case 0x800: /* 4232H */ sc->sc_numports = 4; break; case 0x200: /* 232/245AM */ case 0x400: /* 232/245BL */ case 0x600: /* 232/245R */ default: break; } for (idx = UFTDI_IFACE_INDEX; idx < sc->sc_numports; idx++) { err = usbd_device2interface_handle(dev, idx, &iface); if (err) { aprint_error( "\n%s: failed to get interface idx=%d, err=%s\n", devname, idx, usbd_errstr(err)); goto bad; } id = usbd_get_interface_descriptor(iface); sc->sc_iface[idx] = iface; uca.bulkin = uca.bulkout = -1; uca.ibufsize = uca.obufsize = 0; for (i = 0; i < id->bNumEndpoints; i++) { int addr, dir, attr; ed = usbd_interface2endpoint_descriptor(iface, i); if (ed == NULL) { aprint_error_dev(self, "could not read endpoint descriptor: %s\n", usbd_errstr(err)); goto bad; } addr = ed->bEndpointAddress; dir = UE_GET_DIR(ed->bEndpointAddress); attr = ed->bmAttributes & UE_XFERTYPE; if (dir == UE_DIR_IN && attr == UE_BULK) { uca.bulkin = addr; uca.ibufsize = UGETW(ed->wMaxPacketSize); if (uca.ibufsize >= UFTDI_MAX_IBUFSIZE) uca.ibufsize = UFTDI_MAX_IBUFSIZE; } else if (dir == UE_DIR_OUT && attr == UE_BULK) { uca.bulkout = addr; uca.obufsize = UGETW(ed->wMaxPacketSize) - sc->sc_hdrlen; if (uca.obufsize >= UFTDI_MAX_OBUFSIZE) uca.obufsize = UFTDI_MAX_OBUFSIZE; /* Limit length if we have a 6-bit header. */ if ((sc->sc_hdrlen > 0) && (uca.obufsize > UFTDIOBUFSIZE)) uca.obufsize = UFTDIOBUFSIZE; } else { aprint_error_dev(self, "unexpected endpoint\n"); goto bad; } } if (uca.bulkin == -1) { aprint_error_dev(self, "Could not find data bulk in\n"); goto bad; } if (uca.bulkout == -1) { aprint_error_dev(self, "Could not find data bulk out\n"); goto bad; } uca.portno = FTDI_PIT_SIOA + idx; /* bulkin, bulkout set above */ if (uca.ibufsize == 0) uca.ibufsize = UFTDIIBUFSIZE; uca.ibufsizepad = uca.ibufsize; if (uca.obufsize == 0) uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen; uca.opkthdrlen = sc->sc_hdrlen; uca.device = dev; uca.iface = iface; uca.methods = &uftdi_methods; uca.arg = sc; uca.info = NULL; DPRINTF(("uftdi: in=0x%x out=0x%x isize=0x%x osize=0x%x\n", uca.bulkin, uca.bulkout, uca.ibufsize, uca.obufsize)); sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL, &uca, ucomprint, ucomsubmatch); } usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev); return; bad: DPRINTF(("uftdi_attach: ATTACH ERROR\n")); sc->sc_dying = 1; return; }
int ugen_do_ioctl(struct ugen_softc *sc, int endpt, u_long cmd, caddr_t addr, int flag, struct proc *p) { struct ugen_endpoint *sce; int err; struct usbd_interface *iface; struct usb_config_desc *cd; usb_config_descriptor_t *cdesc; struct usb_interface_desc *id; usb_interface_descriptor_t *idesc; struct usb_endpoint_desc *ed; usb_endpoint_descriptor_t *edesc; struct usb_alt_interface *ai; struct usb_string_desc *si; u_int8_t conf, alt; DPRINTFN(5, ("ugenioctl: cmd=%08lx\n", cmd)); if (usbd_is_dying(sc->sc_udev)) return (EIO); switch (cmd) { case FIONBIO: /* All handled in the upper FS layer. */ return (0); case USB_SET_SHORT_XFER: if (endpt == USB_CONTROL_ENDPOINT) return (EINVAL); /* This flag only affects read */ sce = &sc->sc_endpoints[endpt][IN]; if (sce == NULL || sce->pipeh == NULL) return (EINVAL); if (*(int *)addr) sce->state |= UGEN_SHORT_OK; else sce->state &= ~UGEN_SHORT_OK; return (0); case USB_SET_TIMEOUT: sce = &sc->sc_endpoints[endpt][IN]; if (sce == NULL) return (EINVAL); sce->timeout = *(int *)addr; sce = &sc->sc_endpoints[endpt][OUT]; if (sce == NULL) return (EINVAL); sce->timeout = *(int *)addr; return (0); default: break; } if (endpt != USB_CONTROL_ENDPOINT) return (EINVAL); switch (cmd) { #ifdef UGEN_DEBUG case USB_SETDEBUG: ugendebug = *(int *)addr; break; #endif case USB_GET_CONFIG: err = usbd_get_config(sc->sc_udev, &conf); if (err) return (EIO); *(int *)addr = conf; break; case USB_SET_CONFIG: if (!(flag & FWRITE)) return (EPERM); err = ugen_set_config(sc, *(int *)addr); switch (err) { case USBD_NORMAL_COMPLETION: break; case USBD_IN_USE: return (EBUSY); default: return (EIO); } break; case USB_GET_ALTINTERFACE: ai = (struct usb_alt_interface *)addr; err = usbd_device2interface_handle(sc->sc_udev, ai->uai_interface_index, &iface); if (err) return (EINVAL); idesc = usbd_get_interface_descriptor(iface); if (idesc == NULL) return (EIO); ai->uai_alt_no = idesc->bAlternateSetting; break; case USB_SET_ALTINTERFACE: if (!(flag & FWRITE)) return (EPERM); ai = (struct usb_alt_interface *)addr; err = usbd_device2interface_handle(sc->sc_udev, ai->uai_interface_index, &iface); if (err) return (EINVAL); err = ugen_set_interface(sc, ai->uai_interface_index, ai->uai_alt_no); if (err) return (EINVAL); break; case USB_GET_NO_ALT: ai = (struct usb_alt_interface *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, ai->uai_config_index, 0); if (cdesc == NULL) return (EINVAL); idesc = usbd_find_idesc(cdesc, ai->uai_interface_index, 0); if (idesc == NULL) { free(cdesc, M_TEMP, 0); return (EINVAL); } ai->uai_alt_no = usbd_get_no_alts(cdesc, idesc->bInterfaceNumber); free(cdesc, M_TEMP, 0); break; case USB_GET_DEVICE_DESC: *(usb_device_descriptor_t *)addr = *usbd_get_device_descriptor(sc->sc_udev); break; case USB_GET_CONFIG_DESC: cd = (struct usb_config_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, cd->ucd_config_index, 0); if (cdesc == NULL) return (EINVAL); cd->ucd_desc = *cdesc; free(cdesc, M_TEMP, 0); break; case USB_GET_INTERFACE_DESC: id = (struct usb_interface_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, id->uid_config_index, 0); if (cdesc == NULL) return (EINVAL); if (id->uid_config_index == USB_CURRENT_CONFIG_INDEX && id->uid_alt_index == USB_CURRENT_ALT_INDEX) alt = ugen_get_alt_index(sc, id->uid_interface_index); else alt = id->uid_alt_index; idesc = usbd_find_idesc(cdesc, id->uid_interface_index, alt); if (idesc == NULL) { free(cdesc, M_TEMP, 0); return (EINVAL); } id->uid_desc = *idesc; free(cdesc, M_TEMP, 0); break; case USB_GET_ENDPOINT_DESC: ed = (struct usb_endpoint_desc *)addr; cdesc = usbd_get_cdesc(sc->sc_udev, ed->ued_config_index, 0); if (cdesc == NULL) return (EINVAL); if (ed->ued_config_index == USB_CURRENT_CONFIG_INDEX && ed->ued_alt_index == USB_CURRENT_ALT_INDEX) alt = ugen_get_alt_index(sc, ed->ued_interface_index); else alt = ed->ued_alt_index; edesc = usbd_find_edesc(cdesc, ed->ued_interface_index, alt, ed->ued_endpoint_index); if (edesc == NULL) { free(cdesc, M_TEMP, 0); return (EINVAL); } ed->ued_desc = *edesc; free(cdesc, M_TEMP, 0); break; case USB_GET_FULL_DESC: { int len; struct iovec iov; struct uio uio; struct usb_full_desc *fd = (struct usb_full_desc *)addr; int error; cdesc = usbd_get_cdesc(sc->sc_udev, fd->ufd_config_index, &len); if (cdesc == NULL) return (EINVAL); if (len > fd->ufd_size) len = fd->ufd_size; iov.iov_base = (caddr_t)fd->ufd_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = UIO_READ; uio.uio_procp = p; error = uiomove((void *)cdesc, len, &uio); free(cdesc, M_TEMP, 0); return (error); } case USB_GET_STRING_DESC: { int len; si = (struct usb_string_desc *)addr; err = usbd_get_string_desc(sc->sc_udev, si->usd_string_index, si->usd_language_id, &si->usd_desc, &len); if (err) return (EINVAL); break; } case USB_DO_REQUEST: { struct usb_ctl_request *ur = (void *)addr; int len = UGETW(ur->ucr_request.wLength); struct iovec iov; struct uio uio; void *ptr = 0; int error = 0; if (!(flag & FWRITE)) return (EPERM); /* Avoid requests that would damage the bus integrity. */ if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_ADDRESS) || (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE && ur->ucr_request.bRequest == UR_SET_CONFIG) || (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE && ur->ucr_request.bRequest == UR_SET_INTERFACE)) return (EINVAL); if (len < 0 || len > 32767) return (EINVAL); if (len != 0) { iov.iov_base = (caddr_t)ur->ucr_data; iov.iov_len = len; uio.uio_iov = &iov; uio.uio_iovcnt = 1; uio.uio_resid = len; uio.uio_offset = 0; uio.uio_segflg = UIO_USERSPACE; uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ? UIO_READ : UIO_WRITE; uio.uio_procp = p; ptr = malloc(len, M_TEMP, M_WAITOK); if (uio.uio_rw == UIO_WRITE) { error = uiomove(ptr, len, &uio); if (error) goto ret; } } sce = &sc->sc_endpoints[endpt][IN]; err = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen, sce->timeout); if (err) { error = EIO; goto ret; } /* Only if USBD_SHORT_XFER_OK is set. */ if (len > ur->ucr_actlen) len = ur->ucr_actlen; if (len != 0) { if (uio.uio_rw == UIO_READ) { error = uiomove(ptr, len, &uio); if (error) goto ret; } } ret: if (ptr) free(ptr, M_TEMP, 0); return (error); } case USB_GET_DEVICEINFO: usbd_fill_deviceinfo(sc->sc_udev, (struct usb_device_info *)addr, 1); break; default: return (EINVAL); } return (0); }
void ubcmtp_attach(struct device *parent, struct device *self, void *aux) { struct ubcmtp_softc *sc = (struct ubcmtp_softc *)self; struct usb_attach_arg *uaa = aux; struct usbd_device *dev = uaa->device; struct wsmousedev_attach_args a; usb_device_descriptor_t *udd; int i; sc->sc_udev = uaa->device; sc->sc_status = 0; if ((udd = usbd_get_device_descriptor(dev)) == NULL) { printf("ubcmtp: failed getting device descriptor\n"); return; } for (i = 0; i < nitems(ubcmtp_devices); i++) { if (uaa->vendor == ubcmtp_devices[i].vendor && ( uaa->product == ubcmtp_devices[i].ansi || uaa->product == ubcmtp_devices[i].iso || uaa->product == ubcmtp_devices[i].jis)) { sc->dev_type = &ubcmtp_devices[i]; DPRINTF("%s: attached to 0x%x/0x%x type %d\n", sc->sc_dev.dv_xname, uaa->vendor, uaa->product, sc->dev_type->type); break; } } if (sc->dev_type == NULL) { /* how did we match then? */ printf("%s: failed looking up device in table\n", sc->sc_dev.dv_xname); return; } switch (sc->dev_type->type) { case UBCMTP_TYPE1: sc->tp_maxlen = UBCMTP_TYPE1_TPLEN; sc->tp_offset = UBCMTP_TYPE1_TPOFF; sc->tp_ifacenum = UBCMTP_TYPE1_TPIFACE; /* button offsets */ sc->bt_maxlen = sizeof(struct ubcmtp_button); sc->bt_ifacenum = UBCMTP_TYPE1_BTIFACE; break; case UBCMTP_TYPE2: sc->tp_maxlen = UBCMTP_TYPE2_TPLEN; sc->tp_offset = UBCMTP_TYPE2_TPOFF; sc->tp_ifacenum = UBCMTP_TYPE2_TPIFACE; break; case UBCMTP_TYPE3: sc->tp_maxlen = UBCMTP_TYPE3_TPLEN; sc->tp_offset = UBCMTP_TYPE3_TPOFF; sc->tp_ifacenum = UBCMTP_TYPE3_TPIFACE; break; } a.accessops = &ubcmtp_accessops; a.accesscookie = sc; sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); }
int kue_load_fw(struct kue_softc *sc) { usb_device_descriptor_t *dd; usbd_status err; struct kue_firmware *fw; u_char *buf; size_t buflen; DPRINTFN(1,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__)); /* * First, check if we even need to load the firmware. * If the device was still attached when the system was * rebooted, it may already have firmware loaded in it. * If this is the case, we don't need to do it again. * And in fact, if we try to load it again, we'll hang, * so we have to avoid this condition if we don't want * to look stupid. * * We can test this quickly by checking the bcdRevision * code. The NIC will return a different revision code if * it's probed while the firmware is still loaded and * running. */ if ((dd = usbd_get_device_descriptor(sc->kue_udev)) == NULL) return (EIO); if (UGETW(dd->bcdDevice) >= KUE_WARM_REV) { printf("%s: warm boot, no firmware download\n", sc->kue_dev.dv_xname); return (0); } err = loadfirmware("kue", &buf, &buflen); if (err) { printf("%s: failed loadfirmware of file %s: errno %d\n", sc->kue_dev.dv_xname, "kue", err); return (err); } fw = (struct kue_firmware *)buf; printf("%s: cold boot, downloading firmware\n", sc->kue_dev.dv_xname); /* Load code segment */ DPRINTFN(1,("%s: kue_load_fw: download code_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[0], ntohl(fw->codeseglen)); if (err) { printf("%s: failed to load code segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF, 0); return (EIO); } /* Load fixup segment */ DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[ntohl(fw->codeseglen)], ntohl(fw->fixseglen)); if (err) { printf("%s: failed to load fixup segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF, 0); return (EIO); } /* Send trigger command. */ DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n", sc->kue_dev.dv_xname)); err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN, 0, (void *)&fw->data[ntohl(fw->codeseglen) + ntohl(fw->fixseglen)], ntohl(fw->trigseglen)); if (err) { printf("%s: failed to load trigger segment: %s\n", sc->kue_dev.dv_xname, usbd_errstr(err)); free(buf, M_DEVBUF, 0); return (EIO); } free(buf, M_DEVBUF, 0); usbd_delay_ms(sc->kue_udev, 10); /* * Reload device descriptor. * Why? The chip without the firmware loaded returns * one revision code. The chip with the firmware * loaded and running returns a *different* revision * code. This confuses the quirk mechanism, which is * dependent on the revision data. */ (void)usbd_reload_device_desc(sc->kue_udev); DPRINTFN(1,("%s: %s: done\n", sc->kue_dev.dv_xname, __func__)); /* Reset the adapter. */ kue_reset(sc); return (0); }