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 M'XL(`)@=,#T``\4[:7?B2)*?T:_(GGZORMB`=0O9:T^[#:YFRV5[P>[IV1H_ MGI!21F.!6!T^IJG][1N1*4$B3KMJWM)5)4A%1D9&QAW9/Y.[A,9'E:?HGREU MA]+/Y+<H28\JZ7,0!@_#M)&YSPWW7S#>C2(8/QQ&(WJ80Q\.'@^S9%!7&X8$ M$#=.Z@[)$XV3HXK2T&8CZ>N$'E6Z[4]WEV==23HY(>=#9_Q`>S0E)R?2X/$7 M+Z-AXS&.G&$CBA^FL]=3598515$-63-,Q9BJ34W3IXHI#SSXZJF6[0],6WJ( MZ<,O?+H;C1:GJ[*EJ*HFFX8QU0W%;$HMHC1,LTED]5"V#A6-*/J1)A\IRH&L M'LDRR3?W2XD%Y,`B=5GZE7P_O>>2"ZS)PH\)"9V4)BG))AY^(7X4DV'@D3H9 M.8_PVYE,PL!UTB`:$S<*0^KB5Y@.*WIA,'X@HPPX/(IB2B;1,XW]+"1I1)PP MC)[)@*8IC4F6.`^41#[YK=,B=S<]FC2DS\10--62;N9G(=7?^)$DV9&ETQ4, M"<9NF'GT$"C,7@YA0QY]:@SGW-%E0[>GBFP9YE139$?Q+,W2J.%30U_'_PU( M\8PU..6F84\-6U.-E42U(C<;T7'*N(ER6^!(7X2#TQ49CDQ5#<N:&HJN>'+3 M=BW/L`>>M9:T;:CG!#:G"DC":@*].$#E*>8O,LQ6S*EBJZ8Y;1JZ-QC8CN^[ MMF')[EJJ1'S!>)*E<ZPBQ^2FTM1W(:C.D#3<!;)4>:KKMFE/7=O5;>I;KJ:Y M5%FK1JNI$E&+M"E-RU1WHLVC@^RAS#)KJH+&*S#H6]Y`4[2!0545=/]MQ`FX M1>)`T*S5\E\FS@7]7,$WU;:4*?P=`'E-ZON*H5EO9=P<M2ADABSO=J8HI&Y9 MSF!?P+KF0)45:E%'5S40-OMMA,T0+XB:JE@J\P";-&:U4_A^]2W[B>U:J\-_ MBMXTY*FBF:;%7(>^X#C4YI'1W.8X%)W4E1_F.>Z8KR#ID!)/W`&!/V#A6^W? MP6T$:.*YJ;DF]?B9_0&3?;.1\^]P`2U5(8K48?^"IQDT7`+CIV0NFP0'\I%< MS?.1KX_T=1`YL7<XBK*$'OXS>DW2P'T\I$]`X+W44>0FL2785.?Z_-/Y]>5E M^_RV<WW5N;J`39$DC3,W)9S\_MP]]H.Q'Y&]F#K>X7,<I+0JW0Z#A,0TS>(Q M.%629!,06`@_P"DB'W%"/.)<=`;1$ZV121P]!1YZV'$$<./P55KMC),:&60I M>ER&2GC!CX@^!2X%?YTT".FDDA,FT8P2!`AAL^6I)`2-2H`L-CX,:.S$[O"U M`?N@P&3PZ1,G23B$LXX!.7N>@W28;]*C+T3R`QIZ!#</<<)\/!TZ*4F&408O M!S2GD'I`-*X91&X:$C\(0[:FA/,B^"<F#!W;FR]@"S"RB1_@/>#ENP@=B'.$ M+4H,LL8G,?0%5^H*@>@&24P(C>-QA)36VYVKW\\N&](_0"PLC>CPA0G&@ERT MVG\L"08+?_HQ]<E>+@U=@?T"19QT8&SD!J!A7L$ZV`S#P7@1)$@XB@&P_QDX M0(MC$C#-3DR839(@A<`+C=\F2[[:^'V/0Y$*NY2`Y.SJ2-!0JYHQ!8.JJ\SN M:?;;#9\-(3-8H!]E^;Y`3#R/?$%WUV@D$Q_Q-YS0`QW#F82`95/$G$?("8X\ M1_$C8(ECP!*^LI"9>=62/=W$S??84T630;CA8:-=Q8>J2Y4`I'?B@,V*ZZ?< MI-1/1\Z+(',@5V4`P2(DP;]HE?PI52KB%/(XPGV[>_@Z\O?FBB-8DRK9AVF5 M"L'/EB7(/E%K<^A/%S?]S^WN5?NR>@RCN(E%BJ_N+B\Y615O\+#W%]\)0E"\ M%$TDHPP]G3#%B6/G]2\,686;"[`6^.L;_!W1D3MY%5:H;2`7J23\LWWS.>`V M_AYS(L!PB=L\V#:O1N1_%S6/?DSIDN`("!%H_6N0D/F/S:#Y\9\0%>"^@7&> MP8HPJ>,^?EWWHC])XX.#>W*R8J$%63]&]`M4;MC"`=F&[N#@&!1-5T#M!*SU 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