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