--- local_tree.orig/drivers/usb/core/devio.c 2004-07-26 12:17:18.000000000 +0200 +++ local_tree/drivers/usb/core/devio.c 2004-07-29 18:38:16.817733447 +0200 @@ -71,6 +71,7 @@ dev_info( dev , format , ## arg); \ } while (0) +#define MAX_BUFFER_LENGTH 16384 static inline int connected (struct usb_device *dev) { @@ -680,57 +681,79 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) { - struct usb_device *dev = ps->dev; struct usbdevfs_bulktransfer bulk; - unsigned int tmo, len1, pipe; - int len2; - unsigned char *tbuf; - int i, ret; + struct usb_device *dev = ps->dev; + unsigned char *tbuf = NULL; + struct urb *urb = NULL; + int dir_in, length, ret; + unsigned int pipe, timeout; if (copy_from_user(&bulk, arg, sizeof(bulk))) return -EFAULT; - if ((ret = findintfep(ps->dev, bulk.ep)) < 0) - return ret; - if ((ret = checkintf(ps, ret))) - return ret; - if (bulk.ep & USB_DIR_IN) - pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); - else - pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); - if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN))) + length = bulk.len; + if (length < 0 || length > MAX_BUFFER_LENGTH) return -EINVAL; - len1 = bulk.len; - if (!(tbuf = kmalloc(len1, GFP_KERNEL))) + if (!(tbuf = kmalloc(length, GFP_KERNEL))) return -ENOMEM; - tmo = (bulk.timeout * HZ + 999) / 1000; - if (bulk.ep & 0x80) { - if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) { - kfree(tbuf); - return -EINVAL; - } - i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); - if (!i && len2) { - if (copy_to_user(bulk.data, tbuf, len2)) { - kfree(tbuf); - return -EFAULT; - } + dir_in = bulk.ep & USB_DIR_IN; + if (dir_in) { + if (length && !access_ok(VERIFY_WRITE, bulk.data, length)) { + ret = -EINVAL; + goto out_free; } } else { - if (len1) { - if (copy_from_user(tbuf, bulk.data, len1)) { - kfree(tbuf); - return -EFAULT; + if (length) { + if (copy_from_user(tbuf, bulk.data, length)) { + ret = -EFAULT; + goto out_free; } } - i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); } - kfree(tbuf); - if (i < 0) { + if (!(urb = usb_alloc_urb(0, GFP_KERNEL))) { + ret = -ENOMEM; + goto out_free; + } + down(&dev->serialize); + if (!connected(dev)) { + ret = -ENODEV; + goto out_release; + } + if ((ret = findintfep(ps->dev, bulk.ep)) < 0) + goto out_release; + if ((ret = checkintf(ps, ret))) + goto out_release; + if (dir_in) + pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f); + else + pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f); + if (!usb_maxpacket(dev, pipe, !dir_in)) { + ret = -EINVAL; + goto out_release; + } + timeout = (bulk.timeout * HZ + 999) / 1000; + usb_fill_bulk_urb(urb, dev, pipe, tbuf, length, NULL, NULL); + ret = start_wait_urb(dev, urb, timeout, &length); + up(&dev->serialize); + if (ret < 0) { dev_warn(&dev->dev, "usbfs: USBDEVFS_BULK failed " - "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, i); - return i; + "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, ret); + goto out_free; + } + if (dir_in && length) { + if (copy_to_user(bulk.data, tbuf, length)) { + ret = -EFAULT; + goto out_free; + } } - return len2; + usb_free_urb(urb); + kfree(tbuf); + return length; +out_release: + up(&dev->serialize); +out_free: + usb_free_urb(urb); + kfree(tbuf); + return ret; } static int proc_resetep(struct dev_state *ps, void __user *arg) @@ -1375,16 +1398,10 @@ break; case USBDEVFS_BULK: - down(&dev->serialize); - if (!connected(dev)) { - up(&dev->serialize); - return -ENODEV; - } snoop(&dev->dev, "%s: BULK\n", __FUNCTION__); ret = proc_bulk(ps, p); if (ret >= 0) inode->i_mtime = CURRENT_TIME; - up(&dev->serialize); break; case USBDEVFS_RESETEP:
------------------------------------------------------- This SF.Net email is sponsored by OSTG. Have you noticed the changes on Linux.com, ITManagersJournal and NewsForge in the past few weeks? Now, one more big change to announce. We are now OSTG- Open Source Technology Group. Come see the changes on the new OSTG site. www.ostg.com _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel