📄 proc_usb.c
字号:
if (obulk.ep & 0x80) pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f); else pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f); if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80))) return -EINVAL; len1 = obulk.len; if (len1 > PAGE_SIZE) len1 = PAGE_SIZE; if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; if (obulk.ep & 0x80) { if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) { free_page((unsigned long)tbuf); return -EINVAL; } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5); if ((i > 0) && len2) { copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT); } } else { if (len1) { copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT); } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "procusb: EZUSB_OLD_BULK failed ep 0x%x len %u ret %d\n", obulk.ep, obulk.len, i); return i; } 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); if ((ep & ~0x80) >= 16) return -EINVAL; usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0); 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; case EZUSB_SETCONFIGURATION: if (obsolete_warn < 20) { printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl\n", current->pid, current->comm); obsolete_warn++; } if (!capable(CAP_SYS_RAWIO)) return -EPERM; get_user_ret(cfg, (unsigned int *)arg, -EFAULT); if (usb_set_configuration(dev, cfg) < 0) 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_old_ctrltransfer octrl; struct usb_proc_old_bulktransfer obulk; struct usb_proc_setinterface setintf; unsigned int len1, ep, pipe, cfg; int 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, (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 "/proc/bus/usb: USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d\n", ctrl.requesttype, ctrl.request, ctrl.length, i); return i; } 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 = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000); 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 = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000); } 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_OLD_CONTROL: if (!capable(CAP_SYS_RAWIO)) return -EPERM; copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT); if (octrl.length > PAGE_SIZE) return -EINVAL; if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; if (octrl.requesttype & 0x80) { if (octrl.length && !access_ok(VERIFY_WRITE, octrl.data, octrl.length)) { free_page((unsigned long)tbuf); return -EINVAL; } i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), octrl.request, octrl.requesttype, octrl.value, octrl.index, tbuf, octrl.length, HZ); if ((i > 0) && octrl.length) { copy_to_user_ret(octrl.data, tbuf, octrl.length, -EFAULT); } } else { if (octrl.length) { copy_from_user_ret(tbuf, octrl.data, octrl.length, -EFAULT); } i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), octrl.request, octrl.requesttype, octrl.value, octrl.index, tbuf, octrl.length, HZ); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n", octrl.requesttype, octrl.request, octrl.length, i); return i; } return 0; case USB_PROC_OLD_BULK: if (!capable(CAP_SYS_RAWIO)) return -EPERM; copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT); if (obulk.ep & 0x80) pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f); else pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f); if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80))) return -EINVAL; len1 = obulk.len; if (len1 > PAGE_SIZE) len1 = PAGE_SIZE; if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; if (obulk.ep & 0x80) { if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) { free_page((unsigned long)tbuf); return -EINVAL; } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5); if ((i > 0) && len2) { copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT); } } else { if (len1) { copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT); } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5); } free_page((unsigned long)tbuf); if (i < 0) { printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d\n", obulk.ep, obulk.len, i); return i; } 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 USB_PROC_SETCONFIGURATION: if (!capable(CAP_SYS_RAWIO)) return -EPERM; get_user_ret(cfg, (unsigned int *)arg, -EFAULT); if (usb_set_configuration(dev, cfg) < 0) return -EINVAL; return 0; case EZUSB_CONTROL: case EZUSB_BULK: case EZUSB_OLD_CONTROL: case EZUSB_OLD_BULK: case EZUSB_RESETEP: case EZUSB_SETINTERFACE: case EZUSB_SETCONFIGURATION: return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg); } 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 */};void proc_usb_add_bus(struct usb_bus *bus){ char buf[16]; bus->proc_entry = NULL; if (!usbdir) return; sprintf(buf, "%03d", bus->busnum);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31) if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))#else if (!(bus->proc_entry = proc_mkdir(buf, usbdir)))#endif return; bus->proc_entry->data = bus; conndiscevent();}/* 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); conndiscevent();}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; conndiscevent();}void proc_usb_remove_device(struct usb_device *dev){ if (dev->proc_entry) remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry); conndiscevent();}void proc_usb_cleanup (void){ if (driversdir) remove_proc_entry("drivers", usbdir); if (devicesdir) remove_proc_entry("devices", usbdir); if (usbdir) remove_proc_entry("usb", proc_bus);}int proc_usb_init (void){#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31) usbdir = create_proc_entry("usb", S_IFDIR, proc_bus);#else usbdir = proc_mkdir("usb", proc_bus);#endif if (!usbdir) { printk ("proc_usb: cannot create /proc/bus/usb entry\n"); return -1; } driversdir = create_proc_entry("drivers", 0, usbdir); if (!driversdir) { printk ("proc_usb: cannot create /proc/bus/usb/drivers entry\n"); proc_usb_cleanup(); return -1; } driversdir->ops = &proc_usb_drvlist_inode_operations; devicesdir = create_proc_entry("devices", 0, usbdir); if (!devicesdir) { printk ("proc_usb: cannot create /proc/bus/usb/devices entry\n"); proc_usb_cleanup (); return -1; } devicesdir->ops = &proc_usb_devlist_inode_operations; return 0;}/* end proc_usb.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -