fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / usb / core / devices.c
index 5541363..ea398e5 100644 (file)
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
 #include <linux/usbdevice_fs.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
+#include "usb.h"
 #include "hcd.h"
 
 #define MAX_TOPO_LEVEL         6
 /* 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);
@@ -173,14 +175,15 @@ static char *usb_dump_endpoint_descriptor (
 )
 {
        char dir, unit, *type;
-       unsigned interval, in, bandwidth = 1;
+       unsigned interval, bandwidth = 1;
 
        if (start > end)
                return start;
-       in = (desc->bEndpointAddress & USB_DIR_IN);
-       dir = in ? 'I' : 'O';
+
+       dir = usb_endpoint_dir_in(desc) ? '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;
                }
@@ -202,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
                break;
        case USB_ENDPOINT_XFER_BULK:
                type = "Bulk";
-               if (speed == USB_SPEED_HIGH && !in)     /* uframes per NAK */
+               if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
                        interval = desc->bInterval;
                else
                        interval = 0;
@@ -227,7 +230,7 @@ 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;
 }
@@ -238,7 +241,7 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
        int setno)
 {
        const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc;
-       char *driver_name = "";
+       const char *driver_name = "";
 
        if (start > end)
                return start;
@@ -283,9 +286,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 <halted> status to each endpoint line
  */
 
 static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
@@ -336,10 +338,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,
@@ -349,8 +354,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;
 }
 
@@ -359,33 +365,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;
 }
 
@@ -452,7 +446,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 usbdev->serialize semaphore.
+ * 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)
@@ -469,7 +463,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;
@@ -536,10 +530,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;
@@ -556,10 +547,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
                struct usb_device *childdev = usbdev->children[chix];
 
                if (childdev) {
-                       down(&childdev->serialize);
+                       usb_lock_device(childdev);
                        ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
                                        bus, level + 1, chix, ++cnt);
-                       up(&childdev->serialize);
+                       usb_unlock_device(childdev);
                        if (ret == -EFAULT)
                                return total_written;
                        total_written += ret;
@@ -570,7 +561,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;
@@ -582,32 +572,29 @@ 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;
-               down(&bus->root_hub->serialize);
+               usb_lock_device(bus->root_hub);
                ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, bus->root_hub, bus, 0, 0, 0);
-               up(&bus->root_hub->serialize);
+               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;
 }
 
 /* Kernel lock for "lastev" protection */
 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;
+       struct usb_device_status *st = file->private_data;
        unsigned int mask = 0;
 
        lock_kernel();
@@ -617,10 +604,11 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
                        unlock_kernel();
                        return POLLIN;
                }
-               
+
                /* 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;
                }
 
@@ -651,11 +639,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;
 }
 
@@ -683,7 +668,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
        return ret;
 }
 
-struct file_operations usbdevfs_devices_fops = {
+const struct file_operations usbfs_devices_fops = {
        .llseek =       usb_device_lseek,
        .read =         usb_device_read,
        .poll =         usb_device_poll,