usbd_status usbd_read_report_desc(struct usbd_interface *ifc, void **descp, int *sizep) { usb_interface_descriptor_t *id; usb_hid_descriptor_t *hid; struct usbd_device *dev; usbd_status err; usbd_interface2device_handle(ifc, &dev); id = usbd_get_interface_descriptor(ifc); if (id == NULL) return USBD_INVAL; hid = usbd_get_hid_descriptor(ifc); if (hid == NULL) return USBD_IOERROR; *sizep = UGETW(hid->descrs[0].wDescriptorLength); *descp = kmem_alloc(*sizep, KM_SLEEP); if (*descp == NULL) return USBD_NOMEM; err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, *sizep, *descp); if (err) { kmem_free(*descp, *sizep); *descp = NULL; return err; } return USBD_NORMAL_COMPLETION; }
usbd_status usbd_read_report_desc(usbd_interface_handle ifc, void **descp, int *sizep, struct malloc_type * mem) { usb_interface_descriptor_t *id; usb_hid_descriptor_t *hid; usbd_device_handle dev; usbd_status err; usbd_interface2device_handle(ifc, &dev); id = usbd_get_interface_descriptor(ifc); if (id == NULL) return (USBD_INVAL); hid = usbd_get_hid_descriptor(ifc); if (hid == NULL) return (USBD_IOERROR); *sizep = UGETW(hid->descrs[0].wDescriptorLength); *descp = malloc(*sizep, mem, M_NOWAIT); if (*descp == NULL) return (USBD_NOMEM); err = usbd_get_report_descriptor(dev, id->bInterfaceNumber, *sizep, *descp); if (err) { free(*descp, mem); *descp = NULL; return (err); } return (USBD_NORMAL_COMPLETION); }
usb_hid_descriptor_t * usbd_get_hid_descriptor(usbd_interface_handle ifc) { usb_interface_descriptor_t *idesc = usbd_get_interface_descriptor(ifc); usbd_device_handle dev; usb_config_descriptor_t *cdesc; usb_hid_descriptor_t *hd; char *p, *end; if (idesc == NULL) return (NULL); usbd_interface2device_handle(ifc, &dev); cdesc = usbd_get_config_descriptor(dev); p = (char *)idesc + idesc->bLength; end = (char *)cdesc + UGETW(cdesc->wTotalLength); for (; p < end; p += hd->bLength) { hd = (usb_hid_descriptor_t *)p; if (p + hd->bLength <= end && hd->bDescriptorType == UDESC_HID) return (hd); if (hd->bDescriptorType == UDESC_INTERFACE) break; } return (NULL); }
/* From FreeBSD's usbdi_util.c */ usbd_status usbd_set_idle(usbd_interface_handle iface, int duration, int id) { usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_IDLE; USETW2(req.wValue, duration, id); USETW(req.wIndex, ifd->bInterfaceNumber); USETW(req.wLength, 0); return (usbd_do_request(dev, &req, 0)); }
/* From FreeBSD's usbdi_util.c */ usbd_status usbd_set_protocol(usbd_interface_handle iface, int report) { usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_PROTOCOL; USETW(req.wValue, report); USETW(req.wIndex, id->bInterfaceNumber); USETW(req.wLength, 0); return (usbd_do_request(dev, &req, 0)); }
static void ata_usbchannel_setmode(device_t parent, device_t dev) { struct atausb_softc *sc = device_get_softc(GRANDPARENT(dev)); struct ata_device *atadev = device_get_softc(dev); usbd_device_handle udev; usbd_interface2device_handle(sc->iface, &udev); if (usbd_get_speed(udev) == USB_SPEED_HIGH) atadev->mode = ATA_USB2; else atadev->mode = ATA_USB1; }
void ukbd_cnpollc(void *v, int on) { struct ukbd_softc *sc = v; usbd_device_handle dev; DPRINTFN(2,("ukbd_cnpollc: sc=%p on=%d\n", v, on)); usbd_interface2device_handle(sc->sc_hdev.sc_parent->sc_iface, &dev); if (on) sc->sc_spl = splusb(); else splx(sc->sc_spl); usbd_set_polling(dev, on); }
/* * Bulk-Only transport part */ static void atausb_bbb_reset(struct atausb_softc *sc) { usbd_device_handle udev; if (atausbdebug) device_printf(sc->dev, "Bulk Reset\n"); sc->timeout = 5000; sc->state = ATAUSB_S_BBB_RESET1; usbd_interface2device_handle(sc->iface, &udev); sc->usb_request.bmRequestType = UT_WRITE_CLASS_INTERFACE; sc->usb_request.bRequest = 0xff; /* bulk-only reset */ USETW(sc->usb_request.wValue, 0); USETW(sc->usb_request.wIndex, sc->ifaceno); USETW(sc->usb_request.wLength, 0); atausb_ctl_start(sc, udev, &sc->usb_request, NULL, 0, 0, sc->transfer[ATAUSB_T_BBB_RESET1]); }
static void atausb_clear_stall(struct atausb_softc *sc, u_int8_t endpt, usbd_pipe_handle pipe, int state, usbd_xfer_handle xfer) { usbd_device_handle udev; if (atausbdebug) device_printf(sc->dev, "clear endpoint 0x%02x stall\n", endpt); usbd_interface2device_handle(sc->iface, &udev); sc->state = state; usbd_clear_endpoint_toggle(pipe); sc->usb_request.bmRequestType = UT_WRITE_ENDPOINT; sc->usb_request.bRequest = UR_CLEAR_FEATURE; USETW(sc->usb_request.wValue, UF_ENDPOINT_HALT); USETW(sc->usb_request.wIndex, endpt); USETW(sc->usb_request.wLength, 0); atausb_ctl_start(sc, udev, &sc->usb_request, NULL, 0, 0, xfer); }
static int atausb_detach(device_t dev) { struct atausb_softc *sc = device_get_softc(dev); usbd_device_handle udev; device_t *children; int nchildren, i; /* signal that device is going away */ sc->state = ATAUSB_S_DETACH; /* abort all the pipes in case there are active transfers */ usbd_interface2device_handle(sc->iface, &udev); usbd_abort_pipe(udev->default_pipe); if (sc->bulkout_pipe) usbd_abort_pipe(sc->bulkout_pipe); if (sc->bulkin_pipe) usbd_abort_pipe(sc->bulkin_pipe); if (sc->bulkirq_pipe) usbd_abort_pipe(sc->bulkirq_pipe); /* detach & delete all children */ if (!device_get_children(dev, &children, &nchildren)) { for (i = 0; i < nchildren; i++) device_delete_child(dev, children[i]); kfree(children, M_TEMP); } /* free the transfers */ for (i = 0; i < ATAUSB_T_MAX; i++) if (sc->transfer[i]) usbd_free_xfer(sc->transfer[i]); /* remove all the pipes */ if (sc->bulkout_pipe) usbd_close_pipe(sc->bulkout_pipe); if (sc->bulkin_pipe) usbd_close_pipe(sc->bulkin_pipe); if (sc->bulkirq_pipe) usbd_close_pipe(sc->bulkirq_pipe); spin_uninit(&sc->locked_mtx); return 0; }
usbd_status usbd_get_report(usbd_interface_handle iface, int type, int id, void *data, int len) { usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; DPRINTFN(4, ("usbd_get_report: len=%d\n", len)); if (ifd == NULL) return (USBD_IOERROR); usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); USETW(req.wIndex, ifd->bInterfaceNumber); USETW(req.wLength, len); return (usbd_do_request(dev, &req, data)); }
usbd_status usbd_set_protocol(usbd_interface_handle iface, int report) { usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); usbd_device_handle dev; usb_device_request_t req; DPRINTFN(4, ("usbd_set_protocol: iface=%p, report=%d, endpt=%d\n", iface, report, id->bInterfaceNumber)); if (id == NULL) return (USBD_IOERROR); usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_PROTOCOL; USETW(req.wValue, report); USETW(req.wIndex, id->bInterfaceNumber); USETW(req.wLength, 0); return (usbd_do_request(dev, &req, 0)); }
usbd_status usbd_get_protocol(struct usbd_interface *iface, uint8_t *report) { usb_interface_descriptor_t *id = usbd_get_interface_descriptor(iface); struct usbd_device *dev; usb_device_request_t req; USBHIST_FUNC(); USBHIST_CALLED(usbdebug); DPRINTFN(4, "iface=%p, endpt=%d", iface, id->bInterfaceNumber, 0, 0); if (id == NULL) return USBD_IOERROR; usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_PROTOCOL; USETW(req.wValue, 0); USETW(req.wIndex, id->bInterfaceNumber); USETW(req.wLength, 1); return usbd_do_request(dev, &req, report); }
usbd_status usbd_set_idle(struct usbd_interface *iface, int duration, int id) { usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); struct usbd_device *dev; usb_device_request_t req; USBHIST_FUNC(); USBHIST_CALLED(usbdebug); DPRINTFN(4, "duration %d id %d", duration, id, 0, 0); if (ifd == NULL) return USBD_IOERROR; usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_WRITE_CLASS_INTERFACE; req.bRequest = UR_SET_IDLE; USETW2(req.wValue, duration, id); USETW(req.wIndex, ifd->bInterfaceNumber); USETW(req.wLength, 0); return usbd_do_request(dev, &req, 0); }
usbd_status usbd_get_report(struct usbd_interface *iface, int type, int id, void *data, int len) { usb_interface_descriptor_t *ifd = usbd_get_interface_descriptor(iface); struct usbd_device *dev; usb_device_request_t req; USBHIST_FUNC(); USBHIST_CALLED(usbdebug); DPRINTFN(4, "len=%d", len, 0, 0, 0); if (ifd == NULL) return USBD_IOERROR; usbd_interface2device_handle(iface, &dev); req.bmRequestType = UT_READ_CLASS_INTERFACE; req.bRequest = UR_GET_REPORT; USETW2(req.wValue, type, id); USETW(req.wIndex, ifd->bInterfaceNumber); USETW(req.wLength, len); return usbd_do_request(dev, &req, data); }
static int ukbd_poll(keyboard_t *kbd, int on) { ukbd_state_t *state; usbd_device_handle dev; state = (ukbd_state_t *)kbd->kb_data; usbd_interface2device_handle(state->ks_iface, &dev); crit_enter(); if (on) { ++state->ks_polling; if (state->ks_polling == 1) usbd_set_polling(dev, on); } else { --state->ks_polling; if (state->ks_polling == 0) usbd_set_polling(dev, on); } crit_exit(); return 0; }
static int atausb_attach(device_t dev) { struct atausb_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); usb_interface_descriptor_t *id; usb_endpoint_descriptor_t *ed; usbd_device_handle udev; usb_device_request_t request; char devinfo[1024], *proto, *subclass; u_int8_t maxlun; int err, i; sc->dev = dev; usbd_devinfo(uaa->device, 0, devinfo); device_set_desc_copy(dev, devinfo); sc->bulkin = sc->bulkout = sc->bulkirq = -1; sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL; sc->iface = uaa->iface; sc->ifaceno = uaa->ifaceno; sc->maxlun = 0; sc->timeout = 5000; sc->locked_ch = NULL; sc->restart_ch = NULL; spin_init(&sc->locked_mtx); id = usbd_get_interface_descriptor(sc->iface); switch (id->bInterfaceProtocol) { case UIPROTO_MASS_BBB: case UIPROTO_MASS_BBB_OLD: proto = "Bulk-Only"; break; case UIPROTO_MASS_CBI: proto = "CBI"; break; case UIPROTO_MASS_CBI_I: proto = "CBI with CCI"; break; default: proto = "Unknown"; } switch (id->bInterfaceSubClass) { case UISUBCLASS_RBC: subclass = "RBC"; break; case UISUBCLASS_QIC157: case UISUBCLASS_SFF8020I: case UISUBCLASS_SFF8070I: subclass = "ATAPI"; break; case UISUBCLASS_SCSI: subclass = "SCSI"; break; case UISUBCLASS_UFI: subclass = "UFI"; break; default: subclass = "Unknown"; } device_printf(dev, "using %s over %s\n", subclass, proto); if (strcmp(proto, "Bulk-Only") || (strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI"))) return ENXIO; for (i = 0 ; i < id->bNumEndpoints ; i++) { if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) { device_printf(sc->dev, "could not read endpoint descriptor\n"); return ENXIO; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkin = ed->bEndpointAddress; } if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) { sc->bulkout = ed->bEndpointAddress; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I && UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) { sc->bulkirq = ed->bEndpointAddress; } } /* check whether we found at least the endpoints we need */ if (!sc->bulkin || !sc->bulkout) { device_printf(sc->dev, "needed endpoints not found (%d,%d)\n", sc->bulkin, sc->bulkout); atausb_detach(dev); return ENXIO; } /* open the pipes */ if (usbd_open_pipe(sc->iface, sc->bulkout, USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) { device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout); atausb_detach(dev); return ENXIO; } if (usbd_open_pipe(sc->iface, sc->bulkin, USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) { device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin); atausb_detach(dev); return ENXIO; } if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) { if (usbd_open_pipe(sc->iface, sc->bulkirq, USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) { device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n", sc->bulkirq); atausb_detach(dev); return ENXIO; } } sc->state = ATAUSB_S_ATTACH; /* alloc needed number of transfer handles */ for (i = 0; i < ATAUSB_T_MAX; i++) { sc->transfer[i] = usbd_alloc_xfer(uaa->device); if (!sc->transfer[i]) { device_printf(sc->dev, "out of memory\n"); atausb_detach(dev); return ENXIO; } } /* driver is ready to process requests here */ sc->state = ATAUSB_S_IDLE; /* get number of devices so we can add matching channels */ usbd_interface2device_handle(sc->iface, &udev); request.bmRequestType = UT_READ_CLASS_INTERFACE; request.bRequest = 0xfe; /* GET_MAX_LUN; */ USETW(request.wValue, 0); USETW(request.wIndex, sc->ifaceno); USETW(request.wLength, sizeof(maxlun)); switch ((err = usbd_do_request(udev, &request, &maxlun))) { case USBD_NORMAL_COMPLETION: if (bootverbose) device_printf(sc->dev, "maxlun=%d\n", maxlun); sc->maxlun = maxlun; break; default: if (bootverbose) device_printf(sc->dev, "get maxlun not supported %s\n", usbd_errstr(err)); } /* ata channels are children to this USB control device */ for (i = 0; i <= sc->maxlun; i++) { /* XXX TGEN devclass_find_free_unit() implementation */ int freeunit = 2; while (freeunit < devclass_get_maxunit(ata_devclass) && devclass_get_device(ata_devclass, freeunit) != NULL) freeunit++; if (!device_add_child(sc->dev, "ata", freeunit)) { device_printf(sc->dev, "failed to attach ata child device\n"); atausb_detach(dev); return ENXIO; } } bus_generic_attach(sc->dev); return 0; }