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); }
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; } }