/*
- * USB HID support for Linux
+ * HID support for Linux
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2005 Vojtech Pavlik <vojtech@suse.cz>
#undef DEBUG
#undef DEBUG_DATA
-#include <linux/usb.h>
-
#include <linux/hid.h>
#include <linux/hiddev.h>
#define DRIVER_VERSION "v2.6"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
-#define DRIVER_DESC "USB HID core driver"
+#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.
*/
* Free a device structure, all reports, and all fields.
*/
-static void hid_free_device(struct hid_device *device)
+void hid_free_device(struct hid_device *device)
{
unsigned i,j;
}
kfree(device->rdesc);
+ kfree(device->collection);
kfree(device);
}
+EXPORT_SYMBOL_GPL(hid_free_device);
/*
* Fetch a report description item from the data stream. We support long
* enumerated, fields are attached to these reports.
*/
-static struct hid_device *hid_parse_report(__u8 *start, unsigned size)
+struct hid_device *hid_parse_report(__u8 *start, unsigned size)
{
struct hid_device *device;
struct hid_parser *parser;
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;
kfree(parser);
return NULL;
}
+EXPORT_SYMBOL_GPL(hid_parse_report);
/*
* Convert a signed n-bit integer to signed 32-bit integer. Common
WARN_ON(n > 32);
report += offset >> 3; /* adjust byte index */
- offset &= 7; /* now only need bit offset into one byte */
+ offset &= 7; /* now only need bit offset into one byte */
x = get_unaligned((u64 *) report);
x = le64_to_cpu(x);
- x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
+ x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */
return (u32) x;
}
hid_dump_input(usage, value);
if (hid->claimed & HID_CLAIMED_INPUT)
hidinput_hid_event(hid, field, usage, value);
- if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt)
- hiddev_hid_event(hid, field, usage, value);
+ if (hid->claimed & HID_CLAIMED_HIDDEV && interrupt && hid->hiddev_hid_event)
+ hid->hiddev_hid_event(hid, field, usage, value);
}
/*
* reporting to the layer).
*/
-static void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
+void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt)
{
unsigned n;
unsigned count = field->report_count;
exit:
kfree(value);
}
-
+EXPORT_SYMBOL_GPL(hid_input_field);
/*
* Output the field into the report.
unsigned size = field->report_size;
unsigned n;
+ /* make sure the unused bits in the last byte are zeros */
+ if (count > 0 && size > 0)
+ data[(count*size-1)/8] = 0;
+
for (n = 0; n < count; n++) {
if (field->logical_minimum < 0) /* signed values */
implement(data, offset + n * size, size, s32ton(field->value[n], size));
* Create a report.
*/
-static void hid_output_report(struct hid_report *report, __u8 *data)
+void hid_output_report(struct hid_report *report, __u8 *data)
{
unsigned n;
for (n = 0; n < report->maxfield; n++)
hid_output_field(report->field[n], data);
}
+EXPORT_SYMBOL_GPL(hid_output_report);
/*
* Set a field value. The report this field belongs to has to be
field->value[offset] = value;
return 0;
}
+EXPORT_SYMBOL_GPL(hid_set_field);
+
+int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt)
+{
+ struct hid_report_enum *report_enum = hid->report_enum + type;
+ struct hid_report *report;
+ int n, rsize;
+
+ if (!hid)
+ return -ENODEV;
+
+ if (!size) {
+ dbg("empty report");
+ return -1;
+ }
+
+#ifdef DEBUG_DATA
+ printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered)\n", size, report_enum->numbered ? "" : "un");
+#endif
+
+ n = 0; /* Normally report number is 0 */
+ if (report_enum->numbered) { /* Device uses numbered reports, data[0] is report number */
+ n = *data++;
+ size--;
+ }
+
+#ifdef DEBUG_DATA
+ {
+ int i;
+ printk(KERN_DEBUG __FILE__ ": report %d (size %u) = ", n, size);
+ for (i = 0; i < size; i++)
+ printk(" %02x", data[i]);
+ printk("\n");
+ }
+#endif
+
+ if (!(report = report_enum->report_id_hash[n])) {
+ dbg("undefined report_id %d received", n);
+ return -1;
+ }
+
+ rsize = ((report->size - 1) >> 3) + 1;
+
+ if (size < rsize) {
+ dbg("report %d is too short, (%d < %d)", report->id, size, rsize);
+ return -1;
+ }
+
+ if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
+ hid->hiddev_report_event(hid, report);
+
+ for (n = 0; n < report->maxfield; n++)
+ hid_input_field(hid, report->field[n], data, interrupt);
+
+ if (hid->claimed & HID_CLAIMED_INPUT)
+ hidinput_report_event(hid, report);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(hid_input_report);
+
+MODULE_LICENSE(DRIVER_LICENSE);