Enable the usbtest driver to test peripherals with super speed isoc endpoints. So far this has only been tested with the modified gadget zero with isoc endpoint support. A module parameter 'need_iso' is added to force the driver to look for an alternate interface containing isoc endpoints, instead of stopping at the first one with bulk endpoints. Signed-off-by: Paul Zimmerman <paulz@xxxxxxxxxxxx> --- drivers/usb/misc/usbtest.c | 52 ++++++++++++++++++++++++++++++++----------- 1 files changed, 38 insertions(+), 14 deletions(-) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 8fe901d..64a93e5 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -11,6 +11,10 @@ #include <linux/usb.h> +static unsigned need_iso; +module_param(need_iso, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(need_iso, "require ISO endpoints"); + /*-------------------------------------------------------------------------*/ /* FIXME make these public somewhere; usbdevfs.h? */ @@ -64,6 +68,7 @@ struct usbtest_dev { int in_iso_pipe; int out_iso_pipe; struct usb_endpoint_descriptor *iso_in, *iso_out; + struct usb_ss_ep_comp_descriptor *iso_in_comp, *iso_out_comp; struct mutex lock; #define TBUF_SIZE 256 @@ -137,12 +142,17 @@ try_iso: iso_out = e; } } - if ((in && out) || iso_in || iso_out) + if (need_iso && (!iso_in || !iso_out) && + tmp != intf->num_altsetting - 1) + continue; + if ((in && out) || iso_in || iso_out) goto found; } return -EINVAL; found: + if (need_iso) + dev->info->alt = tmp; udev = testdev_to_usbdev(dev); if (alt->desc.bAlternateSetting != 0) { tmp = usb_set_interface(udev, @@ -160,6 +170,7 @@ found: } if (iso_in) { dev->iso_in = &iso_in->desc; + dev->iso_in_comp = &iso_in->ss_ep_comp; dev->in_iso_pipe = usb_rcvisocpipe(udev, iso_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); @@ -167,6 +178,7 @@ found: if (iso_out) { dev->iso_out = &iso_out->desc; + dev->iso_out_comp = &iso_out->ss_ep_comp; dev->out_iso_pipe = usb_sndisocpipe(udev, iso_out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); @@ -201,7 +213,8 @@ static struct urb *usbtest_alloc_urb( if (!urb) return urb; usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback, NULL); - urb->interval = (udev->speed == USB_SPEED_HIGH) + urb->interval = (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE; urb->transfer_flags = transfer_flags; @@ -476,9 +489,9 @@ static int perform_sglist( while (retval == 0 && iterations-- > 0) { retval = usb_sg_init(req, udev, pipe, - (udev->speed == USB_SPEED_HIGH) - ? (INTERRUPT_RATE << 3) - : INTERRUPT_RATE, + (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) + ? (INTERRUPT_RATE << 3) : INTERRUPT_RATE, sg, nents, 0, GFP_KERNEL); if (retval) @@ -1583,6 +1596,7 @@ static struct urb *iso_alloc_urb( struct usb_device *udev, int pipe, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp, long bytes, unsigned offset ) @@ -1594,6 +1608,8 @@ static struct urb *iso_alloc_urb( return NULL; maxp = 0x7ff & usb_endpoint_maxp(desc); maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); + maxp *= USB_SS_MULT(comp->bmAttributes); + maxp *= 1 + comp->bMaxBurst; packets = DIV_ROUND_UP(bytes, maxp); urb = usb_alloc_urb(packets, GFP_KERNEL); @@ -1639,7 +1655,8 @@ static struct urb *iso_alloc_urb( static int test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, - int pipe, struct usb_endpoint_descriptor *desc, unsigned offset) + int pipe, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp, unsigned offset) { struct iso_context context; struct usb_device *udev; @@ -1662,11 +1679,12 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, dev_info(&dev->intf->dev, "... iso period %d %sframes, wMaxPacket %04x\n", 1 << (desc->bInterval - 1), - (udev->speed == USB_SPEED_HIGH) ? "micro" : "", + (udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? "micro" : "", usb_endpoint_maxp(desc)); for (i = 0; i < param->sglen; i++) { - urbs[i] = iso_alloc_urb(udev, pipe, desc, + urbs[i] = iso_alloc_urb(udev, pipe, desc, comp, param->length, offset); if (!urbs[i]) { status = -ENOMEM; @@ -1679,7 +1697,8 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, dev_info(&dev->intf->dev, "... total %lu msec (%lu packets)\n", (packets * (1 << (desc->bInterval - 1))) - / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1), + / ((udev->speed == USB_SPEED_HIGH || + udev->speed == USB_SPEED_SUPER) ? 8 : 1), packets); spin_lock_irq(&context.lock); @@ -2062,7 +2081,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->sglen, param->length); /* FIRMWARE: iso sink */ retval = test_iso_queue(dev, param, - dev->out_iso_pipe, dev->iso_out, 0); + dev->out_iso_pipe, dev->iso_out, + dev->iso_out_comp, 0); break; /* iso read tests */ @@ -2075,7 +2095,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->sglen, param->length); /* FIRMWARE: iso source */ retval = test_iso_queue(dev, param, - dev->in_iso_pipe, dev->iso_in, 0); + dev->in_iso_pipe, dev->iso_in, + dev->iso_in_comp, 0); break; /* FIXME scatterlist cancel (needs helper thread) */ @@ -2156,7 +2177,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->iterations, param->sglen, param->length); retval = test_iso_queue(dev, param, - dev->out_iso_pipe, dev->iso_out, 1); + dev->out_iso_pipe, dev->iso_out, + dev->iso_out_comp, 1); break; case 23: @@ -2167,7 +2189,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) param->iterations, param->sglen, param->length); retval = test_iso_queue(dev, param, - dev->in_iso_pipe, dev->iso_in, 1); + dev->in_iso_pipe, dev->iso_in, + dev->iso_in_comp, 1); break; /* unlink URBs from a bulk-OUT queue */ @@ -2511,6 +2534,8 @@ static int __init usbtest_init(void) if (vendor) pr_debug("params: vend=0x%04x prod=0x%04x\n", vendor, product); #endif + if (need_iso) + gz_info.iso = 1; return usb_register(&usbtest_driver); } module_init(usbtest_init); @@ -2523,4 +2548,3 @@ module_exit(usbtest_exit); MODULE_DESCRIPTION("USB Core/HCD Testing Driver"); MODULE_LICENSE("GPL"); - -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html