📄 proc_usb.c
字号:
* count = device count at this level */ /* If this is the root hub, display the bandwidth information */ if (level == 0) start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC, (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC, bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs); /* show the descriptor information for this device */ start = usb_dump_desc(start, end, usbdev); if (start > end) return start + sprintf(start, "(truncated)\n"); /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { if (start > end) return start; if (usbdev->children[chix]) start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt); } return start;}static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos){ struct list_head *buslist; struct usb_bus *bus; char *page, *end; ssize_t ret = 0; unsigned int pos, len; if (*ppos < 0) return -EINVAL; if (nbytes <= 0) return 0; if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; if (!(page = (char*) __get_free_page(GFP_KERNEL))) return -ENOMEM; pos = *ppos; /* enumerate busses */ for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { bus = list_entry(buslist, struct usb_bus, bus_list); end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0); len = end - page; if (len > pos) { len -= pos; if (len > nbytes) len = nbytes; if (copy_to_user(buf, page + pos, len)) { if (!ret) ret = -EFAULT; break; } nbytes -= len; buf += len; ret += len; pos = 0; *ppos += len; } else pos -= len; } free_page((unsigned long)page); return ret;}static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait){ struct usb_device_status *st = (struct usb_device_status *)file->private_data; unsigned int mask = 0; if (!st) { st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL); if (!st) return POLLIN; /* * need to prevent the module from being unloaded, since * proc_unregister does not call the release method and * we would have a memory leak */ st->lastev = conndiscevcnt; file->private_data = st; MOD_INC_USE_COUNT; mask = POLLIN; } if (file->f_mode & FMODE_READ) poll_wait(file, &deviceconndiscwq, wait); if (st->lastev != conndiscevcnt) mask |= POLLIN; st->lastev = conndiscevcnt; return mask;}static int usb_device_open(struct inode *inode, struct file *file){ file->private_data = NULL; MOD_INC_USE_COUNT; return 0;}static int usb_device_release(struct inode *inode, struct file *file){ if (file->private_data) { kfree(file->private_data); file->private_data = NULL; } MOD_DEC_USE_COUNT; return 0;}/* * Dump usb_driver_list. * * We now walk the list of registered USB drivers. */static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos){ struct list_head *tmp = usb_driver_list.next; char *page, *start, *end; ssize_t ret = 0; unsigned int pos, len; if (*ppos < 0) return -EINVAL; if (nbytes <= 0) return 0; if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; if (!(page = (char*) __get_free_page(GFP_KERNEL))) return -ENOMEM; start = page; end = page + (PAGE_SIZE - 100); pos = *ppos; for (; tmp != &usb_driver_list; tmp = tmp->next) { struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list); start += sprintf (start, "%s\n", driver->name); if (start > end) { start += sprintf(start, "(truncated)\n"); break; } } if (start == page) start += sprintf(start, "(none)\n"); len = start - page; if (len > pos) { len -= pos; if (len > nbytes) len = nbytes; ret = len; if (copy_to_user(buf, page + pos, len)) ret = -EFAULT; else *ppos += len; } free_page((unsigned long)page); return ret;}static long long usbdev_lseek(struct file * file, long long offset, int orig);static struct file_operations proc_usb_devlist_file_operations = { usbdev_lseek, /* lseek */ usb_device_read, /* read */ NULL, /* write */ NULL, /* readdir */ usb_device_poll, /* poll */ NULL, /* ioctl */ NULL, /* mmap */ usb_device_open, /* open */ NULL, /* flush */ usb_device_release, /* release */ NULL /* fsync */};static struct inode_operations proc_usb_devlist_inode_operations = { &proc_usb_devlist_file_operations, /* file-ops */};static struct file_operations proc_usb_drvlist_file_operations = { usbdev_lseek, /* lseek */ usb_driver_read, /* read */ NULL, /* write */ NULL, /* readdir */ NULL, /* poll */ NULL, /* 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_drvlist_inode_operations = { &proc_usb_drvlist_file_operations, /* file-ops */};/* * proc entry for every device */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;}/* 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; struct ezusb_bulktransfer bulk; struct ezusb_old_ctrltransfer octrl; struct ezusb_old_bulktransfer obulk; struct ezusb_setinterface setintf; unsigned int len1, ep, pipe, cfg; int len2; unsigned char *tbuf; int i; 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); 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, (ctrl.timeout * HZ + 500) / 1000); if ((i > 0) && 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, (ctrl.timeout * HZ + 500) / 1000); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "procusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n", ctrl.requesttype, ctrl.request, ctrl.length, i); return i; } return i; 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); 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 = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000); if ((i > 0) && len2) { copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT); } } else { if (len1) { copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT); } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "procusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, i); return i; } return len2; case EZUSB_OLD_CONTROL: if (obsolete_warn < 20) { printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl\n", current->pid, current->comm); obsolete_warn++; } if (!capable(CAP_SYS_RAWIO)) return -EPERM; copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT); if (octrl.dlen > PAGE_SIZE) return -EINVAL; if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; if (octrl.requesttype & 0x80) { if (octrl.dlen && !access_ok(VERIFY_WRITE, octrl.data, octrl.dlen)) { free_page((unsigned long)tbuf); return -EINVAL; } i = usb_internal_control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ); if ((i > 0) && octrl.dlen) { copy_to_user_ret(octrl.data, tbuf, octrl.dlen, -EFAULT); } } else { if (octrl.dlen) { copy_from_user_ret(tbuf, octrl.data, octrl.dlen, -EFAULT); } i = usb_internal_control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "procusb: EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n", octrl.requesttype, octrl.request, octrl.length, i); return i; } return i; case EZUSB_OLD_BULK: if (obsolete_warn < 20) { printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_BULK ioctl\n", current->pid, current->comm); obsolete_warn++; } if (!capable(CAP_SYS_RAWIO)) return -EPERM; copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -