Re: [PATCH] USB: usbfs: compute urb->actual_length for isochronous

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

 



Hi Alan,

On 11/8/2017 9:23 PM, Alan Stern wrote:
> The USB kerneldoc says that the actual_length field "is read in
> non-iso completion functions", but the usbfs driver uses it for all
> URB types in processcompl().  Since not all of the host controller
> drivers set actual_length for isochronous URBs, programs using usbfs
> with some host controllers don't work properly.  For example, Minas
> reports that a USB camera controlled by libusb doesn't work properly
> with a dwc2 controller.

Issue reported not by me, but by William Wu (wlf <wulf@xxxxxxxxxxxxxx>)

> 
> It doesn't seem worthwhile to change the HCDs and the documentation,
> since the in-kernel USB class drivers evidently don't rely on
> actual_length for isochronous transfers.  The easiest solution is for
> usbfs to calculate the actual_length value for itself, by adding up
> the lengths of the individual packets in an isochronous transfer.
> 
> Signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
> CC: Minas Harutyunyan <Minas.Harutyunyan@xxxxxxxxxxxx>
> Reported-and-tested-by: wlf <wulf@xxxxxxxxxxxxxx>
> CC: <stable@xxxxxxxxxxxxxxx>
> 
> ---
> 
> 
> [as1853]
> 
> 
>   drivers/usb/core/devio.c |   14 ++++++++++++++
>   1 file changed, 14 insertions(+)
> 
> Index: usb-4.x/drivers/usb/core/devio.c
> ===================================================================
> --- usb-4.x.orig/drivers/usb/core/devio.c
> +++ usb-4.x/drivers/usb/core/devio.c
> @@ -1828,6 +1828,18 @@ static int proc_unlinkurb(struct usb_dev
>   	return 0;
>   }
>   
> +static void compute_isochronous_actual_length(struct urb *urb)
> +{
> +	unsigned int i;
> +
> +	if (urb->number_of_packets > 0) {
> +		urb->actual_length = 0;
> +		for (i = 0; i < urb->number_of_packets; i++)
> +			urb->actual_length +=
> +					urb->iso_frame_desc[i].actual_length;
> +	}
> +}
> +
>   static int processcompl(struct async *as, void __user * __user *arg)
>   {
>   	struct urb *urb = as->urb;
> @@ -1835,6 +1847,7 @@ static int processcompl(struct async *as
>   	void __user *addr = as->userurb;
>   	unsigned int i;
>   
> +	compute_isochronous_actual_length(urb);
>   	if (as->userbuffer && urb->actual_length) {
>   		if (copy_urb_data_to_user(as->userbuffer, urb))
>   			goto err_out;
> @@ -2003,6 +2016,7 @@ static int processcompl_compat(struct as
>   	void __user *addr = as->userurb;
>   	unsigned int i;
>   
> +	compute_isochronous_actual_length(urb);
>   	if (as->userbuffer && urb->actual_length) {
>   		if (copy_urb_data_to_user(as->userbuffer, urb))
>   			return -EFAULT;
> 
> 

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