示例#1
0
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;
}
示例#2
0
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);
}
示例#3
0
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;
	}
}