vserver 2.0 rc7
[linux-2.6.git] / drivers / usb / input / hiddev.c
index ff319d9..96b7c90 100644 (file)
@@ -124,7 +124,6 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
        int i, j;
        struct hid_report *report;
        struct hid_report_enum *report_enum;
-       struct list_head *list;
        struct hid_field *field;
 
        if (uref->report_type < HID_REPORT_TYPE_MIN ||
@@ -132,9 +131,8 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
 
        report_enum = hid->report_enum +
                (uref->report_type - HID_REPORT_TYPE_MIN);
-       list = report_enum->report_list.next;
-       while (list != &report_enum->report_list) {
-               report = (struct hid_report *) list;
+
+       list_for_each_entry(report, &report_enum->report_list, list)
                for (i = 0; i < report->maxfield; i++) {
                        field = report->field[i];
                        for (j = 0; j < field->maxusage; j++) {
@@ -146,8 +144,6 @@ hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
                                }
                        }
                }
-               list = list->next;
-       }
 
        return NULL;
 }
@@ -223,16 +219,6 @@ static int hiddev_fasync(int fd, struct file *file, int on)
        return retval < 0 ? retval : 0;
 }
 
-/*
- * De-allocate a hiddev structure
- */
-static struct usb_class_driver hiddev_class;
-static void hiddev_cleanup(struct hiddev *hiddev)
-{
-       hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-       usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
-       kfree(hiddev);
-}
 
 /*
  * release file op
@@ -253,7 +239,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
                if (list->hiddev->exist) 
                        hid_close(list->hiddev->hid);
                else
-                       hiddev_cleanup(list->hiddev);
+                       kfree(list->hiddev);
        }
 
        kfree(list);
@@ -433,9 +419,9 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                dinfo.busnum = dev->bus->busnum;
                dinfo.devnum = dev->devnum;
                dinfo.ifnum = hid->ifnum;
-               dinfo.vendor = dev->descriptor.idVendor;
-               dinfo.product = dev->descriptor.idProduct;
-               dinfo.version = dev->descriptor.bcdDevice;
+               dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
+               dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
+               dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
                dinfo.num_applications = hid->maxapplication;
                if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
                        return -EFAULT;
@@ -636,16 +622,18 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                                goto inval;
 
                        field = report->field[uref->field_index];
-                       if (uref->usage_index >= field->maxusage)
-                               goto inval;
 
-                       if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) {
-                               if (uref_multi->num_values >= HID_MAX_USAGES || 
-                                   uref->usage_index >= field->maxusage || 
-                                  (uref->usage_index + uref_multi->num_values) >= field->maxusage)
+                       if (cmd == HIDIOCGCOLLECTIONINDEX) {
+                               if (uref->usage_index >= field->maxusage)
                                        goto inval;
+                       } else if (uref->usage_index >= field->report_count)
+                               goto inval;
+
+                       else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+                                (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+                                 uref->usage_index + uref_multi->num_values >= field->report_count))
+                               goto inval;
                        }
-               }
 
                switch (cmd) {
                        case HIDIOCGUSAGE:
@@ -795,17 +783,21 @@ int hiddev_connect(struct hid_device *hid)
  * This is where hid.c calls us to disconnect a hiddev device from the
  * corresponding hid device (usually because the usb device has disconnected)
  */
+static struct usb_class_driver hiddev_class;
 void hiddev_disconnect(struct hid_device *hid)
 {
        struct hiddev *hiddev = hid->hiddev;
 
        hiddev->exist = 0;
 
+       hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
+       usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+
        if (hiddev->open) {
                hid_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
        } else {
-               hiddev_cleanup(hiddev);
+               kfree(hiddev);
        }
 }