Merge tag 'usb-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
[sfrench/cifs-2.6.git] / drivers / usb / core / devio.c
index 4ae667d8c238549d85372aacbdda8d9e188176c2..705c573d0257e28b5142070caaca17e06e5a25fd 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*****************************************************************************/
 
 /*
@@ -5,20 +6,6 @@
  *
  *      Copyright (C) 1999-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
  *  This file implements the usbfs/x/y files, where
  *  x is the bus number and y the device number.
  *
@@ -1833,6 +1820,18 @@ static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg)
        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;
@@ -1840,6 +1839,7 @@ static int processcompl(struct async *as, void __user * __user *arg)
        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;
@@ -2008,6 +2008,7 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
        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;