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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to