X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fhid%2Fhid-core.c;h=62e21cc739381e314908bbd0d6e971a303a11c56;hb=5f757f91e70a97eda8f0cc13bddc853209b2d173;hp=18c2b3cf6bcc97873a120b0d7a143c823d27dc80;hpb=cd39301a68f9604854f3543117b01dc73cbe193f;p=powerpc.git diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 18c2b3cf6b..62e21cc739 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -4,7 +4,7 @@ * Copyright (c) 1999 Andreas Gal * Copyright (c) 2000-2005 Vojtech Pavlik * Copyright (c) 2005 Michael Haboustak for Concept2, Inc - * Copyright (c) 2006 Jiri Kosina + * Copyright (c) 2006-2007 Jiri Kosina */ /* @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -27,30 +26,21 @@ #include #include #include - -#undef DEBUG -#undef DEBUG_DATA +#include #include #include +#include /* * Version Information */ #define DRIVER_VERSION "v2.6" -#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik" -#define DRIVER_DESC "USB HID core driver" +#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik, Jiri Kosina" +#define DRIVER_DESC "HID core driver" #define DRIVER_LICENSE "GPL" -/* - * Module parameters. - */ - -static unsigned int hid_mousepoll_interval; -module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644); -MODULE_PARM_DESC(mousepoll, "Polling interval of mice"); - /* * Register a new report for a device. */ @@ -551,6 +541,7 @@ void hid_free_device(struct hid_device *device) } kfree(device->rdesc); + kfree(device->collection); kfree(device); } EXPORT_SYMBOL_GPL(hid_free_device); @@ -656,7 +647,7 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) 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))) { + if (!(device->rdesc = kmalloc(size, GFP_KERNEL))) { kfree(device->collection); kfree(device); return NULL; @@ -664,12 +655,13 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) memcpy(device->rdesc, start, size); device->rsize = size; - if (!(parser = kzalloc(sizeof(struct hid_parser), GFP_KERNEL))) { + if (!(parser = vmalloc(sizeof(struct hid_parser)))) { kfree(device->rdesc); kfree(device->collection); kfree(device); return NULL; } + memset(parser, 0, sizeof(struct hid_parser)); parser->device = device; end = start + size; @@ -677,45 +669,40 @@ struct hid_device *hid_parse_report(__u8 *start, unsigned size) if (item.format != HID_ITEM_FORMAT_SHORT) { dbg("unexpected long global item"); - kfree(device->collection); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } 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->collection); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } if (start == end) { if (parser->collection_stack_ptr) { dbg("unbalanced collection at end of report description"); - kfree(device->collection); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } if (parser->local.delimiter_depth) { dbg("unbalanced delimiter at end of report description"); - kfree(device->collection); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } - kfree(parser); + vfree(parser); return device; } } dbg("item fetching failed at offset %d\n", (int)(end - start)); - kfree(device->collection); hid_free_device(device); - kfree(parser); + vfree(parser); return NULL; } EXPORT_SYMBOL_GPL(hid_parse_report); @@ -768,8 +755,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) report += offset >> 3; /* adjust byte index */ offset &= 7; /* now only need bit offset into one byte */ - x = get_unaligned((u64 *) report); - x = le64_to_cpu(x); + x = le64_to_cpu(get_unaligned((__le64 *) report)); x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ return (u32) x; } @@ -784,7 +770,7 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) */ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) { - u64 x; + __le64 x; u64 m = (1ULL << n) - 1; WARN_ON(n > 32); @@ -795,10 +781,10 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3 report += offset >> 3; offset &= 7; - x = get_unaligned((u64 *)report); + x = get_unaligned((__le64 *)report); x &= cpu_to_le64(~(m << offset)); x |= cpu_to_le64(((u64) value) << offset); - put_unaligned(x, (u64 *) report); + put_unaligned(x, (__le64 *) report); } /* @@ -886,8 +872,13 @@ static void hid_output_field(struct hid_field *field, __u8 *data) unsigned count = field->report_count; unsigned offset = field->report_offset; unsigned size = field->report_size; + unsigned bitsused = offset + count * size; unsigned n; + /* make sure the unused bits in the last byte are zeros */ + if (count > 0 && size > 0 && (bitsused % 8) != 0) + data[(bitsused-1)/8] &= (1 << (bitsused % 8)) - 1; + for (n = 0; n < count; n++) { if (field->logical_minimum < 0) /* signed values */ implement(data, offset + n * size, size, s32ton(field->value[n], size)); @@ -954,8 +945,8 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i return -1; } -#ifdef DEBUG_DATA - printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", len, report_enum->numbered ? "" : "un"); +#ifdef CONFIG_HID_DEBUG + printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un"); #endif n = 0; /* Normally report number is 0 */ @@ -964,7 +955,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i size--; } -#ifdef DEBUG_DATA +#ifdef CONFIG_HID_DEBUG { int i; printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size); @@ -983,7 +974,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int i if (size < rsize) { dbg("report %d is too short, (%d < %d)", report->id, size, rsize); - return -1; + memset(data + size, 0, rsize - size); } if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)