|
@@ -1301,23 +1301,20 @@ static int proc_releaseinterface(struct dev_state *ps, void __user *arg)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
|
|
|
|
|
+static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
|
|
{
|
|
{
|
|
- struct usbdevfs_ioctl ctrl;
|
|
|
|
int size;
|
|
int size;
|
|
void *buf = NULL;
|
|
void *buf = NULL;
|
|
int retval = 0;
|
|
int retval = 0;
|
|
struct usb_interface *intf = NULL;
|
|
struct usb_interface *intf = NULL;
|
|
struct usb_driver *driver = NULL;
|
|
struct usb_driver *driver = NULL;
|
|
|
|
|
|
- /* get input parameters and alloc buffer */
|
|
|
|
- if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
|
|
|
|
- return -EFAULT;
|
|
|
|
- if ((size = _IOC_SIZE (ctrl.ioctl_code)) > 0) {
|
|
|
|
|
|
+ /* alloc buffer */
|
|
|
|
+ if ((size = _IOC_SIZE (ctl->ioctl_code)) > 0) {
|
|
if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
|
|
if ((buf = kmalloc (size, GFP_KERNEL)) == NULL)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
- if ((_IOC_DIR(ctrl.ioctl_code) & _IOC_WRITE)) {
|
|
|
|
- if (copy_from_user (buf, ctrl.data, size)) {
|
|
|
|
|
|
+ if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) {
|
|
|
|
+ if (copy_from_user (buf, ctl->data, size)) {
|
|
kfree(buf);
|
|
kfree(buf);
|
|
return -EFAULT;
|
|
return -EFAULT;
|
|
}
|
|
}
|
|
@@ -1333,9 +1330,9 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
|
|
|
|
|
if (ps->dev->state != USB_STATE_CONFIGURED)
|
|
if (ps->dev->state != USB_STATE_CONFIGURED)
|
|
retval = -EHOSTUNREACH;
|
|
retval = -EHOSTUNREACH;
|
|
- else if (!(intf = usb_ifnum_to_if (ps->dev, ctrl.ifno)))
|
|
|
|
|
|
+ else if (!(intf = usb_ifnum_to_if (ps->dev, ctl->ifno)))
|
|
retval = -EINVAL;
|
|
retval = -EINVAL;
|
|
- else switch (ctrl.ioctl_code) {
|
|
|
|
|
|
+ else switch (ctl->ioctl_code) {
|
|
|
|
|
|
/* disconnect kernel driver from interface */
|
|
/* disconnect kernel driver from interface */
|
|
case USBDEVFS_DISCONNECT:
|
|
case USBDEVFS_DISCONNECT:
|
|
@@ -1367,7 +1364,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
|
if (driver == NULL || driver->ioctl == NULL) {
|
|
if (driver == NULL || driver->ioctl == NULL) {
|
|
retval = -ENOTTY;
|
|
retval = -ENOTTY;
|
|
} else {
|
|
} else {
|
|
- retval = driver->ioctl (intf, ctrl.ioctl_code, buf);
|
|
|
|
|
|
+ retval = driver->ioctl (intf, ctl->ioctl_code, buf);
|
|
if (retval == -ENOIOCTLCMD)
|
|
if (retval == -ENOIOCTLCMD)
|
|
retval = -ENOTTY;
|
|
retval = -ENOTTY;
|
|
}
|
|
}
|
|
@@ -1376,15 +1373,42 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
|
|
|
|
|
|
/* cleanup and return */
|
|
/* cleanup and return */
|
|
if (retval >= 0
|
|
if (retval >= 0
|
|
- && (_IOC_DIR (ctrl.ioctl_code) & _IOC_READ) != 0
|
|
|
|
|
|
+ && (_IOC_DIR (ctl->ioctl_code) & _IOC_READ) != 0
|
|
&& size > 0
|
|
&& size > 0
|
|
- && copy_to_user (ctrl.data, buf, size) != 0)
|
|
|
|
|
|
+ && copy_to_user (ctl->data, buf, size) != 0)
|
|
retval = -EFAULT;
|
|
retval = -EFAULT;
|
|
|
|
|
|
kfree(buf);
|
|
kfree(buf);
|
|
return retval;
|
|
return retval;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int proc_ioctl_default(struct dev_state *ps, void __user *arg)
|
|
|
|
+{
|
|
|
|
+ struct usbdevfs_ioctl ctrl;
|
|
|
|
+
|
|
|
|
+ if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+ return proc_ioctl(ps, &ctrl);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#ifdef CONFIG_COMPAT
|
|
|
|
+static int proc_ioctl_compat(struct dev_state *ps, void __user *arg)
|
|
|
|
+{
|
|
|
|
+ struct usbdevfs_ioctl32 __user *uioc;
|
|
|
|
+ struct usbdevfs_ioctl ctrl;
|
|
|
|
+ u32 udata;
|
|
|
|
+
|
|
|
|
+ uioc = compat_ptr(arg);
|
|
|
|
+ if (get_user(ctrl.ifno, &uioc->ifno) ||
|
|
|
|
+ get_user(ctrl.ioctl_code, &uioc->ioctl_code) ||
|
|
|
|
+ __get_user(udata, &uioc->data))
|
|
|
|
+ return -EFAULT;
|
|
|
|
+ ctrl.data = compat_ptr(udata);
|
|
|
|
+
|
|
|
|
+ return proc_ioctl(ps, &ctrl);
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* NOTE: All requests here that have interface numbers as parameters
|
|
* NOTE: All requests here that have interface numbers as parameters
|
|
* are assuming that somehow the configuration has been prevented from
|
|
* are assuming that somehow the configuration has been prevented from
|
|
@@ -1485,6 +1509,10 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
|
|
ret = proc_reapurbnonblock_compat(ps, p);
|
|
ret = proc_reapurbnonblock_compat(ps, p);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case USBDEVFS_IOCTL32:
|
|
|
|
+ snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
|
|
|
|
+ ret = proc_ioctl_compat(ps, p);
|
|
|
|
+ break;
|
|
#endif
|
|
#endif
|
|
|
|
|
|
case USBDEVFS_DISCARDURB:
|
|
case USBDEVFS_DISCARDURB:
|
|
@@ -1519,7 +1547,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
|
|
|
|
|
|
case USBDEVFS_IOCTL:
|
|
case USBDEVFS_IOCTL:
|
|
snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
|
|
snoop(&dev->dev, "%s: IOCTL\n", __FUNCTION__);
|
|
- ret = proc_ioctl(ps, p);
|
|
|
|
|
|
+ ret = proc_ioctl_default(ps, p);
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
usb_unlock_device(dev);
|
|
usb_unlock_device(dev);
|