On Thu, 20 Aug 2015, Felipe Balbi wrote: > > > > - When using pattern = 1 as module parameters to compare the data, the > > > > packet size must be same between host and device's. > > > > > > why ? > > > > The gadget stores the pattern data starting from 0 for each packet it > > sends. But the host tests the pattern data starting from 0 only at the > > beginning of the transfer; the host expects the pattern to continue > > without resetting at packet boundaries (if the transfer length is > > larger than the maxpacket size). > > then that's another bug which needs to be fixed :-) Here's my attempt at a fix. Completely untested, but it does compile without errors. Peter, do you mind trying this out? Alan Stern Index: usb-4.2/drivers/usb/misc/usbtest.c =================================================================== --- usb-4.2.orig/drivers/usb/misc/usbtest.c +++ usb-4.2/drivers/usb/misc/usbtest.c @@ -303,11 +303,20 @@ static unsigned mod_pattern; module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)"); -static inline void simple_fill_buf(struct urb *urb) +static unsigned get_maxpacket(struct usb_device *udev, int pipe) +{ + struct usb_host_endpoint *ep; + + ep = usb_pipe_endpoint(udev, pipe); + return le16_to_cpup(&ep->desc.wMaxPacketSize); +} + +static void simple_fill_buf(struct urb *urb) { unsigned i; u8 *buf = urb->transfer_buffer; unsigned len = urb->transfer_buffer_length; + unsigned maxpacket; switch (pattern) { default: @@ -316,8 +325,9 @@ static inline void simple_fill_buf(struc memset(buf, 0, len); break; case 1: /* mod63 */ + maxpacket = get_maxpacket(urb->dev, urb->pipe); for (i = 0; i < len; i++) - *buf++ = (u8) (i % 63); + *buf++ = (u8) ((i % maxpacket) % 63); break; } } @@ -349,6 +359,7 @@ static int simple_check_buf(struct usbte u8 expected; u8 *buf = urb->transfer_buffer; unsigned len = urb->actual_length; + unsigned maxpacket = get_maxpacket(urb->dev, urb->pipe); int ret = check_guard_bytes(tdev, urb); if (ret) @@ -366,7 +377,7 @@ static int simple_check_buf(struct usbte * with set_interface or set_config. */ case 1: /* mod63 */ - expected = i % 63; + expected = (i % maxpacket) % 63; break; /* always fail unsupported patterns */ default: @@ -478,11 +489,12 @@ static void free_sglist(struct scatterli } static struct scatterlist * -alloc_sglist(int nents, int max, int vary) +alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe) { struct scatterlist *sg; unsigned i; unsigned size = max; + unsigned maxpacket = get_maxpacket(interface_to_usbdev(dev->intf), pipe); if (max == 0) return NULL; @@ -511,7 +523,7 @@ alloc_sglist(int nents, int max, int var break; case 1: for (j = 0; j < size; j++) - *buf++ = (u8) (j % 63); + *buf++ = (u8) ((j % maxpacket) % 63); break; } @@ -2175,7 +2187,7 @@ usbtest_ioctl(struct usb_interface *intf "TEST 5: write %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist(param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0, dev, dev->out_pipe); if (!sg) { retval = -ENOMEM; break; @@ -2193,7 +2205,7 @@ usbtest_ioctl(struct usb_interface *intf "TEST 6: read %d sglists %d entries of %d bytes\n", param->iterations, param->sglen, param->length); - sg = alloc_sglist(param->sglen, param->length, 0); + sg = alloc_sglist(param->sglen, param->length, 0, dev, dev->in_pipe); if (!sg) { retval = -ENOMEM; break; @@ -2210,7 +2222,7 @@ usbtest_ioctl(struct usb_interface *intf "TEST 7: write/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist(param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary, dev, dev->out_pipe); if (!sg) { retval = -ENOMEM; break; @@ -2227,7 +2239,7 @@ usbtest_ioctl(struct usb_interface *intf "TEST 8: read/%d %d sglists %d entries 0..%d bytes\n", param->vary, param->iterations, param->sglen, param->length); - sg = alloc_sglist(param->sglen, param->length, param->vary); + sg = alloc_sglist(param->sglen, param->length, param->vary, dev, dev->in_pipe); if (!sg) { retval = -ENOMEM; break; -- 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