On Wed, 2 Oct 2013, Robert Baldyga wrote:

> This patch fix validation of maxpacket value given in endpoint descriptor.
> Add check of maxpacket for bulk endpoints. If maxpacket is not set in
> descriptor, it's set to maximum value for given type on endpoint in used
> speed.
> 
> Correct maxpacket value is:
> 
>              FULL-SPEED        HIGH-SPEED   SUPER-SPEED
> BULK         8, 16, 32, 64     512          1024
> INTERRUPT    1..64             1..1024      1..1024
> ISOCHRONOUS  1..1023           1..1024      1..1024
> 
> Signed-off-by: Robert Baldyga <r.bald...@samsung.com>
> ---
> 
> Hello,
> 
> This is fourth version of my patch. From last version I have removed
> code reporting full speed bulk maxpacket because it's not needed since
> maxpacket check for all speeds is performed before.

It seems that this patch does a lot of things wrong.  Comments below.

> @@ -124,37 +124,90 @@ ep_matches (
>  
>       }
>  
> +     max = 0x7ff & usb_endpoint_maxp(desc);
> +
>       /*
> -      * If the protocol driver hasn't yet decided on wMaxPacketSize
> -      * and wants to know the maximum possible, provide the info.
> +      * Test if maxpacket given in descriptor isn't greater than maximum
> +      * packet size for this endpoint
>        */
> -     if (desc->wMaxPacketSize == 0)
> -             desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket);
> +     if (ep->maxpacket < max)
> +             return 0;
>  
> -     /* endpoint maxpacket size is an input parameter, except for bulk
> -      * where it's an output parameter representing the full speed limit.
> -      * the usb spec fixes high speed bulk maxpacket at 512 bytes.
> +     /*
> +      * Test if ep supports maxpacket size set in descriptor.
> +      * If the protocol driver hasn't yet decided on wMaxPacketSize
> +      * (when wMaxPacketSize == 0) and wants to know the maximum possible,
> +      * provide the info.

This disagrees with the kerneldoc for usb_ep_autoconfig().  For bulk
endpoints, wMaxPacket is always supposed to be set to the full-speed
value, regardless of what the protocol driver specifies.

>        */
> -     max = 0x7ff & usb_endpoint_maxp(desc);
>       switch (type) {
> +     case USB_ENDPOINT_XFER_BULK:
> +             /*
> +              * LIMITS:
> +              * full speed:    64 bytes
> +              * high speed:   512 bytes
> +              * super speed: 1024 bytes
> +              */
> +             if (max == 0) {
> +                     if (gadget_is_superspeed(gadget))
> +                             desc->wMaxPacketSize = cpu_to_le16(1024);
> +                     else if (gadget_is_dualspeed(gadget))
> +                             desc->wMaxPacketSize = cpu_to_le16(512);
> +                     else
> +                             desc->wMaxPacketSize = cpu_to_le16(64);

So these lines are wrong.  Also, how do you know that 64 is correct for 
full speed?  The hardware might only support 32.

> +             } else {
> +                     if (max > 1024)
> +                             return 0;
> +                     if (!gadget_is_superspeed(gadget) && max > 512)
> +                             return 0;
> +                     if (!gadget_is_dualspeed(gadget) && max > 64)
> +                             return 0;
> +             }

For bulk endpoints, you should ignore the original value in the
descriptor.  All that matters is ep->maxpacket; it will override the
value in the descriptor.

> +             break;
> +
>       case USB_ENDPOINT_XFER_INT:
> -             /* INT:  limit 64 bytes full speed, 1024 high/super speed */
> -             if (!gadget_is_dualspeed(gadget) && max > 64)
> -                     return 0;
> -             /* FALLTHROUGH */
> +             /*
> +              * LIMITS:
> +              * full speed:          64 bytes
> +              * high/super speed:  1024 bytes
> +              * multiple transactions per microframe only for super speed

The last comment is wrong.  High speed also allows multiple interrupt 
transactions in a microframe.

Also, why bother to spell out the limits in the comment?  You're not 
going to use those values; you're going to use the limit in 
ep->maxpacket.

> +              */
> +             if (max == 0) {
> +                     if (gadget_is_dualspeed(gadget))
> +                             desc->wMaxPacketSize = cpu_to_le16(1024);
> +                     else
> +                             desc->wMaxPacketSize = cpu_to_le16(64);

These values should be taken from ep->maxpacket, not from the spec.

> +             } else {
> +                     if (max > 1024)
> +                             return 0;
> +                     if (!gadget_is_superspeed(gadget))
> +                             if ((desc->wMaxPacketSize & cpu_to_le16(3<<11)))
> +                                     return 0;
> +                     if (!gadget_is_dualspeed(gadget) && max > 64)
> +                             return 0;

The first and third tests are unnecessary, because you have already 
checked that max <= ep->maxpacket.

Similar issues apply to the Isochronous case.

Alan Stern

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