Import 2.3.25pre1
[davej-history.git] / drivers / usb / proc_usb.c
blob332e9c0efd1de5b2c7c52dff352a947a140b5706
1 /*
2 * drivers/usb/proc_usb.c
3 * (C) Copyright 1999 Randy Dunlap.
4 * (C) Copyright 1999 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *************************************************************
22 * This is a /proc/bus/usb filesystem output module for USB.
23 * It creates /proc/bus/usb/drivers and /proc/bus/usb/devices.
25 * /proc/bus/usb/devices contains USB topology, device, config, class,
26 * interface, & endpoint data.
28 * I considered using /proc/bus/usb/devices/device# for each device
29 * as it is attached or detached, but I didn't like this for some
30 * reason -- maybe it's just too deep of a directory structure.
31 * I also don't like looking in multiple places to gather and view
32 * the data. Having only one file for ./devices also prevents race
33 * conditions that could arise if a program was reading device info
34 * for devices that are being removed (unplugged). (That is, the
35 * program may find a directory for devnum_12 then try to open it,
36 * but it was just unplugged, so the directory is now deleted.
37 * But programs would just have to be prepared for situations like
38 * this in any plug-and-play environment.)
41 #define __KERNEL__ 1
43 #include <linux/types.h>
44 #include <asm/types.h>
45 #include <linux/kernel.h>
46 /* #include <linux/module.h> */
47 #include <linux/fs.h>
48 #include <linux/proc_fs.h>
49 #include <linux/stat.h>
50 #include <linux/string.h>
51 #include <linux/list.h>
52 #include <linux/bitops.h>
53 #include <asm/uaccess.h>
54 #include <linux/mm.h>
56 #include "usb.h"
58 #define DUMP_LIMIT (PAGE_SIZE - 100)
59 /* limit to only one memory page of output */
61 #define MAX_TOPO_LEVEL 6
64 static char *format_topo =
65 /* T: Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
66 "T: Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
68 static char *format_bandwidth =
69 /* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
70 "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
72 static char *format_device1 =
73 /* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
74 "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
76 static char *format_device2 =
77 /* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
78 "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
80 static char *format_config =
81 /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
82 "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
84 static char *format_iface =
85 /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx */
86 "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
88 static char *format_endpt =
89 /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
90 "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
94 * Need access to the driver and USB bus lists.
95 * extern struct list_head usb_driver_list;
96 * extern struct list_head usb_bus_list;
97 * However, these will come from functions that return ptrs to each of them.
100 extern struct list_head *usb_driver_get_list (void);
101 extern struct list_head *usb_bus_get_list (void);
103 extern struct proc_dir_entry *proc_bus;
105 static struct proc_dir_entry *usbdir = NULL, *driversdir = NULL;
106 static struct proc_dir_entry *devicesdir = NULL;
108 struct class_info {
109 int class;
110 char *class_name;
113 struct class_info clas_info [] =
114 { /* max. 5 chars. per name string */
115 {USB_CLASS_PER_INTERFACE, ">ifc"},
116 {USB_CLASS_AUDIO, "audio"},
117 {USB_CLASS_COMM, "comm."},
118 {USB_CLASS_HID, "HID"},
119 {USB_CLASS_HUB, "hub"},
120 {USB_CLASS_PRINTER, "print"},
121 {USB_CLASS_MASS_STORAGE, "stor."},
122 {USB_CLASS_VENDOR_SPEC, "vend."},
123 {-1, "unk."} /* leave as last */
126 /*****************************************************************/
128 static char *class_decode (const int class)
130 int ix;
132 for (ix = 0; clas_info [ix].class != -1; ix++)
133 if (clas_info [ix].class == class)
134 break;
136 return (clas_info [ix].class_name);
138 static int usb_dump_endpoint_descriptor (const struct usb_endpoint_descriptor *desc,
139 char *buf, int *len)
141 char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
143 *len += sprintf (buf + *len, format_endpt,
144 desc->bEndpointAddress,
145 (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
146 desc->bmAttributes,
147 EndpointType[desc->bmAttributes & 3],
148 desc->wMaxPacketSize,
149 desc->bInterval
152 return (*len >= DUMP_LIMIT) ? -1 : 0;
155 static int usb_dump_endpoint (const struct usb_endpoint_descriptor *endpoint,
156 char *buf, int *len)
158 if (usb_dump_endpoint_descriptor (endpoint, buf, len) < 0)
159 return -1;
161 return 0;
164 static int usb_dump_interface_descriptor (const struct usb_interface *iface,
165 int setno, char *buf, int *len)
167 struct usb_interface_descriptor *desc =
168 &iface->altsetting[setno];
170 *len += sprintf (buf + *len, format_iface,
171 desc->bInterfaceNumber,
172 desc->bAlternateSetting,
173 desc->bNumEndpoints,
174 desc->bInterfaceClass,
175 class_decode (desc->bInterfaceClass),
176 desc->bInterfaceSubClass,
177 desc->bInterfaceProtocol,
178 iface->driver ? iface->driver->name : "(none)"
181 return (*len >= DUMP_LIMIT) ? -1 : 0;
184 static int usb_dump_interface (const struct usb_interface *iface,
185 int setno, char *buf, int *len)
187 int i;
188 struct usb_interface_descriptor *desc =
189 &iface->altsetting[setno];
191 if (usb_dump_interface_descriptor (iface, setno, buf, len) < 0)
192 return -1;
194 for (i = 0; i < desc->bNumEndpoints; i++) {
195 if (usb_dump_endpoint (desc->endpoint + i, buf, len) < 0)
196 return -1;
199 return 0;
202 /* TBD:
203 * 0. TBDs
204 * 1. marking active config and ifaces (code lists all, but should mark
205 * which ones are active, if any)
206 * 2. add <halted> status to each endpoint line
209 static int usb_dump_config_descriptor (const struct usb_config_descriptor *desc,
210 const int active, char *buf, int *len)
212 *len += sprintf (buf + *len, format_config,
213 active ? '*' : ' ', /* mark active/actual/current cfg. */
214 desc->bNumInterfaces,
215 desc->bConfigurationValue,
216 desc->bmAttributes,
217 desc->MaxPower * 2
220 return (*len >= DUMP_LIMIT) ? -1 : 0;
223 static int usb_dump_config (const struct usb_config_descriptor *config,
224 const int active, char *buf, int *len)
226 int i, j;
227 struct usb_interface *interface;
229 if (!config) { /* getting these some in 2.3.7; none in 2.3.6 */
230 *len += sprintf (buf + *len, "(null Cfg. desc.)\n");
231 return 0;
234 if (usb_dump_config_descriptor (config, active, buf, len) < 0)
235 return -1;
237 for (i = 0; i < config->bNumInterfaces; i++) {
238 interface = config->interface + i;
239 if (!interface)
240 break;
242 for (j = 0; j < interface->num_altsetting; j++)
243 if (usb_dump_interface (interface, j, buf, len) < 0)
244 return -1;
247 return 0;
251 * Dump the different USB descriptors.
253 static int usb_dump_device_descriptor (const struct usb_device_descriptor *desc,
254 char *buf, int *len)
256 *len += sprintf (buf + *len, format_device1,
257 desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
258 desc->bDeviceClass,
259 class_decode (desc->bDeviceClass),
260 desc->bDeviceSubClass,
261 desc->bDeviceProtocol,
262 desc->bMaxPacketSize0,
263 desc->bNumConfigurations
265 if (*len >= DUMP_LIMIT) return -1;
267 *len += sprintf (buf + *len, format_device2,
268 desc->idVendor, desc->idProduct,
269 desc->bcdDevice >> 8, desc->bcdDevice & 0xff
272 return (*len >= DUMP_LIMIT) ? -1 : 0;
275 static int usb_dump_desc (const struct usb_device *dev, char *buf, int *len)
277 int i;
279 if (usb_dump_device_descriptor (&dev->descriptor, buf, len) < 0)
280 return -1;
282 for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
283 if (usb_dump_config (dev->config + i,
284 (dev->config + i) == dev->actconfig, /* active ? */
285 buf, len) < 0)
286 return -1;
289 return 0;
292 static int usb_hcd_bandwidth (const struct usb_device *dev, char *buf, int *len)
294 *len += sprintf (buf + *len, format_bandwidth,
295 dev->bus->bandwidth_allocated,
296 FRAME_TIME_MAX_USECS_ALLOC,
297 (100 * dev->bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) /
298 FRAME_TIME_MAX_USECS_ALLOC,
299 dev->bus->bandwidth_int_reqs,
300 dev->bus->bandwidth_isoc_reqs
303 return (*len >= DUMP_LIMIT) ? -1 : 0;
306 #ifdef PROC_EXTRA /* TBD: may want to add this code later */
308 static int usb_dump_hub_descriptor (const struct usb_hub_descriptor * desc,
309 char *buf, int *len)
311 int leng = USB_DT_HUB_NONVAR_SIZE;
312 unsigned char *ptr = (unsigned char *) desc;
314 *len += sprintf (buf + *len, "Interface:");
316 while (leng) {
317 *len += sprintf (buf + *len, " %02x", *ptr);
318 ptr++; leng--;
320 *len += sprintf (buf + *len, "\n");
322 return (*len >= DUMP_LIMIT) ? -1 : 0;
325 static int usb_dump_string (const struct usb_device *dev, char *id, int index,
326 char *buf, int *len)
328 if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
329 *len += sprintf (buf + *len, "%s: %s ", id, dev->stringindex[index]);
331 return (*len >= DUMP_LIMIT) ? -1 : 0;
334 #endif /* PROC_EXTRA */
336 /*****************************************************************/
338 static int usb_device_dump (char *buf, int *len,
339 const struct usb_device *usbdev,
340 int level, int index, int count)
342 int chix;
343 int cnt = 0;
344 int parent_devnum;
346 if (level > MAX_TOPO_LEVEL) return -1;
348 parent_devnum = usbdev->parent ? (usbdev->parent->devnum == -1) ? 0
349 : usbdev->parent->devnum : 0;
351 * So the root hub's parent is 0 and any device that is
352 * plugged into the root hub has a parent of 0.
354 *len += sprintf (buf + *len, format_topo,
355 level, parent_devnum, index, count,
356 usbdev->devnum,
357 usbdev->slow ? "1.5" : "12 ",
358 usbdev->maxchild
361 * level = topology-tier level;
362 * parent_devnum = parent device number;
363 * index = parent's connector number;
364 * count = device count at this level
367 if (*len >= DUMP_LIMIT)
368 return -1;
370 if ((level == 0) && (usbdev->devnum < 0)) { /* for root hub */
371 if (usb_hcd_bandwidth (usbdev, buf, len) < 0)
372 return -1;
374 else { /* for anything but a root hub */
375 if (usb_dump_desc (usbdev, buf, len) < 0)
376 return -1;
379 /* Now look at all of this device's children. */
380 for (chix = 0; chix < usbdev->maxchild; chix++) {
381 if (usbdev->children [chix]) {
382 if (usb_device_dump (buf, len,
383 usbdev->children [chix],
384 level + 1, chix, ++cnt) < 0)
385 return -1;
389 return 0;
392 static int usb_bus_list_dump (char *buf, int len)
394 struct list_head *usb_bus_list = usb_bus_get_list ();
395 struct list_head *list = usb_bus_list->next;
397 len = 0;
400 * Go thru each usb_bus. Within each usb_bus: each usb_device.
401 * Within each usb_device: all of its device & config. descriptors,
402 * marking the currently active ones.
406 while (list != usb_bus_list) {
407 struct usb_bus *bus = list_entry (list, struct usb_bus, bus_list);
409 if (usb_device_dump (buf, &len, bus->root_hub, 0, 0, 0)
410 < 0)
411 break;
413 list = list->next;
415 if (len >= DUMP_LIMIT) {
416 len += sprintf (buf + len, "(truncated)\n");
417 break;
421 return (len);
424 static int usb_bus_list_dump_devices (char *buf, char **start, off_t offset,
425 int len, int *eof, void *data)
427 return usb_bus_list_dump (buf, len);
431 * Dump usb_driver_list.
433 * We now walk the list of registered USB drivers.
435 static int usb_driver_list_dump (char *buf, char **start, off_t offset,
436 int len, int *eof, void *data)
438 struct list_head *usb_driver_list = usb_driver_get_list ();
439 struct list_head *tmp = usb_driver_list->next;
440 int cnt = 0;
442 len = 0;
444 while (tmp != usb_driver_list) {
445 struct usb_driver *driver = list_entry (tmp, struct usb_driver,
446 driver_list);
447 len += sprintf (buf + len, "%s\n", driver->name);
448 cnt++;
449 tmp = tmp->next;
451 if (len >= DUMP_LIMIT)
453 len += sprintf (buf + len, "(truncated)\n");
454 return (len);
458 if (!cnt)
459 len += sprintf (buf + len, "(none)\n");
460 return (len);
464 * proc entry for every device
467 static long long usbdev_lseek(struct file * file, long long offset, int orig)
469 switch (orig) {
470 case 0:
471 file->f_pos = offset;
472 return file->f_pos;
474 case 1:
475 file->f_pos += offset;
476 return file->f_pos;
478 case 2:
479 return -EINVAL;
481 default:
482 return -EINVAL;
486 static ssize_t usbdev_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
488 struct inode *inode = file->f_dentry->d_inode;
489 struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
490 struct usb_device *dev = (struct usb_device *)dp->data;
491 ssize_t ret = 0;
492 unsigned len;
494 if (*ppos < 0)
495 return -EINVAL;
496 if (*ppos < sizeof(struct usb_device_descriptor)) {
497 len = sizeof(struct usb_device_descriptor);
498 if (len > nbytes)
499 len = nbytes;
500 copy_to_user_ret(buf, ((char *)&dev->descriptor) + *ppos, len, -EFAULT);
501 *ppos += len;
502 buf += len;
503 nbytes -= len;
504 ret += len;
506 return ret;
509 /* note: this is a compatibility kludge that will vanish soon. */
510 #include "ezusb.h"
512 static int usbdev_ioctl_ezusbcompat(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
514 static unsigned obsolete_warn = 0;
515 struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
516 struct usb_device *dev = (struct usb_device *)dp->data;
517 struct ezusb_ctrltransfer ctrl;
518 struct ezusb_bulktransfer bulk;
519 struct ezusb_old_ctrltransfer octrl;
520 struct ezusb_old_bulktransfer obulk;
521 struct ezusb_setinterface setintf;
522 unsigned int len1, ep, pipe, cfg;
523 unsigned long len2;
524 unsigned char *tbuf;
525 int i;
527 switch (cmd) {
528 case EZUSB_CONTROL:
529 if (obsolete_warn < 20) {
530 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_CONTROL ioctl\n",
531 current->pid, current->comm);
532 obsolete_warn++;
534 if (!capable(CAP_SYS_RAWIO))
535 return -EPERM;
536 copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
537 if (ctrl.length > PAGE_SIZE)
538 return -EINVAL;
539 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
540 return -ENOMEM;
541 if (ctrl.requesttype & 0x80) {
542 if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
543 free_page((unsigned long)tbuf);
544 return -EINVAL;
546 i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
547 ctrl.value, ctrl.index, tbuf, ctrl.length,
548 (ctrl.timeout * HZ + 500) / 1000);
549 if (!i && ctrl.length) {
550 copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
552 } else {
553 if (ctrl.length) {
554 copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
556 i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
557 ctrl.value, ctrl.index, tbuf, ctrl.length,
558 (ctrl.timeout * HZ + 500) / 1000);
560 free_page((unsigned long)tbuf);
561 if (i) {
562 printk(KERN_WARNING "procusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n",
563 ctrl.requesttype, ctrl.request, ctrl.length, i);
564 return -ENXIO;
566 return 0;
568 case EZUSB_BULK:
569 if (obsolete_warn < 20) {
570 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_BULK ioctl\n",
571 current->pid, current->comm);
572 obsolete_warn++;
574 if (!capable(CAP_SYS_RAWIO))
575 return -EPERM;
576 copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
577 if (bulk.ep & 0x80)
578 pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
579 else
580 pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
581 if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
582 return -EINVAL;
583 len1 = bulk.len;
584 if (len1 > PAGE_SIZE)
585 len1 = PAGE_SIZE;
586 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
587 return -ENOMEM;
588 if (bulk.ep & 0x80) {
589 if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
590 free_page((unsigned long)tbuf);
591 return -EINVAL;
593 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
594 if (!i && len2) {
595 copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
597 } else {
598 if (len1) {
599 copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
601 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
603 free_page((unsigned long)tbuf);
604 if (i) {
605 printk(KERN_WARNING "procusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n",
606 bulk.ep, bulk.len, i);
607 return -ENXIO;
609 return len2;
611 case EZUSB_OLD_CONTROL:
612 if (obsolete_warn < 20) {
613 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl\n",
614 current->pid, current->comm);
615 obsolete_warn++;
617 if (!capable(CAP_SYS_RAWIO))
618 return -EPERM;
619 copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
620 if (octrl.dlen > PAGE_SIZE)
621 return -EINVAL;
622 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
623 return -ENOMEM;
624 if (octrl.requesttype & 0x80) {
625 if (octrl.dlen && !access_ok(VERIFY_WRITE, octrl.data, octrl.dlen)) {
626 free_page((unsigned long)tbuf);
627 return -EINVAL;
629 i = dev->bus->op->control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
630 if (!i && octrl.dlen) {
631 copy_to_user_ret(octrl.data, tbuf, octrl.dlen, -EFAULT);
633 } else {
634 if (octrl.dlen) {
635 copy_from_user_ret(tbuf, octrl.data, octrl.dlen, -EFAULT);
637 i = dev->bus->op->control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
639 free_page((unsigned long)tbuf);
640 if (i) {
641 printk(KERN_WARNING "procusb: EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n",
642 octrl.requesttype, octrl.request, octrl.length, i);
643 return -ENXIO;
645 return 0;
647 case EZUSB_OLD_BULK:
648 if (obsolete_warn < 20) {
649 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_OLD_BULK ioctl\n",
650 current->pid, current->comm);
651 obsolete_warn++;
653 if (!capable(CAP_SYS_RAWIO))
654 return -EPERM;
655 copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
656 if (obulk.ep & 0x80)
657 pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
658 else
659 pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
660 if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
661 return -EINVAL;
662 len1 = obulk.len;
663 if (len1 > PAGE_SIZE)
664 len1 = PAGE_SIZE;
665 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
666 return -ENOMEM;
667 if (obulk.ep & 0x80) {
668 if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
669 free_page((unsigned long)tbuf);
670 return -EINVAL;
672 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
673 if (!i && len2) {
674 copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
676 } else {
677 if (len1) {
678 copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
680 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
682 free_page((unsigned long)tbuf);
683 if (i) {
684 printk(KERN_WARNING "procusb: EZUSB_OLD_BULK failed ep 0x%x len %u ret %d\n",
685 obulk.ep, obulk.len, i);
686 return -ENXIO;
688 return len2;
690 case EZUSB_RESETEP:
691 if (obsolete_warn < 20) {
692 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_RESETEP ioctl\n",
693 current->pid, current->comm);
694 obsolete_warn++;
696 if (!capable(CAP_SYS_RAWIO))
697 return -EPERM;
698 get_user_ret(ep, (unsigned int *)arg, -EFAULT);
699 if ((ep & ~0x80) >= 16)
700 return -EINVAL;
701 usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
702 return 0;
704 case EZUSB_SETINTERFACE:
705 if (obsolete_warn < 20) {
706 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl\n",
707 current->pid, current->comm);
708 obsolete_warn++;
710 if (!capable(CAP_SYS_RAWIO))
711 return -EPERM;
712 copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
713 if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
714 return -EINVAL;
715 return 0;
717 case EZUSB_SETCONFIGURATION:
718 if (obsolete_warn < 20) {
719 printk(KERN_WARNING "/proc/bus/usb: process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl\n",
720 current->pid, current->comm);
721 obsolete_warn++;
723 if (!capable(CAP_SYS_RAWIO))
724 return -EPERM;
725 get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
726 if (usb_set_configuration(dev, cfg) < 0)
727 return -EINVAL;
728 return 0;
731 return -ENOIOCTLCMD;
736 static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
738 struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
739 struct usb_device *dev = (struct usb_device *)dp->data;
740 struct usb_proc_ctrltransfer ctrl;
741 struct usb_proc_bulktransfer bulk;
742 struct usb_proc_old_ctrltransfer octrl;
743 struct usb_proc_old_bulktransfer obulk;
744 struct usb_proc_setinterface setintf;
745 unsigned int len1, ep, pipe, cfg;
746 unsigned long len2;
747 unsigned char *tbuf;
748 int i;
750 switch (cmd) {
751 case USB_PROC_CONTROL:
752 if (!capable(CAP_SYS_RAWIO))
753 return -EPERM;
754 copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
755 if (ctrl.length > PAGE_SIZE)
756 return -EINVAL;
757 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
758 return -ENOMEM;
759 if (ctrl.requesttype & 0x80) {
760 if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
761 free_page((unsigned long)tbuf);
762 return -EINVAL;
764 i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request,
765 ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
766 ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
767 if (!i && ctrl.length) {
768 copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
770 } else {
771 if (ctrl.length) {
772 copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
774 i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request,
775 ctrl.requesttype, ctrl.value, ctrl.index, tbuf,
776 ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
778 free_page((unsigned long)tbuf);
779 if (i) {
780 printk(KERN_WARNING "/proc/bus/usb: USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d\n",
781 ctrl.requesttype, ctrl.request, ctrl.length, i);
782 return -ENXIO;
784 return 0;
786 case USB_PROC_BULK:
787 if (!capable(CAP_SYS_RAWIO))
788 return -EPERM;
789 copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
790 if (bulk.ep & 0x80)
791 pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
792 else
793 pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
794 if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
795 return -EINVAL;
796 len1 = bulk.len;
797 if (len1 > PAGE_SIZE)
798 len1 = PAGE_SIZE;
799 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
800 return -ENOMEM;
801 if (bulk.ep & 0x80) {
802 if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
803 free_page((unsigned long)tbuf);
804 return -EINVAL;
806 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
807 if (!i && len2) {
808 copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
810 } else {
811 if (len1) {
812 copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
814 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
816 free_page((unsigned long)tbuf);
817 if (i) {
818 printk(KERN_WARNING "/proc/bus/usb: USB_PROC_BULK failed ep 0x%x len %u ret %d\n",
819 bulk.ep, bulk.len, i);
820 return -ENXIO;
822 return len2;
824 case USB_PROC_OLD_CONTROL:
825 if (!capable(CAP_SYS_RAWIO))
826 return -EPERM;
827 copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
828 if (octrl.length > PAGE_SIZE)
829 return -EINVAL;
830 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
831 return -ENOMEM;
832 if (octrl.requesttype & 0x80) {
833 if (octrl.length && !access_ok(VERIFY_WRITE, octrl.data, octrl.length)) {
834 free_page((unsigned long)tbuf);
835 return -EINVAL;
837 i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), octrl.request,
838 octrl.requesttype, octrl.value, octrl.index, tbuf,
839 octrl.length, HZ);
840 if (!i && octrl.length) {
841 copy_to_user_ret(octrl.data, tbuf, octrl.length, -EFAULT);
843 } else {
844 if (octrl.length) {
845 copy_from_user_ret(tbuf, octrl.data, octrl.length, -EFAULT);
847 i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), octrl.request,
848 octrl.requesttype, octrl.value, octrl.index, tbuf,
849 octrl.length, HZ);
851 free_page((unsigned long)tbuf);
852 if (i) {
853 printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d\n",
854 octrl.requesttype, octrl.request, octrl.length, i);
855 return -ENXIO;
857 return 0;
859 case USB_PROC_OLD_BULK:
860 if (!capable(CAP_SYS_RAWIO))
861 return -EPERM;
862 copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
863 if (obulk.ep & 0x80)
864 pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
865 else
866 pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
867 if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
868 return -EINVAL;
869 len1 = obulk.len;
870 if (len1 > PAGE_SIZE)
871 len1 = PAGE_SIZE;
872 if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
873 return -ENOMEM;
874 if (obulk.ep & 0x80) {
875 if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
876 free_page((unsigned long)tbuf);
877 return -EINVAL;
879 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
880 if (!i && len2) {
881 copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
883 } else {
884 if (len1) {
885 copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
887 i = dev->bus->op->bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
889 free_page((unsigned long)tbuf);
890 if (i) {
891 printk(KERN_WARNING "/proc/bus/usb: USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d\n",
892 obulk.ep, obulk.len, i);
893 return -ENXIO;
895 return len2;
897 case USB_PROC_RESETEP:
898 if (!capable(CAP_SYS_RAWIO))
899 return -EPERM;
900 get_user_ret(ep, (unsigned int *)arg, -EFAULT);
901 if ((ep & ~0x80) >= 16)
902 return -EINVAL;
903 usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
904 return 0;
906 case USB_PROC_SETINTERFACE:
907 if (!capable(CAP_SYS_RAWIO))
908 return -EPERM;
909 copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
910 if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
911 return -EINVAL;
912 return 0;
914 case USB_PROC_SETCONFIGURATION:
915 if (!capable(CAP_SYS_RAWIO))
916 return -EPERM;
917 get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
918 if (usb_set_configuration(dev, cfg) < 0)
919 return -EINVAL;
920 return 0;
922 case EZUSB_CONTROL:
923 case EZUSB_BULK:
924 case EZUSB_OLD_CONTROL:
925 case EZUSB_OLD_BULK:
926 case EZUSB_RESETEP:
927 case EZUSB_SETINTERFACE:
928 case EZUSB_SETCONFIGURATION:
929 return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg);
931 return -ENOIOCTLCMD;
934 static struct file_operations proc_usb_device_file_operations = {
935 usbdev_lseek, /* lseek */
936 usbdev_read, /* read */
937 NULL, /* write */
938 NULL, /* readdir */
939 NULL, /* poll */
940 usbdev_ioctl, /* ioctl */
941 NULL, /* mmap */
942 NULL, /* no special open code */
943 NULL, /* flush */
944 NULL, /* no special release code */
945 NULL /* can't fsync */
948 static struct inode_operations proc_usb_device_inode_operations = {
949 &proc_usb_device_file_operations, /* file-ops */
950 NULL, /* create */
951 NULL, /* lookup */
952 NULL, /* link */
953 NULL, /* unlink */
954 NULL, /* symlink */
955 NULL, /* mkdir */
956 NULL, /* rmdir */
957 NULL, /* mknod */
958 NULL, /* rename */
959 NULL, /* readlink */
960 NULL, /* follow_link */
961 NULL, /* get_block */
962 NULL, /* readpage */
963 NULL, /* writepage */
964 NULL, /* flushpage */
965 NULL, /* truncate */
966 NULL, /* permission */
967 NULL, /* smap */
968 NULL /* revalidate */
971 #define PROCUSB_MAXBUSSES 64
973 static unsigned long busnumbermap[(PROCUSB_MAXBUSSES+8 * sizeof(unsigned long)-1) / (8 * sizeof(unsigned long))] = { 0, };
975 void proc_usb_add_bus(struct usb_bus *bus)
977 int bnum;
978 char buf[16];
980 bus->proc_busnum = -1;
981 bus->proc_entry = NULL;
982 if (!usbdir)
983 return;
984 bnum = find_first_zero_bit(busnumbermap, PROCUSB_MAXBUSSES);
985 if (bnum >= PROCUSB_MAXBUSSES)
986 return;
987 sprintf(buf, "%03d", bnum);
988 if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))
989 return;
990 set_bit(bnum, busnumbermap);
991 bus->proc_busnum = bnum;
992 bus->proc_entry->data = bus;
995 /* devices need already be removed! */
996 void proc_usb_remove_bus(struct usb_bus *bus)
998 if (!bus->proc_entry)
999 return;
1000 remove_proc_entry(bus->proc_entry->name, usbdir);
1001 clear_bit(bus->proc_busnum, busnumbermap);
1004 void proc_usb_add_device(struct usb_device *dev)
1006 char buf[16];
1008 dev->proc_entry = NULL;
1009 if (!dev->bus->proc_entry)
1010 return;
1011 sprintf(buf, "%03d", dev->devnum);
1012 if (!(dev->proc_entry = create_proc_entry(buf, 0, dev->bus->proc_entry)))
1013 return;
1014 dev->proc_entry->ops = &proc_usb_device_inode_operations;
1015 dev->proc_entry->data = dev;
1018 void proc_usb_remove_device(struct usb_device *dev)
1020 if (dev->proc_entry)
1021 remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry);
1025 void proc_usb_cleanup (void)
1027 if (driversdir)
1028 remove_proc_entry ("drivers", usbdir);
1029 if (devicesdir)
1030 remove_proc_entry ("devices", usbdir);
1031 if (usbdir)
1032 remove_proc_entry ("usb", proc_bus);
1035 int proc_usb_init (void)
1037 usbdir = create_proc_entry ("usb", S_IFDIR, proc_bus);
1038 if (!usbdir) {
1039 printk ("proc_usb: cannot create /proc/bus/usb entry\n");
1040 return -1;
1043 driversdir = create_proc_read_entry("drivers", 0, usbdir,
1044 usb_driver_list_dump, NULL);
1045 if (!driversdir) {
1046 printk ("proc_usb: cannot create /proc/bus/usb/drivers entry\n");
1047 proc_usb_cleanup ();
1048 return -1;
1051 devicesdir = create_proc_read_entry ("devices", 0, usbdir,
1052 usb_bus_list_dump_devices, NULL);
1053 if (!devicesdir) {
1054 printk ("proc_usb: cannot create /proc/bus/usb/devices entry\n");
1055 proc_usb_cleanup ();
1056 return -1;
1059 return 0;
1062 /* end proc_usb.c */