X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fcore%2Fdevices.c;h=c0f37343a276ce551705065625f923ec13f7f629;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=aa6f7baa6048a39435d6af4a0c1e138a5ad99691;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index aa6f7baa6..c0f37343a 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -57,8 +57,10 @@ #include #include #include +#include #include +#include "usb.h" #include "hcd.h" #define MAX_TOPO_LEVEL 6 @@ -66,45 +68,45 @@ /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ #define ALLOW_SERIAL_NUMBER -static char *format_topo = +static const char *format_topo = /* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */ "\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n"; -static char *format_string_manufacturer = +static const char *format_string_manufacturer = /* S: Manufacturer=xxxx */ "S: Manufacturer=%.100s\n"; -static char *format_string_product = +static const char *format_string_product = /* S: Product=xxxx */ "S: Product=%.100s\n"; #ifdef ALLOW_SERIAL_NUMBER -static char *format_string_serialnumber = +static const char *format_string_serialnumber = /* S: SerialNumber=xxxx */ "S: SerialNumber=%.100s\n"; #endif -static char *format_bandwidth = +static const char *format_bandwidth = /* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */ "B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n"; -static char *format_device1 = +static const char *format_device1 = /* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */ "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n"; -static char *format_device2 = +static const char *format_device2 = /* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */ "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n"; -static char *format_config = +static const char *format_config = /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; -static char *format_iface = +static const char *format_iface = /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ "I: If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; -static char *format_endpt = +static const char *format_endpt = /* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */ "E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n"; @@ -149,7 +151,7 @@ static const struct class_info clas_info[] = /*****************************************************************/ -void usbdevfs_conn_disc_event(void) +void usbfs_conn_disc_event(void) { conndiscevcnt++; wake_up(&deviceconndiscwq); @@ -180,7 +182,7 @@ static char *usb_dump_endpoint_descriptor ( in = (desc->bEndpointAddress & USB_DIR_IN); dir = in ? 'I' : 'O'; if (speed == USB_SPEED_HIGH) { - switch (desc->wMaxPacketSize & (0x03 << 11)) { + switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { case 1 << 11: bandwidth = 2; break; case 2 << 11: bandwidth = 3; break; } @@ -227,18 +229,26 @@ static char *usb_dump_endpoint_descriptor ( start += sprintf(start, format_endpt, desc->bEndpointAddress, dir, desc->bmAttributes, type, - (desc->wMaxPacketSize & 0x07ff) * bandwidth, + (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * bandwidth, interval, unit); return start; } -static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno) +static char *usb_dump_interface_descriptor(char *start, char *end, + const struct usb_interface_cache *intfc, + const struct usb_interface *iface, + int setno) { - struct usb_interface_descriptor *desc = &iface->altsetting[setno].desc; + const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc; + const char *driver_name = ""; if (start > end) return start; down_read(&usb_bus_type.subsys.rwsem); + if (iface) + driver_name = (iface->dev.driver + ? iface->dev.driver->name + : "(none)"); start += sprintf(start, format_iface, desc->bInterfaceNumber, desc->bAlternateSetting, @@ -247,9 +257,7 @@ static char *usb_dump_interface_descriptor(char *start, char *end, const struct class_decode(desc->bInterfaceClass), desc->bInterfaceSubClass, desc->bInterfaceProtocol, - iface->dev.driver - ? iface->dev.driver->name - : "(none)"); + driver_name); up_read(&usb_bus_type.subsys.rwsem); return start; } @@ -258,13 +266,14 @@ static char *usb_dump_interface( int speed, char *start, char *end, + const struct usb_interface_cache *intfc, const struct usb_interface *iface, int setno ) { - struct usb_host_interface *desc = &iface->altsetting[setno]; + const struct usb_host_interface *desc = &intfc->altsetting[setno]; int i; - start = usb_dump_interface_descriptor(start, end, iface, setno); + start = usb_dump_interface_descriptor(start, end, intfc, iface, setno); for (i = 0; i < desc->desc.bNumEndpoints; i++) { if (start > end) return start; @@ -276,9 +285,8 @@ static char *usb_dump_interface( /* TBD: * 0. TBDs - * 1. marking active config and ifaces (code lists all, but should mark + * 1. marking active interface altsettings (code lists all, but should mark * which ones are active, if any) - * 2. add status to each endpoint line */ static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active) @@ -303,6 +311,7 @@ static char *usb_dump_config ( ) { int i, j; + struct usb_interface_cache *intfc; struct usb_interface *interface; if (start > end) @@ -311,14 +320,13 @@ static char *usb_dump_config ( return start + sprintf(start, "(null Cfg. desc.)\n"); start = usb_dump_config_descriptor(start, end, &config->desc, active); for (i = 0; i < config->desc.bNumInterfaces; i++) { + intfc = config->intf_cache[i]; interface = config->interface[i]; - if (!interface) - break; - for (j = 0; j < interface->num_altsetting; j++) { + for (j = 0; j < intfc->num_altsetting; j++) { if (start > end) return start; start = usb_dump_interface(speed, - start, end, interface, j); + start, end, intfc, interface, j); } } return start; @@ -329,10 +337,13 @@ static char *usb_dump_config ( */ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc) { + u16 bcdUSB = le16_to_cpu(desc->bcdUSB); + u16 bcdDevice = le16_to_cpu(desc->bcdDevice); + if (start > end) return start; start += sprintf (start, format_device1, - desc->bcdUSB >> 8, desc->bcdUSB & 0xff, + bcdUSB >> 8, bcdUSB & 0xff, desc->bDeviceClass, class_decode (desc->bDeviceClass), desc->bDeviceSubClass, @@ -342,8 +353,9 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb if (start > end) return start; start += sprintf(start, format_device2, - desc->idVendor, desc->idProduct, - desc->bcdDevice >> 8, desc->bcdDevice & 0xff); + le16_to_cpu(desc->idVendor), + le16_to_cpu(desc->idProduct), + bcdDevice >> 8, bcdDevice & 0xff); return start; } @@ -352,33 +364,21 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb */ static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev) { - char *buf; - if (start > end) return start; - buf = kmalloc(128, GFP_KERNEL); - if (!buf) - return start; - if (dev->descriptor.iManufacturer) { - if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0) - start += sprintf(start, format_string_manufacturer, buf); - } + if (dev->manufacturer) + start += sprintf(start, format_string_manufacturer, dev->manufacturer); if (start > end) goto out; - if (dev->descriptor.iProduct) { - if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0) - start += sprintf(start, format_string_product, buf); - } + if (dev->product) + start += sprintf(start, format_string_product, dev->product); if (start > end) goto out; #ifdef ALLOW_SERIAL_NUMBER - if (dev->descriptor.iSerialNumber) { - if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0) - start += sprintf(start, format_string_serialnumber, buf); - } + if (dev->serial) + start += sprintf(start, format_string_serialnumber, dev->serial); #endif out: - kfree(buf); return start; } @@ -395,7 +395,7 @@ static char *usb_dump_desc(char *start, char *end, struct usb_device *dev) return start; start = usb_dump_device_strings (start, end, dev); - + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { if (start > end) return start; @@ -445,6 +445,7 @@ static char *usb_dump_string(char *start, char *end, const struct usb_device *de * nbytes - the maximum number of bytes to write * skip_bytes - the number of bytes to skip before writing anything * file_offset - the offset into the devices file on completion + * The caller must own the device lock. */ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *skip_bytes, loff_t *file_offset, struct usb_device *usbdev, struct usb_bus *bus, int level, int index, int count) @@ -461,7 +462,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski return 0; if (level > MAX_TOPO_LEVEL) - return total_written; + return 0; /* allocate 2^1 pages = 8K (on i386); should be more than enough for one device */ if (!(pages_start = (char*) __get_free_pages(GFP_KERNEL,1))) return -ENOMEM; @@ -528,10 +529,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski length = *nbytes; if (copy_to_user(*buffer, pages_start + *skip_bytes, length)) { free_pages((unsigned long)pages_start, 1); - - if (total_written == 0) - return -EFAULT; - return total_written; + return -EFAULT; } *nbytes -= length; *file_offset += length; @@ -545,9 +543,13 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski /* Now look at all of this device's children. */ for (chix = 0; chix < usbdev->maxchild; chix++) { - if (usbdev->children[chix]) { - ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, usbdev->children[chix], + struct usb_device *childdev = usbdev->children[chix]; + + if (childdev) { + usb_lock_device(childdev); + ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, level + 1, chix, ++cnt); + usb_unlock_device(childdev); if (ret == -EFAULT) return total_written; total_written += ret; @@ -558,7 +560,6 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { - struct list_head *buslist; struct usb_bus *bus; ssize_t ret, total_written = 0; loff_t skip_bytes = *ppos; @@ -570,20 +571,22 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte if (!access_ok(VERIFY_WRITE, buf, nbytes)) return -EFAULT; - /* enumerate busses */ - down (&usb_bus_list_lock); - for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) { - /* print devices for this bus */ - bus = list_entry(buslist, struct usb_bus, bus_list); + mutex_lock(&usb_bus_list_lock); + /* print devices for all busses */ + list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ + if (!bus->root_hub) + continue; + usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0); + usb_unlock_device(bus->root_hub); if (ret < 0) { - up(&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return ret; } total_written += ret; } - up (&usb_bus_list_lock); + mutex_unlock(&usb_bus_list_lock); return total_written; } @@ -604,6 +607,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct /* we may have dropped BKL - need to check for having lost the race */ if (file->private_data) { kfree(st); + st = file->private_data; goto lost_race; } @@ -634,11 +638,8 @@ static int usb_device_open(struct inode *inode, struct file *file) static int usb_device_release(struct inode *inode, struct file *file) { - if (file->private_data) { - kfree(file->private_data); - file->private_data = NULL; - } - + kfree(file->private_data); + file->private_data = NULL; return 0; } @@ -666,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig) return ret; } -struct file_operations usbdevfs_devices_fops = { +struct file_operations usbfs_devices_fops = { .llseek = usb_device_lseek, .read = usb_device_read, .poll = usb_device_poll,