[RFC PATCH 2/2] usb: usbtest: add super speed isoc support to usbtest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

---
 drivers/usb/misc/usbtest.c |   60 ++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 959145b..8ddfb91 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,16 @@ 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:
+	dev->info->alt = tmp;
 	udev = testdev_to_usbdev(dev);
 	if (alt->desc.bAlternateSetting != 0) {
 		tmp = usb_set_interface(udev,
@@ -160,6 +169,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 +177,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 +212,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 +488,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)
@@ -1025,7 +1037,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
 		case 13:	/* short read, resembling case 10 */
 			req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
 			/* last data packet "should" be DATA1, not DATA0 */
-			len = 1024 - udev->descriptor.bMaxPacketSize0;
+			if (udev->speed == USB_SPEED_SUPER)
+				len = 512;
+			else
+				len = 1024 - udev->descriptor.bMaxPacketSize0;
 			expected = -EREMOTEIO;
 			break;
 		case 14:	/* short read; try to fill the last packet */
@@ -1388,7 +1403,10 @@ static int halt_simple(struct usbtest_dev *dev)
 	int		retval = 0;
 	struct urb	*urb;
 
-	urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
+	if (testdev_to_usbdev(dev)->speed == USB_SPEED_SUPER)
+		urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 1024);
+	else
+		urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
 	if (urb == NULL)
 		return -ENOMEM;
 
@@ -1576,6 +1594,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
 )
@@ -1587,6 +1606,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);
@@ -1632,7 +1653,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;
@@ -1655,11 +1677,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;
@@ -1672,7 +1695,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);
@@ -2055,7 +2079,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 */
@@ -2068,7 +2093,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) */
@@ -2149,7 +2175,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:
@@ -2160,7 +2187,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 */
@@ -2376,6 +2404,7 @@ static struct usbtest_info gz_info = {
 	.name		= "Linux gadget zero",
 	.autoconf	= 1,
 	.ctrl_out	= 1,
+	.iso		= 1,
 	.alt		= 0,
 };
 
@@ -2516,4 +2545,3 @@ module_exit(usbtest_exit);
 
 MODULE_DESCRIPTION("USB Core/HCD Testing Driver");
 MODULE_LICENSE("GPL");
-
-- 
1.7.4.4

--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux