patch-2.3.16 linux/drivers/usb/proc_usb.c
Next file: linux/drivers/usb/uhci.c
Previous file: linux/drivers/usb/printer.c
Back to the patch index
Back to the overall index
- Lines: 222
- Date:
Fri Aug 27 11:46:35 1999
- Orig file:
v2.3.15/linux/drivers/usb/proc_usb.c
- Orig date:
Thu Aug 26 13:05:39 1999
diff -u --recursive --new-file v2.3.15/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
@@ -1,6 +1,7 @@
/*
* drivers/usb/proc_usb.c
* (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
*
* 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
@@ -48,6 +49,9 @@
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/list.h>
+#include <linux/bitops.h>
+#include <asm/uaccess.h>
+#include <linux/mm.h>
#include "usb.h"
@@ -191,7 +195,7 @@
* which ones are active, if any)
* 2. Add proc_usb_init() call from usb-core.c.
* 3. proc_usb as a MODULE ?
- * 4. use __initfunc() ?
+ * 4. use __init ?
* 5. add <halted> status to each endpoint line
*/
@@ -435,12 +439,7 @@
/*
* proc entry for every device
- * sailer@ife.ee.ethz.ch
*/
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include "ezusb.h"
static long long usbdev_lseek(struct file * file, long long offset, int orig)
{
@@ -484,8 +483,12 @@
return ret;
}
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+/* note: this is a compatibility kludge that will vanish soon. */
+#include "ezusb.h"
+
+static int usbdev_ioctl_ezusbcompat(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
+ static unsigned obsolete_warn = 0;
struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
struct usb_device *dev = (struct usb_device *)dp->data;
struct ezusb_ctrltransfer ctrl;
@@ -498,6 +501,11 @@
switch (cmd) {
case EZUSB_CONTROL:
+ if (obsolete_warn < 20) {
+ printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_CONTROL ioctl\n",
+ current->pid, current->comm);
+ obsolete_warn++;
+ }
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
@@ -529,6 +537,11 @@
return 0;
case EZUSB_BULK:
+ if (obsolete_warn < 20) {
+ printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_BULK ioctl\n",
+ current->pid, current->comm);
+ obsolete_warn++;
+ }
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
@@ -567,6 +580,11 @@
return len2;
case EZUSB_RESETEP:
+ if (obsolete_warn < 20) {
+ printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_RESETEP ioctl\n",
+ current->pid, current->comm);
+ obsolete_warn++;
+ }
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
get_user_ret(ep, (unsigned int *)arg, -EFAULT);
@@ -576,12 +594,131 @@
return 0;
case EZUSB_SETINTERFACE:
+ if (obsolete_warn < 20) {
+ printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl\n",
+ current->pid, current->comm);
+ obsolete_warn++;
+ }
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
return -EINVAL;
return 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
+
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
+ struct usb_device *dev = (struct usb_device *)dp->data;
+ struct usb_proc_ctrltransfer ctrl;
+ struct usb_proc_bulktransfer bulk;
+ struct usb_proc_setinterface setintf;
+ unsigned int len1, ep, pipe;
+ unsigned long len2;
+ unsigned char *tbuf;
+ int i;
+
+ switch (cmd) {
+ case USB_PROC_CONTROL:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+ if (ctrl.length > PAGE_SIZE)
+ return -EINVAL;
+ if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ if (ctrl.requesttype & 0x80) {
+ if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
+ free_page((unsigned long)tbuf);
+ return -EINVAL;
+ }
+ i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request,
+ ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
+ ctrl.length);
+ if (!i && ctrl.length) {
+ copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
+ }
+ } else {
+ if (ctrl.length) {
+ copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
+ }
+ i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request,
+ ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
+ ctrl.length);
+ }
+ free_page((unsigned long)tbuf);
+ if (i) {
+ printk(KERN_WARNING "/proc/bus/usb: USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d\n",
+ ctrl.requesttype, ctrl.request, ctrl.length, i);
+ return -ENXIO;
+ }
+ return 0;
+
+ case USB_PROC_BULK:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+ if (bulk.ep & 0x80)
+ pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+ else
+ pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+ if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
+ return -EINVAL;
+ len1 = bulk.len;
+ if (len1 > PAGE_SIZE)
+ len1 = PAGE_SIZE;
+ if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ if (bulk.ep & 0x80) {
+ if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+ free_page((unsigned long)tbuf);
+ return -EINVAL;
+ }
+ i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+ if (!i && len2) {
+ copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+ }
+ } else {
+ if (len1) {
+ copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+ }
+ i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2);
+ }
+ free_page((unsigned long)tbuf);
+ if (i) {
+ printk(KERN_WARNING "/proc/bus/usb: USB_PROC_BULK failed ep 0x%x len %u ret %d\n",
+ bulk.ep, bulk.len, i);
+ return -ENXIO;
+ }
+ return len2;
+
+ case USB_PROC_RESETEP:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+ if ((ep & ~0x80) >= 16)
+ return -EINVAL;
+ usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
+ return 0;
+
+ case USB_PROC_SETINTERFACE:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
+ if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
+ return -EINVAL;
+ return 0;
+
+ case EZUSB_CONTROL:
+ case EZUSB_BULK:
+ case EZUSB_RESETEP:
+ case EZUSB_SETINTERFACE:
+ return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg);
}
return -ENOIOCTLCMD;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)