patch-2.3.15 linux/drivers/usb/proc_usb.c
Next file: linux/drivers/usb/uhci-debug.c
Previous file: linux/drivers/usb/printer.c
Back to the patch index
Back to the overall index
- Lines: 277
- Date:
Wed Aug 25 15:03:54 1999
- Orig file:
v2.3.14/linux/drivers/usb/proc_usb.c
- Orig date:
Mon Aug 16 23:19:13 1999
diff -u --recursive --new-file v2.3.14/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
@@ -213,7 +213,7 @@
const int active, char *buf, int *len)
{
int i, j;
- struct usb_interface *intf;
+ struct usb_interface *interface;
if (!config) { /* getting these some in 2.3.7; none in 2.3.6 */
*len += sprintf (buf + *len, "(null Cfg. desc.)\n");
@@ -224,12 +224,12 @@
return -1;
for (i = 0; i < config->bNumInterfaces; i++) {
- intf = config->interface + i;
- if ((intf) == NULL)
+ interface = config->interface + i;
+ if (!interface)
break;
- for (j = 0; j < intf->num_altsetting; j++)
- if (usb_dump_interface (intf->altsetting + j, buf, len) < 0)
+ for (j = 0; j < interface->num_altsetting; j++)
+ if (usb_dump_interface (interface->altsetting + j, buf, len) < 0)
return -1;
}
@@ -432,6 +432,250 @@
len += sprintf (buf + len, "(none)\n");
return (len);
}
+
+/*
+ * 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)
+{
+ switch (orig) {
+ case 0:
+ file->f_pos = offset;
+ return file->f_pos;
+
+ case 1:
+ file->f_pos += offset;
+ return file->f_pos;
+
+ case 2:
+ return -EINVAL;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t usbdev_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
+ struct usb_device *dev = (struct usb_device *)dp->data;
+ ssize_t ret = 0;
+ unsigned len;
+
+ if (*ppos < 0)
+ return -EINVAL;
+ if (*ppos < sizeof(struct usb_device_descriptor)) {
+ len = sizeof(struct usb_device_descriptor);
+ if (len > nbytes)
+ len = nbytes;
+ copy_to_user_ret(buf, ((char *)&dev->descriptor) + *ppos, len, -EFAULT);
+ *ppos += len;
+ buf += len;
+ nbytes -= len;
+ ret += len;
+ }
+ return ret;
+}
+
+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 ezusb_ctrltransfer ctrl;
+ struct ezusb_bulktransfer bulk;
+ struct ezusb_setinterface setintf;
+ unsigned int len1, ep, pipe;
+ unsigned long len2;
+ unsigned char *tbuf;
+ int i;
+
+ switch (cmd) {
+ case EZUSB_CONTROL:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+ copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+ if (ctrl.dlen > PAGE_SIZE)
+ return -EINVAL;
+ if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+ return -ENOMEM;
+ if (ctrl.requesttype & 0x80) {
+ if (ctrl.dlen && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.dlen)) {
+ free_page((unsigned long)tbuf);
+ return -EINVAL;
+ }
+ i = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&ctrl, tbuf, ctrl.dlen);
+ if (!i && ctrl.dlen) {
+ copy_to_user_ret(ctrl.data, tbuf, ctrl.dlen, -EFAULT);
+ }
+ } else {
+ if (ctrl.dlen) {
+ copy_from_user_ret(tbuf, ctrl.data, ctrl.dlen, -EFAULT);
+ }
+ i = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&ctrl, tbuf, ctrl.dlen);
+ }
+ free_page((unsigned long)tbuf);
+ if (i) {
+ printk(KERN_WARNING "procusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n",
+ ctrl.requesttype, ctrl.request, ctrl.length, i);
+ return -ENXIO;
+ }
+ return 0;
+
+ case EZUSB_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 "procusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n",
+ bulk.ep, bulk.len, i);
+ return -ENXIO;
+ }
+ return len2;
+
+ case EZUSB_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 EZUSB_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;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static struct file_operations proc_usb_device_file_operations = {
+ usbdev_lseek, /* lseek */
+ usbdev_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ usbdev_ioctl, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* flush */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+static struct inode_operations proc_usb_device_inode_operations = {
+ &proc_usb_device_file_operations, /* file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* get_block */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* flushpage */
+ NULL, /* truncate */
+ NULL, /* permission */
+ NULL, /* smap */
+ NULL /* revalidate */
+};
+
+#define PROCUSB_MAXBUSSES 64
+
+static unsigned long busnumbermap[(PROCUSB_MAXBUSSES+8 * sizeof(unsigned long)-1) / (8 * sizeof(unsigned long))] = { 0, };
+
+void proc_usb_add_bus(struct usb_bus *bus)
+{
+ int bnum;
+ char buf[16];
+
+ bus->proc_busnum = -1;
+ bus->proc_entry = NULL;
+ if (!usbdir)
+ return;
+ bnum = find_first_zero_bit(busnumbermap, PROCUSB_MAXBUSSES);
+ if (bnum >= PROCUSB_MAXBUSSES)
+ return;
+ sprintf(buf, "%03d", bnum);
+ if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))
+ return;
+ set_bit(bnum, busnumbermap);
+ bus->proc_busnum = bnum;
+ bus->proc_entry->data = bus;
+}
+
+/* devices need already be removed! */
+void proc_usb_remove_bus(struct usb_bus *bus)
+{
+ if (!bus->proc_entry)
+ return;
+ remove_proc_entry(bus->proc_entry->name, usbdir);
+ clear_bit(bus->proc_busnum, busnumbermap);
+}
+
+void proc_usb_add_device(struct usb_device *dev)
+{
+ char buf[16];
+
+ dev->proc_entry = NULL;
+ if (!dev->bus->proc_entry)
+ return;
+ sprintf(buf, "%03d", dev->devnum);
+ if (!(dev->proc_entry = create_proc_entry(buf, 0, dev->bus->proc_entry)))
+ return;
+ dev->proc_entry->ops = &proc_usb_device_inode_operations;
+ dev->proc_entry->data = dev;
+}
+
+void proc_usb_remove_device(struct usb_device *dev)
+{
+ if (dev->proc_entry)
+ remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry);
+}
+
void proc_usb_cleanup (void)
{
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)