Hi!

I've merged a patch Paul Stewart sent me some time ago, which should make life
easier for the guys writing UPS daemons.

Vojtech


You can import this changeset into BK by piping this whole message to:
'| bk receive [path to repository]' or apply the patch as usual.

===================================================================


[EMAIL PROTECTED], 2002-07-13 14:30:11+02:00, [EMAIL PROTECTED]
  Paul's latest updates for hid - makes application collection
  handling much more powerful to allow better usage of HID UPSes.


 Documentation/usb/hiddev.txt  |   15 ++++
 drivers/usb/input/hid-core.c  |  132 +++++++++++++++++++++++++++++-----------
 drivers/usb/input/hid-debug.h |    6 -
 drivers/usb/input/hid-input.c |    7 +-
 drivers/usb/input/hid.h       |   12 ++-
 drivers/usb/input/hiddev.c    |  138 ++++++++++++++++++++++--------------------
 include/linux/hiddev.h        |   19 ++++-
 7 files changed, 211 insertions(+), 118 deletions(-)


diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt
--- a/Documentation/usb/hiddev.txt      Sat Jul 13 14:31:20 2002
+++ b/Documentation/usb/hiddev.txt      Sat Jul 13 14:31:20 2002
@@ -18,7 +18,7 @@
 The data flow for a HID event produced by a device is something like
 the following :
 
- usb.c ---> hid-core.c  ----> input.c ----> [keyboard/mouse/joystick/event]
+ usb.c ---> hid-core.c  ----> hid-input.c ----> [keyboard/mouse/joystick/event]
                          |
                          |
                           --> hiddev.c ----> POWER / MONITOR CONTROL 
@@ -106,6 +106,15 @@
 collections the device has from the num_applications field from the
 hiddev_devinfo structure. 
 
+HIDIOCGCOLLECTIONINFO - struct hiddev_collection_info (read/write)
+This returns a superset of the information above, providing not only
+application collections, but all the collections the device has.  It
+also returns the level the collection lives in the hierarchy.
+The user passes in a hiddev_collection_info struct with the index 
+field set to the index that should be returned.  The ioctl fills in 
+the other fields.  If the index is larger than the last collection 
+index, the ioctl returns -1 and sets errno to -EINVAL.
+
 HIDIOCGDEVINFO - struct hiddev_devinfo (read)
 Gets a hiddev_devinfo structure which describes the device.
 
@@ -171,6 +180,10 @@
 Sets the value of a usage in an output report.  The user fills in
 the hiddev_usage_ref structure as above, but additionally fills in
 the value field.
+
+HIDIOGCOLLECTIONINDEX - struct hiddev_usage_ref (write)
+Returns the collection index associated with this usage.  This
+indicates where in the collection hierarchy this usage sits.
 
 HIDIOCGFLAG - int (read)
 HIDIOCSFLAG - int (write)
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c      Sat Jul 13 14:31:20 2002
+++ b/drivers/usb/input/hid-core.c      Sat Jul 13 14:31:20 2002
@@ -127,18 +127,41 @@
 
        usage = parser->local.usage[0];
 
-       if (type == HID_COLLECTION_APPLICATION
-               && parser->device->maxapplication < HID_MAX_APPLICATIONS)
-                       parser->device->application[parser->device->maxapplication++] 
= usage;
-
        if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) {
                dbg("collection stack overflow");
                return -1;
        }
 
-       collection = parser->collection_stack + parser->collection_stack_ptr++;
+       if (parser->device->maxcollection == parser->device->collection_size) {
+               collection = kmalloc(sizeof(struct hid_collection) *
+                                    parser->device->collection_size * 2,
+                                    GFP_KERNEL);
+               if (collection == NULL) {
+                       dbg("failed to reallocate collection array");
+                       return -1;
+               }
+               memcpy(collection, parser->device->collection,
+                      sizeof(struct hid_collection) *
+                      parser->device->collection_size);
+               memset(collection + parser->device->collection_size, 0,
+                      sizeof(struct hid_collection) *
+                      parser->device->collection_size);
+               kfree(parser->device->collection);
+               parser->device->collection = collection;
+               parser->device->collection_size *= 2;
+       }
+
+       parser->collection_stack[parser->collection_stack_ptr++] =
+               parser->device->maxcollection;
+
+       collection = parser->device->collection + 
+               parser->device->maxcollection++;
        collection->type = type;
        collection->usage = usage;
+       collection->level = parser->collection_stack_ptr - 1;
+       
+       if (type == HID_COLLECTION_APPLICATION)
+               parser->device->maxapplication++;
 
        return 0;
 }
@@ -166,8 +189,8 @@
 {
        int n;
        for (n = parser->collection_stack_ptr - 1; n >= 0; n--)
-               if (parser->collection_stack[n].type == type)
-                       return parser->collection_stack[n].usage;
+               if (parser->device->collection[parser->collection_stack[n]].type == 
+type)
+                       return 
+parser->device->collection[parser->collection_stack[n]].usage;
        return 0; /* we know nothing about this usage type */
 }
 
@@ -181,7 +204,11 @@
                dbg("usage index exceeded");
                return -1;
        }
-       parser->local.usage[parser->local.usage_index++] = usage;
+       parser->local.usage[parser->local.usage_index] = usage;
+       parser->local.collection_index[parser->local.usage_index] =
+               parser->collection_stack_ptr ? 
+               parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
+       parser->local.usage_index++;
        return 0;
 }
 
@@ -221,8 +248,11 @@
        field->logical = hid_lookup_collection(parser, HID_COLLECTION_LOGICAL);
        field->application = hid_lookup_collection(parser, HID_COLLECTION_APPLICATION);
 
-       for (i = 0; i < usages; i++)
+       for (i = 0; i < usages; i++) {
                field->usage[i].hid = parser->local.usage[i];
+               field->usage[i].collection_index =
+                       parser->local.collection_index[i];
+       }
 
        field->maxusage = usages;
        field->flags = flags;
@@ -460,7 +490,7 @@
 
        switch (item->tag) {
                case HID_MAIN_ITEM_TAG_BEGIN_COLLECTION:
-                       ret = open_collection(parser, data & 3);
+                       ret = open_collection(parser, data & 0xff);
                        break;
                case HID_MAIN_ITEM_TAG_END_COLLECTION:
                        ret = close_collection(parser);
@@ -621,17 +651,30 @@
                return NULL;
        memset(device, 0, sizeof(struct hid_device));
 
+       if (!(device->collection = kmalloc(sizeof(struct hid_collection) *
+                                          HID_DEFAULT_NUM_COLLECTIONS,
+                                          GFP_KERNEL))) {
+               kfree(device);
+               return NULL;
+       }
+       memset(device->collection, 0, sizeof(struct hid_collection) *
+              HID_DEFAULT_NUM_COLLECTIONS);
+       device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
+
        for (i = 0; i < HID_REPORT_TYPES; i++)
                INIT_LIST_HEAD(&device->report_enum[i].report_list);
 
        if (!(device->rdesc = (__u8 *)kmalloc(size, GFP_KERNEL))) {
+               kfree(device->collection);
                kfree(device);
                return NULL;
        }
        memcpy(device->rdesc, start, size);
+       device->rsize = size;
 
        if (!(parser = kmalloc(sizeof(struct hid_parser), GFP_KERNEL))) {
                kfree(device->rdesc);
+               kfree(device->collection);
                kfree(device);
                return NULL;
        }
@@ -643,6 +686,8 @@
 
                if (item.format != HID_ITEM_FORMAT_SHORT) {
                        dbg("unexpected long global item");
+                       kfree(device->rdesc);
+                       kfree(device->collection);
                        hid_free_device(device);
                        kfree(parser);
                        return NULL;
@@ -651,6 +696,8 @@
                if (dispatch_type[item.type](parser, &item)) {
                        dbg("item %u %u %u %u parsing failed\n",
                                item.format, (unsigned)item.size, (unsigned)item.type, 
(unsigned)item.tag);
+                       kfree(device->rdesc);
+                       kfree(device->collection);
                        hid_free_device(device);
                        kfree(parser);
                        return NULL;
@@ -659,12 +706,16 @@
                if (start == end) {
                        if (parser->collection_stack_ptr) {
                                dbg("unbalanced collection at end of report 
description");
+                               kfree(device->rdesc);
+                               kfree(device->collection);
                                hid_free_device(device);
                                kfree(parser);
                                return NULL;
                        }
                        if (parser->local.delimiter_depth) {
                                dbg("unbalanced delimiter at end of report 
description");
+                               kfree(device->rdesc);
+                               kfree(device->collection);
                                hid_free_device(device);
                                kfree(parser);
                                return NULL;
@@ -675,6 +726,8 @@
        }
 
        dbg("item fetching failed at offset %d\n", (int)(end - start));
+       kfree(device->rdesc);
+       kfree(device->collection);
        hid_free_device(device);
        kfree(parser);
        return NULL;
@@ -1284,6 +1337,10 @@
 #define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
 #define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
 
+#define USB_VENDOR_ID_MGE              0x0463
+#define USB_DEVICE_ID_MGE_UPS          0xffff
+#define USB_DEVICE_ID_MGE_UPS1         0x0001
+
 struct hid_blacklist {
        __u16 idVendor;
        __u16 idProduct;
@@ -1301,6 +1358,8 @@
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_HIDDEV },
+       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_HIDDEV },
        { 0, 0 }
 };
 
@@ -1443,6 +1502,27 @@
        return NULL;
 }
 
+static void hid_disconnect(struct usb_device *dev, void *ptr)
+{
+       struct hid_device *hid = ptr;
+
+       usb_unlink_urb(hid->urbin);
+       usb_unlink_urb(hid->urbout);
+       usb_unlink_urb(hid->urbctrl);
+
+       if (hid->claimed & HID_CLAIMED_INPUT)
+               hidinput_disconnect(hid);
+       if (hid->claimed & HID_CLAIMED_HIDDEV)
+               hiddev_disconnect(hid);
+
+       usb_free_urb(hid->urbin);
+       usb_free_urb(hid->urbctrl);
+       if (hid->urbout)
+               usb_free_urb(hid->urbout);
+
+       hid_free_device(hid);
+}
+
 static void* hid_probe(struct usb_device *dev, unsigned int ifnum,
                       const struct usb_device_id *id)
 {
@@ -1467,7 +1547,7 @@
                hid->claimed |= HID_CLAIMED_HIDDEV;
 
        if (!hid->claimed) {
-               hid_free_device(hid);
+               hid_disconnect(dev, hid);
                return NULL;
        }
 
@@ -1481,11 +1561,14 @@
                printk("hiddev%d", hid->minor);
 
        c = "Device";
-       for (i = 0; i < hid->maxapplication; i++)
-               if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
-                       c = hid_types[hid->application[i] & 0xffff];
+       for (i = 0; i < hid->maxcollection; i++) {
+               if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
+                   (hid->collection[i].usage & HID_USAGE_PAGE) == HID_UP_GENDESK &&
+                   (hid->collection[i].usage & 0xffff) < ARRAY_SIZE(hid_types)) {
+                       c = hid_types[hid->collection[i].usage & 0xffff];
                        break;
                }
+       }
 
        usb_make_path(dev, path, 63);
 
@@ -1493,27 +1576,6 @@
                hid->version >> 8, hid->version & 0xff, c, hid->name, path);
 
        return hid;
-}
-
-static void hid_disconnect(struct usb_device *dev, void *ptr)
-{
-       struct hid_device *hid = ptr;
-
-       usb_unlink_urb(hid->urbin);
-       usb_unlink_urb(hid->urbout);
-       usb_unlink_urb(hid->urbctrl);
-
-       if (hid->claimed & HID_CLAIMED_INPUT)
-               hidinput_disconnect(hid);
-       if (hid->claimed & HID_CLAIMED_HIDDEV)
-               hiddev_disconnect(hid);
-
-       usb_free_urb(hid->urbin);
-       usb_free_urb(hid->urbctrl);
-       if (hid->urbout)
-               usb_free_urb(hid->urbout);
-
-       hid_free_device(hid);
 }
 
 static struct usb_device_id hid_usb_ids [] = {
diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
--- a/drivers/usb/input/hid-debug.h     Sat Jul 13 14:31:20 2002
+++ b/drivers/usb/input/hid-debug.h     Sat Jul 13 14:31:20 2002
@@ -352,12 +352,6 @@
        unsigned i,k;
        static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
        
-       for (i = 0; i < device->maxapplication; i++) {
-               printk("Application(");
-               resolv_usage(device->application[i]);
-               printk(")\n");
-       }
-
        for (i = 0; i < HID_REPORT_TYPES; i++) {
                report_enum = device->report_enum + i;
                list = report_enum->report_list.next;
diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
--- a/drivers/usb/input/hid-input.c     Sat Jul 13 14:31:20 2002
+++ b/drivers/usb/input/hid-input.c     Sat Jul 13 14:31:20 2002
@@ -474,11 +474,12 @@
        struct list_head *list;
        int i, j, k;
 
-       for (i = 0; i < hid->maxapplication; i++)
-               if (IS_INPUT_APPLICATION(hid->application[i]))
+       for (i = 0; i < hid->maxcollection; i++)
+               if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
+                   IS_INPUT_APPLICATION(hid->collection[i].usage))
                        break;
 
-       if (i == hid->maxapplication)
+       if (i == hid->maxcollection)
                return -1;
 
        hid->input.private = hid;
diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- a/drivers/usb/input/hid.h   Sat Jul 13 14:31:20 2002
+++ b/drivers/usb/input/hid.h   Sat Jul 13 14:31:20 2002
@@ -205,6 +205,7 @@
 #define HID_QUIRK_NOTOUCH      0x02
 #define HID_QUIRK_IGNORE       0x04
 #define HID_QUIRK_NOGET                0x08
+#define HID_QUIRK_HIDDEV       0x10
 
 /*
  * This is the global enviroment of the parser. This information is
@@ -231,10 +232,11 @@
 
 #define HID_MAX_DESCRIPTOR_SIZE                4096
 #define HID_MAX_USAGES                 1024
-#define HID_MAX_APPLICATIONS           16
+#define HID_DEFAULT_NUM_COLLECTIONS    16
 
 struct hid_local {
        unsigned usage[HID_MAX_USAGES]; /* usage array */
+       unsigned collection_index[HID_MAX_USAGES]; /* collection index array */
        unsigned usage_index;
        unsigned usage_minimum;
        unsigned delimiter_depth;
@@ -249,10 +251,12 @@
 struct hid_collection {
        unsigned type;
        unsigned usage;
+       unsigned level;
 };
 
 struct hid_usage {
        unsigned  hid;                  /* hid usage code */
+       unsigned  collection_index;     /* index into collection array */
        __u16     code;                 /* input driver code */
        __u8      type;                 /* input driver type */
        __s8      hat_min;              /* hat switch fun */
@@ -319,7 +323,9 @@
 struct hid_device {                                                    /* device 
report descriptor */
         __u8 *rdesc;
        unsigned rsize;
-       unsigned application[HID_MAX_APPLICATIONS];                     /* List of HID 
applications */
+       struct hid_collection *collection;                              /* List of HID 
+collections */
+       unsigned collection_size;                                       /* Number of 
+allocated hid_collections */
+       unsigned maxcollection;                                         /* Number of 
+parsed collections */
        unsigned maxapplication;                                        /* Number of 
applications */
        unsigned version;                                               /* HID version 
*/
        unsigned country;                                               /* HID country 
*/
@@ -374,7 +380,7 @@
        struct hid_global     global_stack[HID_GLOBAL_STACK_SIZE];
        unsigned              global_stack_ptr;
        struct hid_local      local;
-       struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE];
+       unsigned              collection_stack[HID_COLLECTION_STACK_SIZE];
        unsigned              collection_stack_ptr;
        struct hid_device    *device;
 };
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c        Sat Jul 13 14:31:20 2002
+++ b/drivers/usb/input/hiddev.c        Sat Jul 13 14:31:20 2002
@@ -80,6 +80,7 @@
 static struct hid_report *
 hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
 {
+       unsigned flags = rinfo->report_id & ~HID_REPORT_ID_MASK;
        struct hid_report_enum *report_enum;
        struct list_head *list;
 
@@ -88,27 +89,28 @@
 
        report_enum = hid->report_enum +
                (rinfo->report_type - HID_REPORT_TYPE_MIN);
-       if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
-               switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
-               case HID_REPORT_ID_FIRST:
-                       list = report_enum->report_list.next;
-                       if (list == &report_enum->report_list) return NULL;
-                       rinfo->report_id = ((struct hid_report *) list)->id;
-                       break;
-
-               case HID_REPORT_ID_NEXT:
-                       list = (struct list_head *)
-                               report_enum->report_id_hash[rinfo->report_id &
-                                                          HID_REPORT_ID_MASK];
-                       if (list == NULL) return NULL;
-                       list = list->next;
-                       if (list == &report_enum->report_list) return NULL;
-                       rinfo->report_id = ((struct hid_report *) list)->id;
-                       break;
 
-               default:
-                       return NULL;
-               }
+       switch (flags) {
+       case 0: /* Nothing to do -- report_id is already set correctly */
+               break;
+
+       case HID_REPORT_ID_FIRST:
+               list = report_enum->report_list.next;
+               if (list == &report_enum->report_list) return NULL;
+               rinfo->report_id = ((struct hid_report *) list)->id;
+               break;
+               
+       case HID_REPORT_ID_NEXT:
+               list = (struct list_head *)
+                       report_enum->report_id_hash[rinfo->report_id & 
+HID_REPORT_ID_MASK];
+               if (list == NULL) return NULL;
+               list = list->next;
+               if (list == &report_enum->report_list) return NULL;
+               rinfo->report_id = ((struct hid_report *) list)->id;
+               break;
+               
+       default:
+               return NULL;
        }
 
        return report_enum->report_id_hash[rinfo->report_id];
@@ -256,8 +258,7 @@
 /*
  * "write" file op
  */
-static ssize_t hiddev_write(struct file * file, const char * buffer,
-                           size_t count, loff_t *ppos)
+static ssize_t hiddev_write(struct file * file, const char * buffer, size_t count, 
+loff_t *ppos)
 {
        return -EINVAL;
 }
@@ -265,8 +266,7 @@
 /*
  * "read" file op
  */
-static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
-                          loff_t *ppos)
+static ssize_t hiddev_read(struct file * file, char * buffer, size_t count, loff_t 
+*ppos)
 {
        DECLARE_WAITQUEUE(wait, current);
        struct hiddev_list *list = file->private_data;
@@ -354,17 +354,20 @@
 /*
  * "ioctl" file op
  */
-static int hiddev_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 
+unsigned long arg)
 {
        struct hiddev_list *list = file->private_data;
        struct hiddev *hiddev = list->hiddev;
        struct hid_device *hid = hiddev->hid;
        struct usb_device *dev = hid->dev;
+       struct hiddev_collection_info cinfo;
        struct hiddev_report_info rinfo;
+       struct hiddev_field_info finfo;
        struct hiddev_usage_ref uref;
+       struct hiddev_devinfo dinfo;
        struct hid_report *report;
        struct hid_field *field;
+       int i;
 
        if (!hiddev->exist) return -EIO;
 
@@ -376,11 +379,18 @@
        case HIDIOCAPPLICATION:
                if (arg < 0 || arg >= hid->maxapplication)
                        return -EINVAL;
-               return hid->application[arg];
+
+               for (i = 0; i < hid->maxcollection; i++)
+                       if (hid->collection[i].type == 
+                           HID_COLLECTION_APPLICATION && arg-- == 0)
+                               break;
+               
+               if (i == hid->maxcollection)
+                       return -EINVAL;
+
+               return hid->collection[i].usage;
 
        case HIDIOCGDEVINFO:
-       {
-               struct hiddev_devinfo dinfo;
                dinfo.bustype = BUS_USB;
                dinfo.busnum = dev->bus->busnum;
                dinfo.devnum = dev->devnum;
@@ -390,7 +400,6 @@
                dinfo.version = dev->descriptor.bcdDevice;
                dinfo.num_applications = hid->maxapplication;
                return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
-       }
 
        case HIDIOCGFLAG:
                return put_user(list->flags, (int *) arg);
@@ -438,7 +447,6 @@
                }
 
        case HIDIOCINITREPORT:
-
                hid_init_reports(hid);
 
                return 0;
@@ -483,8 +491,6 @@
                return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
 
        case HIDIOCGFIELDINFO:
-       {
-               struct hiddev_field_info finfo;
                if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
                        return -EFAULT;
                rinfo.report_type = finfo.report_type;
@@ -513,7 +519,6 @@
                finfo.unit = field->unit;
 
                return copy_to_user((void *) arg, &finfo, sizeof(finfo));
-       }
 
        case HIDIOCGUCODE:
                if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
@@ -536,9 +541,14 @@
                return copy_to_user((void *) arg, &uref, sizeof(uref));
 
        case HIDIOCGUSAGE:
+       case HIDIOCSUSAGE:
+       case HIDIOCGCOLLECTIONINDEX:
                if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
                        return -EFAULT;
 
+               if (cmd != HIDIOCGUSAGE && uref.report_type == HID_REPORT_TYPE_INPUT)
+                               return -EINVAL;
+
                if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
                        field = hiddev_lookup_usage(hid, &uref);
                        if (field == NULL)
@@ -557,37 +567,35 @@
                                return -EINVAL;
                }
 
-               uref.value = field->value[uref.usage_index];
+               switch (cmd) {
+                       case HIDIOCGUSAGE:
+                               uref.value = field->value[uref.usage_index];
+                               return copy_to_user((void *) arg, &uref, sizeof(uref));
+                               return 0;
+
+                       case HIDIOCSUSAGE:
+                               field->value[uref.usage_index] = uref.value;
+                               return 0;
 
-               return copy_to_user((void *) arg, &uref, sizeof(uref));
+                       case HIDIOCGCOLLECTIONINDEX:
+                               return field->usage[uref.usage_index].collection_index;
+               }
 
-       case HIDIOCSUSAGE:
-               if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
+               return 0;
+
+       case HIDIOCGCOLLECTIONINFO:
+               if (copy_from_user(&cinfo, (void *) arg, sizeof(cinfo)))
                        return -EFAULT;
 
-               if (uref.report_type == HID_REPORT_TYPE_INPUT)
+               if (cinfo.index >= hid->maxcollection)
                        return -EINVAL;
 
-               if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
-                       field = hiddev_lookup_usage(hid, &uref);
-                       if (field == NULL)
-                               return -EINVAL;
-               } else {
-                       rinfo.report_type = uref.report_type;
-                       rinfo.report_id = uref.report_id;
-                       if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
-                               return -EINVAL;
-
-                       if (uref.field_index >= report->maxfield)
-                               return -EINVAL;
-
-                       field = report->field[uref.field_index];
-                       if (uref.usage_index >= field->maxusage)
-                               return -EINVAL;
-               }
-
-               field->value[uref.usage_index] = uref.value;
+               cinfo.type = hid->collection[cinfo.index].type;
+               cinfo.usage = hid->collection[cinfo.index].usage;
+               cinfo.level = hid->collection[cinfo.index].level;
 
+               if (copy_to_user((void *) arg, &cinfo, sizeof(cinfo)))
+                       return -EFAULT;
                return 0;
 
        default:
@@ -628,11 +636,13 @@
        int retval;
        char devfs_name[16];
 
-       for (i = 0; i < hid->maxapplication; i++)
-               if (!IS_INPUT_APPLICATION(hid->application[i]))
+       for (i = 0; i < hid->maxcollection; i++)
+               if (hid->collection[i].type == 
+                   HID_COLLECTION_APPLICATION &&
+                   !IS_INPUT_APPLICATION(hid->collection[i].usage))
                        break;
 
-       if (i == hid->maxapplication)
+       if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0)
                return -1;
 
        retval = usb_register_dev(&hiddev_fops, HIDDEV_MINOR_BASE, 1, &minor);
@@ -657,10 +667,8 @@
 
        sprintf(devfs_name, "hiddev%d", minor);
        hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
-                                      DEVFS_FL_DEFAULT, USB_MAJOR,
-                                      minor + HIDDEV_MINOR_BASE,
-                                      S_IFCHR | S_IRUGO | S_IWUSR,
-                                      &hiddev_fops, NULL);
+               DEVFS_FL_DEFAULT, USB_MAJOR, minor + HIDDEV_MINOR_BASE,
+               S_IFCHR | S_IRUGO | S_IWUSR, &hiddev_fops, NULL);
        hid->minor = minor;
        hid->hiddev = hiddev;
 
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h    Sat Jul 13 14:31:20 2002
+++ b/include/linux/hiddev.h    Sat Jul 13 14:31:20 2002
@@ -49,6 +49,13 @@
        unsigned num_applications;
 };
 
+struct hiddev_collection_info {
+       unsigned index;
+       unsigned type;
+       unsigned usage;
+       unsigned level;
+};
+
 #define HID_STRING_SIZE 256
 struct hiddev_string_descriptor {
        int index;
@@ -64,9 +71,9 @@
 /* To do a GUSAGE/SUSAGE, fill in at least usage_code,  report_type and 
  * report_id.  Set report_id to REPORT_ID_UNKNOWN if the rest of the fields 
  * are unknown.  Otherwise use a usage_ref struct filled in from a previous 
- * successful GUSAGE/SUSAGE call to save time.  To actually send a value
- * to the device, perform a SUSAGE first, followed by a SREPORT.  If an
- * INITREPORT is done, a GREPORT isn't necessary before a GUSAGE.
+ * successful GUSAGE call to save time.  To actually send a value to the
+ * device, perform a SUSAGE first, followed by a SREPORT.  An INITREPORT or a
+ * GREPORT isn't necessary for a GUSAGE to return valid data.
  */
 #define HID_REPORT_ID_UNKNOWN 0xffffffff
 #define HID_REPORT_ID_FIRST   0x00000100
@@ -129,7 +136,7 @@
  * Protocol version.
  */
 
-#define HID_VERSION            0x010003
+#define HID_VERSION            0x010004
 
 /*
  * IOCTLs (0x00 - 0x7f)
@@ -150,6 +157,8 @@
 #define HIDIOCGUCODE           _IOWR('H', 0x0D, struct hiddev_usage_ref)
 #define HIDIOCGFLAG            _IOR('H', 0x0E, int)
 #define HIDIOCSFLAG            _IOW('H', 0x0F, int)
+#define HIDIOCGCOLLECTIONINDEX _IOW('H', 0x10, struct hiddev_usage_ref)
+#define HIDIOCGCOLLECTIONINFO  _IOWR('H', 0x11, struct hiddev_collection_info)
 
 /* 
  * Flags to be used in HIDIOCSFLAG
@@ -197,7 +206,7 @@
 int __init hiddev_init(void);
 void __exit hiddev_exit(void);
 #else
-static inline void *hiddev_connect(struct hid_device *hid) { return NULL; }
+static inline int hiddev_connect(struct hid_device *hid) { return -1; }
 static inline void hiddev_disconnect(struct hid_device *hid) { }
 static inline void hiddev_event(struct hid_device *hid, unsigned int usage, int 
value) { }
 static inline int hiddev_init(void) { return 0; }

===================================================================


This BitKeeper patch contains the following changesets:
+
## Wrapped with gzip_uu ##


begin 664 bkpatch19000
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
M4^Z9Y\A7T0O>!N6/*[EMAIL PROTECTED]"JP8KTYUZI?W9S<]DY/\/OU=6T"'8,B6DI)F@]
M^CD9'I65RC\G9BT_OX[O[QL%3?BL"FKS7GS,ER&)39W9)W@8\[-&C0TYS-<5
M8WWF8N&$28ZF-'$AA`'(C3@$5JX\F;^2#1`;A1`/]9X<$7F)0($"=E"JRKC`
M'Q6LWNP%L#OYF`3D/_@F$_A^<(!&#L`,H@%1+&:JGW(V!?=+VV9[V\::X)XI
M6DLW-22!/_CY`@71A(X%PY&+3XU`ZN"0#T1^\7W0_8ZIPBR92^]/>RL-P%M<
M!)HF%/Y6^^+L[O*V?W7W15"$7FT&)#B&*K?_W%)Q"IA5RN44/03;:&%95YAR
ML)_;S69N-3>0A\NN,VPGFR:B/0)66NP`Q(V43&W'U#!-FBT2YZCQP=[JVS'H
M!C,)):#8HXG+W>+&V8;V/;--A<]>/WW+?.O[YEML_IK)FV9"(FR"=?_9HWXP
MIN2N]VO_]_95Z[K;AT/]\JE-%C[RBPS:M``-277GO)U#]R%"%*%]^&R&5D3<
M$.ZR)$:3V6'\N4Q.;366&I/!_[KK=#_W\T3_6^TM")35&,#WH50I4H)%`:PG
M!A[3("](W&@\!CX6>@5!;C_/:/?A6>.P^V`SJQ)HL:!]!116L\&%IC%SVC@_
M&T/X_MC/XL$>1LJG\"5@@<B:EU&6;GCKIG%89;C1AK%1-W2"$421'[@COCSK
M?&FW^IVKF[M;](!#3.LA3A>W!V.XQA84G&4Y#DPMES#D6T117+/!I5?Y!N9K
MYUN&55;"<W;`0LAE]I:S.J<`0Z^6HD/D@-Z9/QF](K'LZ#@\P((+UQ`6=,18
M=F)LW<7PJW!H%8%A\_`AF`<=ZP,A\N%#'LFNFL\39L[\N]X92.\-_%,M4-[=
M]#^!N+=[GW=#PU6T"ILYZW;/_M[O=?Z[C?!]I#/)'5`%4F\R&_RZ%=T]"QJ;
M3>3O-V2C;:(.K<_O\RKR;@G^F\K9Y<+F3E5LS/`-W9SJ&C9,,,-?3O#M;0F^
M3.KF#TOONW04/4%6'@?C-$_P<RLBQ,<)!&?ID+Y^A/Q]')$P&O,J$X5\&U)T
M7I/?*47/^?&>'%TS#&)N..JBS+G34;^EJ[)C+:?432F*.8K6E-]]U#JI:S^Z
MACVC=59OF54KQ_193/S=R&/GRQM".YUOSH3WG*_.(HV.;C4Q7M_5(OX8>]CI
M<5<EOEUKW*I5(+;)*O#\P2@(<*UE*JOK)79'L[1K2W(W,5VT12B@NJ5H-A-0
M57Z[A-K_!@G%LU\CBJQMNHLDOLO&=(`O<)Y%6%F.VRKR"UB#EJKQ_),]1-@U
MF4I%,1&:92K9.`D>QE2LE.:I)2+X<O8'=[V]^V-RN+^B3HZE.+)_"/@,90$?
MJYL<X[BQ,+ZTT'$%$.<-@S%8@'*A#[&W-%7%+>)#6X@P!>A]014QBP"TET&2
M%G<>Q%(PH%RY<Y:#5?+)5]EH`%X%*\QY$=(K+5E"M&@-*LMX6/[ME2EI:9;%
M-F<MGLC"9ZET4;(BO=NS\\\LIH&09*V&LW[L3DK^AI;P;GJ^T`HN5%U3;7#4
M3-7-MZNZI4'@\>,:"V>>-VO@Q10=$1=7CQN`//P(TIW;#&@?6*][%_O`^/,>
M$]%4%Z3&#YV'!-Q4C.T_R(SI)(K3?H!9S/^BS'3;-]?=6Y8/GO4^0^AO@]Y:
M$+K*-DL`%`4#V$H"/M@=DCV&CL7&KI-0(A^A&;B*TB'&9J"M7D3J=3)?)0"&
MA-AT?67=Q5GGA&E*90!O'GGA%K$MTG/1Z?9NCP`J1*T]*9#2<3::[0-?-<;T
M)2TZ"1SVA'Q8!UTEBS6DRA)C3LB>6#'B+\A^E;#I]=/`.YZ37JFLI/VJ_8=(
M>H$/?_:'P`U`Q\MRRT3"DD,G&7Y=<6#+YW5?WC?OG92VF%.!C_KI_S>WP!\Y
M69@>E:MY+=5@]6W5Q.PTKSHD:('[LZXM:]46R_E!B*TE?-1`L,;821XZ,0P-
M,M_'NF8^V8VR<5J#K,#WX=?^9!(E$"'AC1^VG+UV.93;U:N]81W-8&&C9C3G
MZX!C*]9@7>YBD6",UF6?/6ID866^\$RM$8,[\H013'K`0SY482U>]MU\%<+%
M?X\16%\&9L5H#N?/X(QE.$S%$,B;`3&?A=0%Q^C);.[);"PH_P.KW+N'S=OB
M9BEO*&Z,GY$C8)``7&8X14G<'!8+S41^RX#9J6)L7>R-FP8+K,+#QD-HZ;K"
M'DT3!PW%1(88&LK>S'!TKL][+*PZ6A@K7V(X@HF`32N:IB./_'12P++YN.$L
MIGXCUT\QQ<@-Q^W?;]KSLM>J/;8,IH$=?-@`4YA^6*\HB@@T%G3#AZW\Y(09
MEJ_S=@;[^96]$1LUQ^+:;C1Y[:=1'^^P[.WQXF$5#ZY&/N#,61T??U2K"W-E
M?BHK65F9-5764($MIQG-9;3`!I6S@<68E<TG(\Q=:.0LK;G4L^&-:EA-1S-A
M@);I4FE[ZU:^N#Z:-="!A7X<C3@3/S#EKI%%9N9<9.^JF"0:9I/OD-6K.")\
MV>#A]^EJQ6A!U$<4&^8U;<89/H?+VI)B"`BYZA[/9O#2V98I14\PGU.T7S?.
M*7(-PYZW2C<)6<ZM,G]$[6")$P@%-FM4[,JH>$P_K@@@[6#+<IB?WEP,,#4T
MW1W^V&3UT'YP3/^3!?%CDL<<8HY9S6UIRS3Q2DK'-'GW"%Y=]/H7ET62R;L-
M7\[^\[I;(R/P:#$YR&\B]K]TKJZ[_5_/>FUL_L%N+LY_ZY(I@6_=NT_7_-O?
M[GHP\T/AD*))4N/1#<]G5E_\7IW+?,_-\W(9==.%\^)FJ#[5K*:MLT3&>GL>
M@S=#?VP:4]3.A)+IH9A7\YNA_)9\*3E9O=_W)":&0BQI<TSRIY"X%,9Q-I`;
MC]GOPC*42PS?F!.#0`32%Q,M%$1J2>:Z-$GP6E?N*5V6VD4D<9XH28,1N\@7
M$<=-,WB#V0KD<0[A[HQ?BD1$O/9<(Q,:X^U0@.#N!JQ^G$#PYT=X90R(&;SB
M.^YT`?79F'2N.K?\-\'T$;%]RG\'R?AC"B>$-#KQ*\\O"TK3XFHH$@-F"[OU
M#;P+IO*[8&JIRO-[N]L#BU"IR"^R(LLR**EB8$@B`*WP895^Y_IO>Q]_^U@C
M6$:JK;LP6=V$Y^*:H>G.\"AE/*4CQT!<9N$&?\P"Y!!7$.+D4L^QU$V$P(3,
@KWZ1;_/_\\@=4O<QR48G`UM1-(WZTO\!_+/)-=XT````
`
end
-- 
Vojtech Pavlik
SuSE Labs


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to