Example #1
0
usbd_status
usbd_intr_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
		   u_int16_t flags, u_int32_t timeout, void *buf,
		   u_int32_t *size, const char *lbl)
{
	usbd_status err;

	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout, NULL);

	DPRINTFN(1, ("usbd_intr_transfer: start transfer %d bytes\n", *size));
	err = usbd_sync_transfer_sig(xfer);

	usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);

	DPRINTFN(1,("usbd_intr_transfer: transferred %d\n", *size));
	if (err) {
		DPRINTF(("usbd_intr_transfer: error=%d\n", err));
		usbd_clear_endpoint_stall(pipe);
	}
	USBHIST_LOG(usbdebug, "<- done err %d", xfer, err, 0, 0);

	return (err);
}
Example #2
0
usbd_status
usbd_get_string_desc(struct usbd_device *dev, int sindex, int langid,
		     usb_string_descriptor_t *sdesc, int *sizep)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;
	usbd_status err;
	int actlen;

	req.bmRequestType = UT_READ_DEVICE;
	req.bRequest = UR_GET_DESCRIPTOR;
	USETW2(req.wValue, UDESC_STRING, sindex);
	USETW(req.wIndex, langid);
	USETW(req.wLength, 2);	/* only size byte first */
	err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
		&actlen, USBD_DEFAULT_TIMEOUT);
	if (err)
		return err;

	if (actlen < 2)
		return USBD_SHORT_XFER;

	USETW(req.wLength, sdesc->bLength);	/* the whole string */
 	err = usbd_do_request_flags(dev, &req, sdesc, USBD_SHORT_XFER_OK,
 		&actlen, USBD_DEFAULT_TIMEOUT);
	if (err)
		return err;

	if (actlen != sdesc->bLength) {
		DPRINTF("expected %d, got %d", sdesc->bLength, actlen, 0, 0);
	}

	*sizep = actlen;
	return USBD_NORMAL_COMPLETION;
}
Example #3
0
usb_interface_descriptor_t *
usbd_find_idesc(usb_config_descriptor_t *cd, int ifaceidx, int altidx)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	char *p = (char *)cd;
	char *end = p + UGETW(cd->wTotalLength);
	usb_interface_descriptor_t *d;
	int curidx, lastidx, curaidx = 0;

	for (curidx = lastidx = -1; p < end; ) {
		d = (usb_interface_descriptor_t *)p;
		DPRINTFN(4, "idx=%d(%d) altidx=%d(%d)", ifaceidx, curidx,
		    altidx, curaidx);
		DPRINTFN(4, "len=%d type=%d", d->bLength, d->bDescriptorType,
		    0, 0);
		if (d->bLength == 0) /* bad descriptor */
			break;
		p += d->bLength;
		if (p <= end && d->bDescriptorType == UDESC_INTERFACE) {
			if (d->bInterfaceNumber != lastidx) {
				lastidx = d->bInterfaceNumber;
				curidx++;
				curaidx = 0;
			} else
				curaidx++;
			if (ifaceidx == curidx && altidx == curaidx)
				return d;
		}
	}
	return NULL;
}
Example #4
0
usbd_status
usbd_reload_device_desc(struct usbd_device *dev)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_descriptor_t *udd = &dev->ud_ddesc;
	usbd_status err;

	/* Get the full device descriptor. */
	err = usbd_get_device_desc(dev, udd);
	if (err)
		return err;

	DPRINTFN(15, "bLength             %5u", udd->bLength, 0, 0, 0);
	DPRINTFN(15, "bDescriptorType     %5u", udd->bDescriptorType, 0, 0, 0);
	DPRINTFN(15, "bcdUSB              %2x.%02x", udd->bcdUSB[1],
	    udd->bcdUSB[0], 0, 0);
	DPRINTFN(15, "bDeviceClass        %5u", udd->bDeviceClass, 0, 0, 0);
	DPRINTFN(15, "bDeviceSubClass     %5u", udd->bDeviceSubClass, 0, 0, 0);
	DPRINTFN(15, "bDeviceProtocol     %5u", udd->bDeviceProtocol, 0, 0, 0);
	DPRINTFN(15, "bMaxPacketSize0     %5u", udd->bMaxPacketSize, 0, 0, 0);
	DPRINTFN(15, "idVendor           0x%04x", udd->idVendor, 0, 0, 0);
	DPRINTFN(15, "idProduct          0x%04x", udd->idProduct, 0, 0, 0);
	DPRINTFN(15, "bcdDevice           %2x.%02x", udd->bcdDevice[1],
	    udd->bcdDevice[0], 0, 0);
	DPRINTFN(15, "iManufacturer       %5u", udd->iManufacturer, 0, 0, 0);
	DPRINTFN(15, "iProduct            %5u", udd->iProduct, 0, 0, 0);
	DPRINTFN(15, "iSerial             %5u", udd->iSerialNumber, 0, 0, 0);
	DPRINTFN(15, "bNumConfigurations  %5u", udd->bNumConfigurations, 0, 0,
	    0);

	/* Figure out what's wrong with this device. */
	dev->ud_quirks = usbd_find_quirk(udd);

	return USBD_NORMAL_COMPLETION;
}
Example #5
0
void
usb_detach_broadcast(device_t dv, kcondvar_t *cv)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(1, "for dv %p", dv, 0, 0, 0);
	cv_broadcast(cv);
}
Example #6
0
usbd_status
usbd_get_device_desc(struct usbd_device *dev, usb_device_descriptor_t *d)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	return (usbd_get_desc(dev, UDESC_DEVICE,
			     0, USB_DEVICE_DESCRIPTOR_SIZE, d));
}
Example #7
0
void
usb_detach_wakeupold(device_t dv)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(1, "for dv %p", dv, 0, 0, 0);
	wakeup(dv); /* XXXSMP ok */
}
Example #8
0
usbd_status
usbd_get_config_desc_full(struct usbd_device *dev, int conf, void *d, int size)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(3, "conf=%d", conf, 0, 0, 0);
	return usbd_get_desc(dev, UDESC_CONFIG, conf, size, d);
}
Example #9
0
void
usb_detach_waitold(device_t dv)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(1, "waiting for dv %p", dv, 0, 0, 0);
	if (tsleep(dv, PZERO, "usbdet", hz * 60)) /* XXXSMP ok */
		printf("usb_detach_waitold: %s didn't detach\n",
			device_xname(dv));
	DPRINTFN(1, "done", 0, 0, 0, 0);
}
Example #10
0
void
usb_detach_wait(device_t dv, kcondvar_t *cv, kmutex_t *lock)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(1, "waiting for dv %p", dv, 0, 0, 0);
	if (cv_timedwait(cv, lock, hz * 60))	// dv, PZERO, "usbdet", hz * 60
		printf("usb_detach_wait: %s didn't detach\n",
			device_xname(dv));
	DPRINTFN(1, "done", 0, 0, 0, 0);
}
Example #11
0
usbd_status
usbd_get_device_status(struct usbd_device *dev, usb_status_t *st)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	req.bmRequestType = UT_READ_DEVICE;
	req.bRequest = UR_GET_STATUS;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, sizeof(usb_status_t));
	return usbd_do_request(dev, &req, st);
}
Example #12
0
usbd_status
usbd_set_port_feature(struct usbd_device *dev, int port, int sel)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p port %d sel %d", dev, sel, 0, 0);
	req.bmRequestType = UT_WRITE_CLASS_OTHER;
	req.bRequest = UR_SET_FEATURE;
	USETW(req.wValue, sel);
	USETW(req.wIndex, port);
	USETW(req.wLength, 0);
	return usbd_do_request(dev, &req, 0);
}
Example #13
0
usbd_status
usbd_clear_hub_feature(struct usbd_device *dev, int sel)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p sel %d", dev, sel, 0, 0);
	req.bmRequestType = UT_WRITE_CLASS_DEVICE;
	req.bRequest = UR_CLEAR_FEATURE;
	USETW(req.wValue, sel);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	return usbd_do_request(dev, &req, 0);
}
Example #14
0
usbd_status
usbd_get_port_status(struct usbd_device *dev, int port, usb_port_status_t *ps)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p port %d", dev, port, 0, 0);
	req.bmRequestType = UT_READ_CLASS_OTHER;
	req.bRequest = UR_GET_STATUS;
	USETW(req.wValue, 0);
	USETW(req.wIndex, port);
	USETW(req.wLength, sizeof(*ps));
	return usbd_do_request(dev, &req, ps);
}
Example #15
0
usbd_status
usbd_set_address(struct usbd_device *dev, int addr)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p addr %d", dev, addr, 0, 0);
	req.bmRequestType = UT_WRITE_DEVICE;
	req.bRequest = UR_SET_ADDRESS;
	USETW(req.wValue, addr);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	return usbd_do_request(dev, &req, 0);
}
Example #16
0
usbd_status
usbd_get_config(struct usbd_device *dev, uint8_t *conf)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p", dev, 0, 0, 0);
	req.bmRequestType = UT_READ_DEVICE;
	req.bRequest = UR_GET_CONFIG;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 1);
	return usbd_do_request(dev, &req, conf);
}
Example #17
0
usbd_status
usbd_set_port_u2_timeout(struct usbd_device *dev, int port, int timeout)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p port %d timeout %d", dev, port, timeout, 0);
	req.bmRequestType = UT_WRITE_CLASS_OTHER;
	req.bRequest = UR_SET_FEATURE;
	USETW(req.wValue, UHF_PORT_U2_TIMEOUT);
	USETW2(req.wIndex, timeout, port);
	USETW(req.wLength, 0);
	return usbd_do_request(dev, &req, 0);
}
Example #18
0
Static usbd_status
usbd_set_config(struct usbd_device *dev, int conf)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTFN(5, "dev %p conf %d", dev, conf, 0, 0);

	req.bmRequestType = UT_WRITE_DEVICE;
	req.bRequest = UR_SET_CONFIG;
	USETW(req.wValue, conf);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	return usbd_do_request(dev, &req, 0);
}
Example #19
0
usbd_status
usbd_get_report_descriptor(struct usbd_device *dev, int ifcno,
			   int size, void *d)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;

	DPRINTF("dev %p ifcno %d size %d", dev, ifcno, size, 0);
	req.bmRequestType = UT_READ_INTERFACE;
	req.bRequest = UR_GET_DESCRIPTOR;
	USETW2(req.wValue, UDESC_REPORT, 0); /* report id should be 0 */
	USETW(req.wIndex, ifcno);
	USETW(req.wLength, size);
	return usbd_do_request(dev, &req, d);
}
Example #20
0
void
usbd_remove_device(struct usbd_device *dev, struct usbd_port *up)
{

	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTF("dev %p up %p", dev, up, 0, 0);

	if (dev->ud_pipe0 != NULL)
		usbd_kill_pipe(dev->ud_pipe0);
	up->up_dev = NULL;
	dev->ud_bus->ub_devices[dev->ud_addr] = NULL;

	kmem_free(dev, sizeof(*dev));
}
Example #21
0
usbd_status
usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc)
{
	usb_device_request_t req;

	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	DPRINTFN(3,"type=%d, index=%d, len=%d", type, index, len, 0);

	req.bmRequestType = UT_READ_DEVICE;
	req.bRequest = UR_GET_DESCRIPTOR;
	USETW2(req.wValue, type, index);
	USETW(req.wIndex, 0);
	USETW(req.wLength, len);
	return usbd_do_request(dev, &req, desc);
}
Example #22
0
usbd_status
usbd_get_config_desc(struct usbd_device *dev, int confidx,
		     usb_config_descriptor_t *d)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usbd_status err;

	DPRINTFN(3, "confidx=%d", confidx, 0, 0, 0);
	err = usbd_get_desc(dev, UDESC_CONFIG, confidx,
			    USB_CONFIG_DESCRIPTOR_SIZE, d);
	if (err)
		return err;
	if (d->bDescriptorType != UDESC_CONFIG) {
		DPRINTFN(1, "confidx=%d, bad desc len=%d type=%d",
		    confidx, d->bLength, d->bDescriptorType, 0);
		return USBD_INVAL;
	}
	return USBD_NORMAL_COMPLETION;
}
Example #23
0
usbd_status
usbd_setup_pipe_flags(struct usbd_device *dev, struct usbd_interface *iface,
    struct usbd_endpoint *ep, int ival, struct usbd_pipe **pipe, uint8_t flags)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	struct usbd_pipe *p;
	usbd_status err;

	p = kmem_alloc(dev->ud_bus->ub_pipesize, KM_SLEEP);
	DPRINTFN(1, "dev=%p addr=%d iface=%p ep=%p pipe=%p", dev, dev->ud_addr, iface, ep);
	if (p == NULL) {
		DPRINTFN(1, "(nomem)", 0, 0, 0, 0);
		return USBD_NOMEM;
	}
	p->up_dev = dev;
	p->up_iface = iface;
	p->up_endpoint = ep;
	ep->ue_refcnt++;
	p->up_intrxfer = NULL;
	p->up_running = 0;
	p->up_aborting = 0;
	p->up_serialise = true;
	p->up_repeat = 0;
	p->up_interval = ival;
	p->up_flags = flags;
	p->up_serialise = true;
	SIMPLEQ_INIT(&p->up_queue);
	err = dev->ud_bus->ub_methods->ubm_open(p);
	if (err) {
		DPRINTF("endpoint=0x%x failed, error=%d",
		    ep->ue_edesc->bEndpointAddress, err, 0, 0);
		kmem_intr_free(p, dev->ud_bus->ub_pipesize);
		return err;
	}

	KASSERT(p->up_methods->upm_start || p->up_serialise == false);

	usb_init_task(&p->up_async_task, usbd_clear_endpoint_stall_task, p,
	    USB_TASKQ_MPSAFE);
	DPRINTFN(1, "pipe=%p", p, 0, 0, 0);
	*pipe = p;
	return USBD_NORMAL_COMPLETION;
}
Example #24
0
usbd_status
usbd_reset_port(struct usbd_device *dev, int port, usb_port_status_t *ps)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_device_request_t req;
	usbd_status err;
	int n;

	req.bmRequestType = UT_WRITE_CLASS_OTHER;
	req.bRequest = UR_SET_FEATURE;
	USETW(req.wValue, UHF_PORT_RESET);
	USETW(req.wIndex, port);
	USETW(req.wLength, 0);
	err = usbd_do_request(dev, &req, 0);
	DPRINTFN(1, "port %d reset done, error=%d", port, err, 0, 0);
	if (err)
		return err;
	n = 10;
	do {
		/* Wait for device to recover from reset. */
		usbd_delay_ms(dev, USB_PORT_RESET_DELAY);
		err = usbd_get_port_status(dev, port, ps);
		if (err) {
			DPRINTF("get status failed %d", err, 0, 0, 0);
			return err;
		}
		/* If the device disappeared, just give up. */
		if (!(UGETW(ps->wPortStatus) & UPS_CURRENT_CONNECT_STATUS))
			return USBD_NORMAL_COMPLETION;
	} while ((UGETW(ps->wPortChange) & UPS_C_PORT_RESET) == 0 && --n > 0);
	if (n == 0)
		return USBD_TIMEOUT;
	err = usbd_clear_port_feature(dev, port, UHF_C_PORT_RESET);
#ifdef USB_DEBUG
	if (err)
		DPRINTF("clear port feature failed %d", err, 0, 0, 0);
#endif

	/* Wait for the device to recover from reset. */
	usbd_delay_ms(dev, USB_PORT_RESET_RECOVERY);
	return err;
}
Example #25
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);
}
Example #26
0
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);
}
Example #27
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);
}
Example #28
0
usbd_status
usbd_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
    uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
{
	usbd_status err;

	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);

	usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
	DPRINTFN(1, "start transfer %d bytes", *size, 0, 0, 0);
	err = usbd_sync_transfer_sig(xfer);

	usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
	DPRINTFN(1, "transferred %d", *size, 0, 0, 0);
	if (err) {
		usbd_clear_endpoint_stall(pipe);
	}
	USBHIST_LOG(usbdebug, "<- done xfer %p err %d", xfer, err, 0, 0);

	return err;
}
Example #29
0
usbd_status
usbd_set_config_no(struct usbd_device *dev, int no, int msg)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	usb_config_descriptor_t cd;
	usbd_status err;
	int index;

	if (no == USB_UNCONFIG_NO)
		return usbd_set_config_index(dev, USB_UNCONFIG_INDEX, msg);

	DPRINTFN(5, "%d", no, 0, 0, 0);
	/* Figure out what config index to use. */
	for (index = 0; index < dev->ud_ddesc.bNumConfigurations; index++) {
		err = usbd_get_config_desc(dev, index, &cd);
		if (err)
			return err;
		if (cd.bConfigurationValue == no)
			return usbd_set_config_index(dev, index, msg);
	}
	return USBD_INVAL;
}
Example #30
0
/*
 * Called from process context when we discover that a port has
 * been disconnected.
 */
int
usb_disconnect_port(struct usbd_port *up, device_t parent, int flags)
{
	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
	struct usbd_device *dev = up->up_dev;
	device_t subdev;
	char subdevname[16];
	const char *hubname = device_xname(parent);
	int i, rc;

	DPRINTFN(3, "up=%p dev=%p port=%d", up, dev, up->up_portno, 0);

	if (dev == NULL) {
		return 0;
	}

	if (dev->ud_subdevlen > 0) {
		DPRINTFN(3, "disconnect subdevs", 0, 0, 0, 0);
		for (i = 0; i < dev->ud_subdevlen; i++) {
			if ((subdev = dev->ud_subdevs[i]) == NULL)
				continue;
			strlcpy(subdevname, device_xname(subdev),
			    sizeof(subdevname));
			if ((rc = config_detach(subdev, flags)) != 0)
				return rc;
			printf("%s: at %s", subdevname, hubname);
			if (up->up_portno != 0)
				printf(" port %d", up->up_portno);
			printf(" (addr %d) disconnected\n", dev->ud_addr);
		}
		KASSERT(!dev->ud_nifaces_claimed);
	}

	usbd_add_dev_event(USB_EVENT_DEVICE_DETACH, dev);
	dev->ud_bus->ub_devices[dev->ud_addr] = NULL;
	up->up_dev = NULL;
	usb_free_device(dev);
	return 0;
}