diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-al.c
linux-2.6.21-rc6-mm1.new/drivers/hid/hid-al.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-al.c 1970-01-01
08:00:00.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/hid-al.c 2007-04-15
21:34:44.000000000 +0800
@@ -0,0 +1,505 @@
+/*
+ * HID abstract layer for Linux driver model
+ *
+ * Copyright (c) 2007 Li Yu
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
+#include <linux/wait.h>
+
+#include "hid-inter.h"
+
+static spinlock_t hid_lock;
+
+struct hid_transport* hid_transports[BUS_MAX];
+static unsigned long hid_transports_exiting[BUS_MAX];
+#define set_hid_transport_exiting(tl) (set_bit(1,
hid_transports_exiting+(tl)->bus))
+#define is_hid_transport_exiting(tl) (test_bit(1,
hid_transports_exiting+(tl)->bus))
+#define clear_hid_transport_exiting(tl) (clear_bit(1,
hid_transports_exiting+(tl)->bus))
+EXPORT_SYMBOL(hid_transports);
+
+
+struct hid_driver* hid_sticky_drivers[NR_STICKY];
+static DECLARE_WAIT_QUEUE_HEAD(hid_sticky_clean_barrier);
+static unsigned long hid_sticky_exiting[NR_STICKY];
+#define set_hid_sticky_exiting(i) (set_bit(1, hid_sticky_exiting+i))
+#define is_hid_sticky_exiting(i) (test_bit(1, hid_sticky_exiting+i))
+#define clear_hid_sticky_exiting(i) (clear_bit(1, hid_sticky_exiting+i))
+
+static int hid_sticky_get(struct hid_driver *hid_drv)
+{
+ return try_module_get(hid_drv->module);
+}
+
+static void hid_sticky_put(struct hid_driver *hid_drv)
+{
+ module_put(hid_drv->module);
+ if(!module_refcount(hid_drv->module))
+ wake_up(&hid_sticky_clean_barrier);
+}
+
+int hid_sticky_driver_exit(int i)
+{
+ if (is_hid_sticky_exiting(i)) {
+ hid_sticky_put(hid_sticky_drivers[i]);
+ return 1;
+ }
+ return 0;
+}
+
+static int hid_driver_skip_device_helper(struct device *dev, void *data)
+{
+ struct skip_id *skip = data;
+ int mask = skip->mask;
+ struct hid_device *hid_dev = to_hid_device(dev);
+
+ if ((mask & HID_IGNORE_VENDOR) &&
+ (hid_dev->vendor != skip->vendor))
+ return 0;
+ if ((mask & HID_IGNORE_PRODUCT) &&
+ (hid_dev->product != skip->product))
+ return 0;
+ if ((mask & HID_IGNORE_VERSION) &&
+ (hid_dev->version != skip->version))
+ return 0;
+ if ((mask & HID_IGNORE_COUNTRY) &&
+ (hid_dev->country != skip->country))
+ return 0;
+
+ return 1;
+}
+
+static int hid_driver_match_skip_table(struct hid_driver *hid_drv,
+ struct hid_device *hid_dev)
+{
+ struct skip_id *skip;
+
+ list_for_each_entry(skip, &hid_drv->skip_table, node) {
+ if (hid_driver_skip_device_helper(&hid_dev->device, skip))
+ return 1;
+ }
+ return 0;
+}
+static int hid_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct hid_driver *hid_drv;
+ struct hid_device *hid_dev;
+
+ hid_drv = to_hid_driver(drv);
+ hid_dev = to_hid_device(dev);
+
+ if (is_hid_driver_sticky(hid_drv))
+ /* the sticky driver match device do not pass here. */
+ return 0;
+ if (hid_dev->bus != hid_drv->bus)
+ return 0;
+ if (hid_driver_match_skip_table(hid_drv, hid_dev))
+ return 0;
+ if (!hid_drv->match || hid_drv->match(hid_drv, hid_dev)) {
+ hid_dev->driver = hid_drv;
+ return 1;
+ }
+ return 0;
+}
+
+static ssize_t hid_driver_show_version(struct device_driver *drv, char *buf)
+{
+ struct hid_driver *hid_drv;
+
+ hid_drv = to_hid_driver(drv);
+ return snprintf(buf, PAGE_SIZE, "%s\n", hid_drv->version);
+}
+
+static ssize_t hid_driver_show_sticky(struct device_driver *drv, char *buf)
+{
+ struct hid_driver *hid_drv;
+
+ hid_drv = to_hid_driver(drv);
+ return snprintf(buf, PAGE_SIZE, "%d\n", is_hid_driver_sticky(hid_drv));
+}
+
+static ssize_t hid_driver_show_skip(struct device_driver *drv, char *buf)
+{
+ /* FIXME: we really need this? */
+ return snprintf(buf, PAGE_SIZE, "\n");
+}
+
+static void hid_driver_skip_device(struct hid_driver *hid_drv,
+ struct skip_id *skip)
+{
+ struct device *dev;
+
+ do {
+ dev = driver_find_device(&hid_drv->driver, NULL,
+ skip, hid_driver_skip_device_helper);
+ if (!dev)
+ return;
+ device_release_driver(dev);
+ } while (1);
+}
+
+static ssize_t hid_driver_store_skip(struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ struct hid_driver *hid_drv;
+ int vendor = 0, product = 0, version = 0, country = 0, mask = 0;
+ struct skip_id *skip;
+ int n;
+
+ hid_drv = to_hid_driver(drv);
+ n = sscanf(buf, "skip:0x%x,0x%x,0x%x,0x%x,0x%x\n",
+ &vendor, &product, &version, &country, &mask);
+ if (n<2)
+ return -EINVAL;
+ skip = kzalloc(sizeof(struct skip_id), GFP_KERNEL);
+ if (!skip)
+ return -ENOMEM;
+ if (!mask)
+ mask = HID_IGNORE_VENDOR|HID_IGNORE_PRODUCT;
+ skip->vendor = vendor;
+ skip->product = product;
+ skip->version = version;
+ skip->country = country;
+ skip->mask = mask;
+ spin_lock(&hid_lock);
+ list_add_tail(&skip->node, &hid_drv->skip_table);
+ spin_unlock(&hid_lock);
+ hid_driver_skip_device(hid_drv, skip);
+ return count;
+}
+
+static struct driver_attribute hidbus_driver_attrs[] = {
+ __ATTR(version, 0444, hid_driver_show_version, NULL),
+ __ATTR(sticky, 0444, hid_driver_show_sticky, NULL),
+ __ATTR(skip_id, 0644, hid_driver_show_skip, hid_driver_store_skip),
+ __ATTR_NULL
+};
+
+struct bus_type hid_bus_type = {
+ .name = "hid",
+ .match = hid_bus_match,
+ .drv_attrs = hidbus_driver_attrs,
+};
+
+static void hid_dummy_release(struct device *dev)
+{
+}
+
+struct device hid_bus = {
+ .bus_id = "hidbus0",
+ .release = hid_dummy_release
+};
+
+static void hid_device_create_links(struct hid_device *hid_dev)
+{
+ struct hid_input *hidinput;
+ int ret;
+
+ list_for_each_entry(hidinput, &hid_dev->inputs, list)
+ ret = sysfs_create_link(&hid_dev->device.kobj,
+ &hidinput->input->dev.kobj,
+ hidinput->input->dev.bus_id);
+ ret = sysfs_create_link(&hid_dev->device.kobj,
+ &hid_dev->dev->kobj, "transport_device");
+}
+
+static void hid_device_remove_links(struct hid_device *hid_dev)
+{
+ struct hid_input *hidinput;
+
+ list_for_each_entry(hidinput, &hid_dev->inputs, list)
+ sysfs_remove_link(&hid_dev->device.kobj,
+ hidinput->input->dev.bus_id);
+
+ sysfs_remove_link(&hid_dev->device.kobj, "transport_device");
+}
+
+static int hid_drv_probe(struct device *dev)
+{
+ struct hid_device *hid_dev;
+ struct hid_driver *hid_drv;
+ struct hid_transport *tl;
+ int i;
+
+ hid_dev = to_hid_device(dev);
+ hid_drv = hid_dev->driver;
+ tl = hid_transports[hid_dev->bus];
+
+ if (is_hid_transport_exiting(tl))
+ return -ENODEV;
+ if (!try_module_get(tl->module))
+ return -ENODEV;
+
+ if (!hid_drv->probe)
+ if (!hidinput_connect(hid_dev))
+ goto ok;
+ if (hid_drv->probe(hid_dev)) {
+ hid_dev->driver = NULL;
+ return -ENODEV;
+ }
+ok:
+ for (i=0; i<NR_STICKY; ++i) {
+ hid_drv = hid_sticky_drivers[i];
+ if (!hid_drv || is_hid_sticky_exiting(i))
+ continue;
+ if (!hid_sticky_get(hid_drv))
+ continue;
+ if (!try_module_get(tl->module)) {
+ hid_sticky_put(hid_drv);
+ continue;
+ }
+ if (!hid_drv->probe)
+ set_bit(i, &hid_dev->sticky_driver);
+ else if (!hid_drv->probe(hid_dev))
+ set_bit(i, &hid_dev->sticky_driver);
+ else {
+ clear_bit(i, &hid_dev->sticky_driver);
+ hid_sticky_put(hid_drv);
+ module_put(tl->module);
+ }
+ }
+ hid_device_create_links(hid_dev);
+ return 0;
+}
+
+static int hid_drv_remove(struct device *dev)
+{
+ struct hid_device *hid_dev;
+ struct hid_driver *hid_drv;
+ struct hid_transport *tl;
+ int i;
+
+ hid_dev = to_hid_device(dev);
+ hid_drv = hid_dev->driver;
+ tl = hid_transports[hid_dev->bus];
+
+ hid_device_remove_links(hid_dev);
+ module_put(tl->module);
+ if (!hid_drv->remove)
+ hidinput_disconnect(hid_dev);
+ else
+ hid_drv->remove(hid_dev);
+
+ for (i=0; i<NR_STICKY; ++i) {
+ hid_drv = hid_sticky_drivers[i];
+ if (!hid_drv)
+ continue;
+ if (hid_drv->remove)
+ hid_drv->remove(hid_dev);
+ clear_bit(i, &hid_dev->sticky_driver);
+ hid_sticky_put(hid_drv);
+ module_put(tl->module);
+ }
+ return 0;
+}
+
+static void hid_drv_shutdown(struct device *dev)
+{
+ struct hid_device *hid_dev;
+
+ hid_dev = to_hid_device(dev);
+
+ if (!hid_dev->driver);
+ return;
+ if (hid_dev->driver->shutdown)
+ hid_dev->driver->shutdown(hid_dev);
+}
+
+static inline int hid_check_transport(int bus)
+{
+ if (bus<=0 || bus>=BUS_MAX)
+ return 0;
+
+ return (int)hid_transports[bus];
+}
+
+static int match_device_for_transport(struct device *dev, void *bus)
+{
+ struct hid_device *hid_dev = to_hid_device(dev);
+
+ if (hid_dev->bus != (int)bus)
+ return 0;
+ device_release_driver(dev);
+ return 0;
+}
+
+static void unbind_devices_for_transport(int bus)
+{
+ struct device *dev;
+
+restart:
+ dev = bus_find_device(&hid_bus_type, NULL,
+ (void*)bus, match_device_for_transport);
+ if (!dev)
+ return;
+ goto restart;
+}
+
+int hid_register_device(struct hid_device *hid_dev)
+{
+ if (!hid_dev || !hid_check_transport(hid_dev->bus))
+ return -EINVAL;
+
+ hid_dev->device.bus = &hid_bus_type;
+ hid_dev->device.release = hid_dummy_release;
+ hid_dev->device.parent = &hid_bus;
+ INIT_LIST_HEAD(&hid_dev->inputs);
+ hid_transports[hid_dev->bus]->update_busid(hid_dev);
+ return device_register(&hid_dev->device);
+}
+EXPORT_SYMBOL_GPL(hid_register_device);
+
+void hid_unregister_device(struct hid_device *hid_dev)
+{
+ device_unregister(&hid_dev->device);
+}
+EXPORT_SYMBOL_GPL(hid_unregister_device);
+
+int hid_register_driver(struct hid_driver *hid_drv)
+{
+ int ret, i;
+
+ if (!hid_drv)
+ return -EINVAL;
+ if (!hid_check_transport(hid_drv->bus))
+ return -EINVAL;
+ if (!try_module_get(hid_drv->module))
+ return -EINVAL;
+ hid_drv->driver.bus = &hid_bus_type;
+ hid_drv->driver.name = hid_drv->name;
+ hid_drv->driver.probe = hid_drv_probe;
+ hid_drv->driver.remove = hid_drv_remove;
+ hid_drv->driver.shutdown = hid_drv_shutdown;
+ INIT_LIST_HEAD(&hid_drv->skip_table);
+ ret = driver_register(&hid_drv->driver);
+ if (!is_hid_driver_sticky(hid_drv))
+ return ret;
+ spin_lock(&hid_lock);
+ for (i=0; i<NR_STICKY; ++i) {
+ if (!hid_sticky_drivers[i]) {
+ clear_hid_sticky_exiting(i);
+ hid_sticky_drivers[i] = hid_drv;
+ break;
+ }
+ }
+ spin_unlock(&hid_lock);
+ if (i<NR_STICKY)
+ return 0;
+ module_put(hid_drv->module);
+ driver_unregister(&hid_drv->driver);
+ return -EBUSY;
+}
+EXPORT_SYMBOL_GPL(hid_register_driver);
+
+void hid_unregister_driver(struct hid_driver *hid_drv)
+{
+ struct skip_id *skip, *next;
+ int i;
+
+ if (!is_hid_driver_sticky(hid_drv))
+ goto skip_sticky;
+ for (i=0; i<NR_STICKY; ++i)
+ if (hid_drv == hid_sticky_drivers[i]) {
+ set_hid_sticky_exiting(i);
+ break;
+ }
+ if (i>=NR_STICKY)
+ return;
+ module_put(hid_drv->module);
+ wait_event(hid_sticky_clean_barrier, !module_refcount(hid_drv->module));
+ spin_lock(&hid_lock);
+ hid_sticky_drivers[i] = NULL;
+ spin_unlock(&hid_lock);
+
+skip_sticky:
+ driver_unregister(&hid_drv->driver);
+ list_for_each_entry_safe(skip, next, &hid_drv->skip_table, node) {
+ list_del(&skip->node);
+ kfree(skip);
+ }
+}
+EXPORT_SYMBOL_GPL(hid_unregister_driver);
+
+int hid_register_transport(struct hid_transport *tl)
+{
+ int ret;
+
+ if (!tl || tl->bus>=BUS_MAX || tl->bus<=0)
+ return -EINVAL;
+ if (!try_module_get(tl->module))
+ return -EINVAL;
+ ret = 0;
+ spin_lock(&hid_lock);
+ if (!hid_transports[tl->bus]) {
+ hid_transports[tl->bus] = tl;
+ clear_hid_transport_exiting(tl);
+ }
+ else
+ ret = -EBUSY;
+ spin_unlock(&hid_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hid_register_transport);
+
+void hid_unregister_transport(struct hid_transport *tl)
+{
+ if (!tl || tl->bus>=BUS_MAX || tl->bus<=0 || tl !=
hid_transports[tl->bus])
+ return;
+ set_hid_transport_exiting(tl);
+ module_put(tl->module);
+ unbind_devices_for_transport(tl->bus);
+ spin_lock(&hid_lock);
+ hid_transports[tl->bus] = NULL;
+ spin_unlock(&hid_lock);
+ return;
+}
+EXPORT_SYMBOL_GPL(hid_unregister_transport);
+
+static ssize_t hid_bus_show_version(struct bus_type *bus, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0.1.0\n");
+}
+
+BUS_ATTR(version, 0444, hid_bus_show_version, NULL);
+
+static int __init hid_init(void)
+{
+ int ret;
+
+ spin_lock_init(&hid_lock);
+ ret = device_register(&hid_bus);
+ if (ret)
+ return ret;
+ ret = bus_register(&hid_bus_type);
+ if (ret) {
+ device_unregister(&hid_bus);
+ return ret;
+ }
+ ret = bus_create_file(&hid_bus_type, &bus_attr_version);
+ return 0;
+}
+
+static void __exit hid_exit(void)
+{
+ bus_remove_file(&hid_bus_type, &bus_attr_version);
+ device_unregister(&hid_bus);
+ bus_unregister(&hid_bus_type);
+}
+
+module_init(hid_init);
+module_exit(hid_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-core.c
linux-2.6.21-rc6-mm1.new/drivers/hid/hid-core.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-core.c 2007-04-10
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/hid-core.c 2007-04-11
09:12:02.000000000 +0800
@@ -28,9 +28,8 @@
#include <linux/vmalloc.h>
#include <linux/hid.h>
-#include <linux/hiddev.h>
#include <linux/hid-debug.h>
-#include <linux/hidraw.h>
+#include "hid-inter.h"
/*
* Version Information
@@ -39,7 +38,6 @@
#define DRIVER_VERSION "v2.6"
#define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
#define DRIVER_DESC "HID core driver"
-#define DRIVER_LICENSE "GPL"
/*
* Register a new report for a device.
@@ -634,7 +632,7 @@ struct hid_device *hid_parse_report(__u8
hid_parser_reserved
};
- if (!(device = kzalloc(sizeof(struct hid_device), GFP_KERNEL)))
+ if (!(device = hid_new_device(GFP_KERNEL)))
return NULL;
if (!(device->collection = kzalloc(sizeof(struct hid_collection) *
@@ -802,11 +800,17 @@ static __inline__ int search(__s32 *arra
static void hid_process_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value, int interrupt)
{
+ struct hid_hook *hook;
+
+ if (!hid->driver)
+ return;
+
+ hook = hid->driver->hook;
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 &&
hid->hiddev_hid_event)
- hid->hiddev_hid_event(hid, field, usage, value);
+ if (hook && hook->hid_event &&
+ !hook->hid_event(field, usage, value, interrupt))
+ return;
+ hidinput_hid_event(hid, field, usage, value);
}
/*
@@ -825,11 +829,13 @@ void hid_input_field(struct hid_device *
__s32 max = field->logical_maximum;
__s32 *value;
+ if (!hid->driver)
+ return;
+
if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
return;
for (n = 0; n < count; n++) {
-
value[n] = min < 0 ? snto32(extract(data, offset + n *
size, size), size) :
extract(data, offset + n *
size, size);
@@ -931,14 +937,110 @@ int hid_set_field(struct hid_field *fiel
}
EXPORT_SYMBOL_GPL(hid_set_field);
+static int hid_raw_event(struct hid_device *hid, int type, u8 *data,
+ int size, int interrupt)
+{
+ struct hid_hook *hook;
+ int ret, i;
+
+ if (!hid->driver)
+ return 0;
+
+ hook = hid->driver->hook;
+ if (hook && hook->raw_event) {
+ if (!hook->raw_event(hid, type, data, size, interrupt))
+ return 0;
+ }
+
+ ret = -ENODEV;
+ for (i=0; i<NR_STICKY; ++i) {
+ if (!hid_sticky_drivers[i] || !test_bit(i, &hid->sticky_driver))
+ continue;
+ if (hid_sticky_driver_exit(i)) {
+ clear_bit(i, &hid->sticky_driver);
+ continue;
+ }
+ hook = hid_sticky_drivers[i]->hook;
+ if (hook && hook->raw_event) {
+ ret = hook->raw_event(hid, type, data, size, interrupt);
+ if (!ret)
+ break;
+ }
+ }
+ return ret;
+}
+
+static int hid_report_pre_event(struct hid_device *hid,
+ struct hid_report *report, int
interrupt)
+{
+ struct hid_hook *hook;
+ int ret, i;
+
+ if (!hid->driver)
+ return 0;
+
+ hook = hid->driver->hook;
+ if (hook && hook->pre_report_event) {
+ if (!hook->pre_report_event(report, interrupt))
+ return 0;
+ }
+
+ ret = -ENODEV;
+ for (i=0; i<NR_STICKY; ++i) {
+ if (!hid_sticky_drivers[i] || !test_bit(i, &hid->sticky_driver))
+ continue;
+ if (hid_sticky_driver_exit(i)) {
+ clear_bit(i, &hid->sticky_driver);
+ continue;
+ }
+ hook = hid_sticky_drivers[i]->hook;
+ if (hook && hook->pre_report_event) {
+ ret = hook->pre_report_event(report, interrupt);
+ if (!ret)
+ break;
+ }
+ }
+ return ret;
+}
+
+static void hid_report_event(struct hid_device *hid,
+ struct hid_report *report, int
interrupt)
+{
+ struct hid_hook *hook;
+ int i;
+
+ if (!hid->driver)
+ return;
+
+ hook = hid->driver->hook;
+ if (hook && hook->report_event) {
+ hook->report_event(report, interrupt);
+ return;
+ }
+
+ hidinput_report_event(hid, report);
+
+ for (i=0; i<NR_STICKY; ++i) {
+ if (!hid_sticky_drivers[i] || !test_bit(i, &hid->sticky_driver))
+ continue;
+ if (hid_sticky_driver_exit(i)) {
+ clear_bit(i, &hid->sticky_driver);
+ continue;
+ }
+ hook = hid_sticky_drivers[i]->hook;
+ if (hook && hook->report_event)
+ hook->report_event(report, interrupt);
+ }
+}
+
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 (!hid || !hid->driver)
+ return -1;
if (!size) {
dbg("empty report");
@@ -976,34 +1078,14 @@ int hid_input_report(struct hid_device *
dbg("report %d is too short, (%d < %d)", report->id, size,
rsize);
memset(data + size, 0, rsize - size);
}
-
- if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event)
- hid->hiddev_report_event(hid, report);
- if (hid->claimed & HID_CLAIMED_HIDRAW)
- hidraw_report_event(hid, data, size);
-
+ hid_raw_event(hid, type, data, size, interrupt);
+ if (!hid_report_pre_event(hid, report, interrupt))
+ return 0;
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);
+ hid_report_event(hid, report, interrupt);
return 0;
}
EXPORT_SYMBOL_GPL(hid_input_report);
-static int __init hid_init(void)
-{
- return hidraw_init();
-}
-
-static void __exit hid_exit(void)
-{
- hidraw_exit();
-}
-
-module_init(hid_init);
-module_exit(hid_exit);
-
-MODULE_LICENSE(DRIVER_LICENSE);
-
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-input.c
linux-2.6.21-rc6-mm1.new/drivers/hid/hid-input.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-input.c 2007-04-10
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/hid-input.c 2007-04-15
21:35:15.000000000 +0800
@@ -33,11 +33,7 @@
#include <linux/hid.h>
#include <linux/hid-debug.h>
-
-static int hid_pb_fnmode = 1;
-module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
-MODULE_PARM_DESC(pb_fnmode,
- "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 =
fkeysfirst)");
+#include "hid-inter.h"
#define unk KEY_UNKNOWN
@@ -73,183 +69,13 @@ static const struct {
#define map_abs_clear(c) do { map_abs(c); clear_bit(c, bit); } while (0)
#define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0)
-#ifdef CONFIG_USB_HIDINPUT_POWERBOOK
-
-struct hidinput_key_translation {
- u16 from;
- u16 to;
- u8 flags;
-};
-
-#define POWERBOOK_FLAG_FKEY 0x01
-
-static struct hidinput_key_translation powerbook_fn_keys[] = {
- { KEY_BACKSPACE, KEY_DELETE },
- { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY },
- { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY },
- { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY },
- { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY },
- { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY },
- { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY },
- { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY },
- { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY },
- { KEY_UP, KEY_PAGEUP },
- { KEY_DOWN, KEY_PAGEDOWN },
- { KEY_LEFT, KEY_HOME },
- { KEY_RIGHT, KEY_END },
- { }
-};
-
-static struct hidinput_key_translation powerbook_numlock_keys[] = {
- { KEY_J, KEY_KP1 },
- { KEY_K, KEY_KP2 },
- { KEY_L, KEY_KP3 },
- { KEY_U, KEY_KP4 },
- { KEY_I, KEY_KP5 },
- { KEY_O, KEY_KP6 },
- { KEY_7, KEY_KP7 },
- { KEY_8, KEY_KP8 },
- { KEY_9, KEY_KP9 },
- { KEY_M, KEY_KP0 },
- { KEY_DOT, KEY_KPDOT },
- { KEY_SLASH, KEY_KPPLUS },
- { KEY_SEMICOLON, KEY_KPMINUS },
- { KEY_P, KEY_KPASTERISK },
- { KEY_MINUS, KEY_KPEQUAL },
- { KEY_0, KEY_KPSLASH },
- { KEY_F6, KEY_NUMLOCK },
- { KEY_KPENTER, KEY_KPENTER },
- { KEY_BACKSPACE, KEY_BACKSPACE },
- { }
-};
-
-static struct hidinput_key_translation powerbook_iso_keyboard[] = {
- { KEY_GRAVE, KEY_102ND },
- { KEY_102ND, KEY_GRAVE },
- { }
-};
-
-static struct hidinput_key_translation *find_translation(struct
hidinput_key_translation *table, u16 from)
-{
- struct hidinput_key_translation *trans;
-
- /* Look for the translation */
- for (trans = table; trans->from; trans++)
- if (trans->from == from)
- return trans;
-
- return NULL;
-}
-
-static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- struct hid_usage *usage, __s32 value)
-{
- struct hidinput_key_translation *trans;
-
- if (usage->code == KEY_FN) {
- if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON;
- else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
-
- input_event(input, usage->type, usage->code, value);
-
- return 1;
- }
-
- if (hid_pb_fnmode) {
- int do_translate;
-
- trans = find_translation(powerbook_fn_keys, usage->code);
- if (trans) {
- if (test_bit(usage->code, hid->pb_pressed_fn))
- do_translate = 1;
- else if (trans->flags & POWERBOOK_FLAG_FKEY)
- do_translate =
- (hid_pb_fnmode == 2 && (hid->quirks &
HID_QUIRK_POWERBOOK_FN_ON)) ||
- (hid_pb_fnmode == 1 && !(hid->quirks &
HID_QUIRK_POWERBOOK_FN_ON));
- else
- do_translate = (hid->quirks &
HID_QUIRK_POWERBOOK_FN_ON);
-
- if (do_translate) {
- if (value)
- set_bit(usage->code,
hid->pb_pressed_fn);
- else
- clear_bit(usage->code,
hid->pb_pressed_fn);
-
- input_event(input, usage->type, trans->to,
value);
-
- return 1;
- }
- }
-
- if (test_bit(usage->code, hid->pb_pressed_numlock) ||
- test_bit(LED_NUML, input->led)) {
- trans = find_translation(powerbook_numlock_keys,
usage->code);
-
- if (trans) {
- if (value)
- set_bit(usage->code,
hid->pb_pressed_numlock);
- else
- clear_bit(usage->code,
hid->pb_pressed_numlock);
-
- input_event(input, usage->type, trans->to,
value);
- }
-
- return 1;
- }
- }
-
- if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
- trans = find_translation(powerbook_iso_keyboard, usage->code);
- if (trans) {
- input_event(input, usage->type, trans->to, value);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void hidinput_pb_setup(struct input_dev *input)
-{
- struct hidinput_key_translation *trans;
-
- set_bit(KEY_NUMLOCK, input->keybit);
-
- /* Enable all needed keys */
- for (trans = powerbook_fn_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_numlock_keys; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
- for (trans = powerbook_iso_keyboard; trans->from; trans++)
- set_bit(trans->to, input->keybit);
-
-}
-#else
-static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev
*input,
- struct hid_usage *usage, __s32 value)
-{
- return 0;
-}
-
-static inline void hidinput_pb_setup(struct input_dev *input)
-{
-}
-#endif
-
-static void hidinput_configure_usage(struct hid_input *hidinput, struct
hid_field *field,
+static void hidinput_configure_usage(struct input_dev *input, struct hid_field
*field,
struct hid_usage *usage)
{
- struct input_dev *input = hidinput->input;
struct hid_device *device = input->private;
int max = 0, code;
unsigned long *bit = NULL;
- field->hidinput = hidinput;
-
#ifdef CONFIG_HID_DEBUG
printk(KERN_DEBUG "Mapping: ");
hid_resolv_usage(usage->hid);
@@ -606,17 +432,7 @@ static void hidinput_configure_usage(str
goto ignore;
case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB
keyboards */
-
set_bit(EV_REP, input->evbit);
- switch(usage->hid & HID_USAGE) {
- case 0x003:
- /* The fn key on Apple PowerBooks */
- map_key_clear(KEY_FN);
- hidinput_pb_setup(input);
- break;
-
- default: goto ignore;
- }
break;
case HID_UP_LOGIVENDOR: /* Reported on Logitech Ultra X Media
Remote */
@@ -746,8 +562,87 @@ ignore:
return;
}
+static void inline hid_driver_hook_usage(struct input_dev *input,
+ struct hid_usage *usage,
+ struct usage_block *usage_block)
+{
+ unsigned long *bits;
+ struct hid_device *hid;
+
+ hid = input->private;
+ switch (usage_block->event) {
+ case EV_KEY:
+ bits = input->keybit;
+ break;
+ case EV_REL:
+ bits = input->relbit;
+ break;
+ case EV_ABS:
+ bits = input->relbit;
+ break;
+ case EV_MSC:
+ bits = input->absbit;
+ break;
+ case EV_SW:
+ bits = input->swbit;
+ break;
+ case EV_LED:
+ bits = input->ledbit;
+ break;
+ case EV_SND:
+ bits = input->sndbit;
+ break;
+ case EV_FF:
+ bits = input->ffbit;
+ break;
+ case EV_FF_STATUS:
+ bits = NULL;
+ break;
+ default:
+ return;
+ }
+
+ usage->code = usage_block->code;
+ usage->type = usage_block->event;
+ set_bit(usage_block->event, input->evbit);
+ if (bits)
+ set_bit(usage_block->code, bits);
+}
+
+static void hid_driver_hook_field(struct hid_driver *driver,
+ struct hid_field *field,
+ struct hid_usage *hid_usage)
+{
+ struct hid_hook *hook = driver->hook;
+ struct input_dev *input = field->hidinput->input;
+ struct usage_block *usage_block;
+ struct usage_page_block *page_block;
+ int page;
+ int usage;
+
+ if (!hook)
+ return;
+
+ page = (hid_usage->hid & HID_USAGE_PAGE);
+ usage = (hid_usage->hid & HID_USAGE);
+ page_block = hook->usage_page_table;
+ for (;page_block && page_block->usage_blockes;page_block++) {
+ if (page_block->page != page)
+ continue;
+ usage_block = page_block->usage_blockes;
+ for (; usage_block && usage_block->usage; usage_block++) {
+ if (usage_block->usage != usage)
+ continue;
+ hid_driver_hook_usage(input, hid_usage, usage_block);
+ }
+ }
+ if (hook->setup_usage)
+ hook->setup_usage(field, hid_usage);
+}
+
void hidinput_hid_event(struct hid_device *hid, struct hid_field *field,
struct hid_usage *usage, __s32 value)
{
+ struct hid_input *hidinput;
struct input_dev *input;
int *quirks = &hid->quirks;
@@ -759,6 +654,8 @@ void hidinput_hid_event(struct hid_devic
if (!usage->type)
return;
+ hidinput = field->hidinput;
+
if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid ==
0x00090005))
|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) &&
(usage->hid == 0x00090007))) {
if (value) hid->quirks |= HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
@@ -776,9 +673,6 @@ void hidinput_hid_event(struct hid_devic
return;
}
- if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) &&
hidinput_pb_event(hid, input, usage, value))
- return;
-
if (usage->hat_min < usage->hat_max || usage->hat_dir) {
int hat_dir = usage->hat_dir;
if (!hat_dir)
@@ -828,10 +722,14 @@ void hidinput_hid_event(struct hid_devic
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
input_event(input, usage->type, usage->code, 0);
}
+EXPORT_SYMBOL(hidinput_hid_event);
void hidinput_report_event(struct hid_device *hid, struct hid_report *report)
{
struct hid_input *hidinput;
+
+ if (!hid->driver)
+ return;
list_for_each_entry(hidinput, &hid->inputs, list)
input_sync(hidinput->input);
@@ -855,16 +753,81 @@ int hidinput_find_field(struct hid_devic
}
EXPORT_SYMBOL_GPL(hidinput_find_field);
+static int hidinput_input_event(struct input_dev *dev, unsigned int type,
+ unsigned int code, int value)
+{
+ struct hid_device *hid = dev->private;
+ struct hid_transport *tl;
+ int ret;
+
+ if (!hid || !hid->driver)
+ return 0;
+ if (hid->driver->event)
+ return hid->driver->event(dev, type, code, value);
+ ret = 0;
+ tl = hid_transports[hid->bus];
+ if (tl->event)
+ ret = tl->event(dev, type, code, value);
+ return ret;
+}
+
+int hid_open(struct hid_device *hid)
+{
+ struct hid_transport *tl;
+ int ret;
+
+ if (hid->driver->open)
+ return hid->driver->open(hid);
+ ret = 0;
+ tl = hid_transports[hid->bus];
+ if (tl->open)
+ ret = tl->open(hid);
+ return ret;
+}
+EXPORT_SYMBOL(hid_open);
+
static int hidinput_open(struct input_dev *dev)
{
struct hid_device *hid = dev->private;
- return hid->hid_open(hid);
+
+ if (!hid || !hid->driver)
+ return 0;
+ return hid_open(hid);
}
+void hid_close(struct hid_device *hid)
+{
+ struct hid_transport *tl;
+
+ if (hid->driver->close) {
+ hid->driver->close(hid);
+ return;
+ }
+ tl = hid_transports[hid->bus];
+ if (tl->close)
+ tl->close(hid);
+}
+EXPORT_SYMBOL(hid_close);
+
static void hidinput_close(struct input_dev *dev)
{
struct hid_device *hid = dev->private;
- hid->hid_close(hid);
+
+ if (!hid || !hid->driver)
+ return;
+ hid_close(hid);
+ return;
+}
+
+static inline void hidinput_register_inputdev(struct hid_driver *driver,
+ struct input_dev *input)
+{
+ struct hid_hook *hook = driver->hook;
+
+ if (hook && hook->register_inputdev)
+ hook->register_inputdev(input);
+ else
+ input_register_device(input);
}
/*
@@ -875,13 +838,18 @@ static void hidinput_close(struct input_
int hidinput_connect(struct hid_device *hid)
{
+ struct hid_driver *drv;
struct hid_report *report;
struct hid_input *hidinput = NULL;
struct input_dev *input_dev;
int i, j, k;
int max_report_type = HID_OUTPUT_REPORT;
- INIT_LIST_HEAD(&hid->inputs);
+ printk("connect %p\n", hid);
+
+ drv = hid->driver;
+ if (!drv)
+ return -1;
for (i = 0; i < hid->maxcollection; i++)
if (hid->collection[i].type == HID_COLLECTION_APPLICATION ||
@@ -912,7 +880,7 @@ int hidinput_connect(struct hid_device *
}
input_dev->private = hid;
- input_dev->event = hid->hidinput_input_event;
+ input_dev->event = hidinput_input_event;
input_dev->open = hidinput_open;
input_dev->close = hidinput_close;
@@ -928,10 +896,15 @@ int hidinput_connect(struct hid_device *
list_add_tail(&hidinput->list, &hid->inputs);
}
- for (i = 0; i < report->maxfield; i++)
+ for (i = 0; i < report->maxfield; i++) {
+ report->field[i]->hidinput = hidinput;
for (j = 0; j < report->field[i]->maxusage; j++)
- hidinput_configure_usage(hidinput,
report->field[i],
+
hidinput_configure_usage(hidinput->input, report->field[i],
report->field[i]->usage + j);
+ hid_driver_hook_field(drv,
+
report->field[i],
+ report->field[i]->usage
+ j);
+ }
if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
/* This will leave hidinput NULL, so that it
@@ -940,13 +913,13 @@ int hidinput_connect(struct hid_device *
* UGCI) cram a lot of unrelated inputs into the
* same interface. */
hidinput->report = report;
- input_register_device(hidinput->input);
+ hidinput_register_inputdev(drv,
hidinput->input);
hidinput = NULL;
}
}
if (hidinput)
- input_register_device(hidinput->input);
+ hidinput_register_inputdev(drv, hidinput->input);
return 0;
}
@@ -956,6 +929,10 @@ void hidinput_disconnect(struct hid_devi
{
struct hid_input *hidinput, *next;
+ BUG_ON(!hid->driver);
+
+ printk("disconnect %p\n", hid);
+
list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
list_del(&hidinput->list);
input_unregister_device(hidinput->input);
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-inter.h
linux-2.6.21-rc6-mm1.new/drivers/hid/hid-inter.h
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/hid-inter.h 1970-01-01
08:00:00.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/hid-inter.h 2007-04-11
09:24:54.000000000 +0800
@@ -0,0 +1,26 @@
+/*
+ * HID abstract layer for Linux driver model
+ *
+ * Copyright (c) 2007 Li Yu
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#ifndef HID_INTERNAL_H__
+#define HID_INTERNAL_H__
+
+#include <linux/input.h> /* for BUS_MAX */
+
+#define NR_STICKY 32
+
+extern struct hid_transport* hid_transports[BUS_MAX];
+extern struct hid_driver* hid_sticky_drivers[NR_STICKY];
+extern int hid_sticky_driver_exit(int i);
+
+#endif
+
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/hidraw.c
linux-2.6.21-rc6-mm1.new/drivers/hid/hidraw.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/hidraw.c 2007-04-10
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/hidraw.c 2007-04-15
21:30:58.000000000 +0800
@@ -32,6 +32,7 @@
#include <linux/mutex.h>
#include <linux/hidraw.h>
+#include "hid-inter.h"
static int hidraw_major;
static struct cdev hidraw_cdev;
@@ -105,12 +106,17 @@ static ssize_t hidraw_write(struct file
{
unsigned int minor = iminor(file->f_path.dentry->d_inode);
struct hid_device *dev = hidraw_table[minor]->hid;
+ struct hid_driver *drv = dev->driver;
+ struct hid_hook *hook = drv->hook;
__u8 *buf;
int ret = 0;
- if (!dev->hid_output_raw_report)
+ if (hid_transports[dev->bus]->raw_report)
+ goto really_start;
+ if (!hook || !hook->raw_report)
return -ENODEV;
+really_start:
if (count > HID_MIN_BUFFER_SIZE) {
printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
current->pid);
@@ -132,7 +138,11 @@ static ssize_t hidraw_write(struct file
goto out;
}
- ret = dev->hid_output_raw_report(dev, buf, count);
+ if (hook && hook->raw_report)
+ ret = hook->raw_report(dev, buf, count);
+ else
+ ret = hid_transports[dev->bus]->raw_report(dev, buf, count);
+
out:
kfree(buf);
return ret;
@@ -178,7 +188,7 @@ static int hidraw_open(struct inode *ino
dev = hidraw_table[minor];
if (!dev->open++)
- dev->hid->hid_open(dev->hid);
+ err = hid_open(dev->hid);
out_unlock:
spin_unlock(&minors_lock);
@@ -203,7 +213,7 @@ static int hidraw_release(struct inode *
dev = hidraw_table[minor];
if (!dev->open--) {
if (list->hidraw->exist)
- dev->hid->hid_close(dev->hid);
+ dev->hid->driver->close(dev->hid);
else
kfree(list->hidraw);
}
@@ -264,11 +274,15 @@ static const struct file_operations hidr
.ioctl = hidraw_ioctl,
};
-void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
+static int hidraw_raw_event(struct hid_device *hid, int type, u8 *data,
+ int len, int interrupt)
{
struct hidraw *dev = hid->hidraw;
struct hidraw_list *list;
+ if (!dev)
+ return -1;
+
list_for_each_entry(list, &dev->list, node) {
list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC);
list->buffer[list->head].len = len;
@@ -277,10 +291,10 @@ void hidraw_report_event(struct hid_devi
}
wake_up_interruptible(&dev->wait);
+ return 0;
}
-EXPORT_SYMBOL_GPL(hidraw_report_event);
-int hidraw_connect(struct hid_device *hid)
+static int hidraw_connect(struct hid_device *hid)
{
int minor, result = -EINVAL;
struct hidraw *dev;
@@ -332,12 +346,14 @@ out:
return result;
}
-EXPORT_SYMBOL_GPL(hidraw_connect);
-void hidraw_disconnect(struct hid_device *hid)
+static void hidraw_disconnect(struct hid_device *hid)
{
struct hidraw *hidraw = hid->hidraw;
+ if (!hidraw)
+ return;
+
hidraw->exist = 0;
spin_lock(&minors_lock);
@@ -347,19 +363,36 @@ void hidraw_disconnect(struct hid_device
device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
if (hidraw->open) {
- hid->hid_close(hid);
+ hid_close(hid);
wake_up_interruptible(&hidraw->wait);
} else {
kfree(hidraw);
}
}
-EXPORT_SYMBOL_GPL(hidraw_disconnect);
+
+static struct hid_hook hidraw_hook = {
+ .raw_event = hidraw_raw_event,
+};
+
+static struct hid_driver hid_hidraw_driver = {
+ .name = "hidraw",
+ .version = "0.1.0",
+ .module = THIS_MODULE,
+ .probe = hidraw_connect,
+ .remove = hidraw_disconnect,
+ .hook = &hidraw_hook,
+};
int __init hidraw_init(void)
{
int result;
dev_t dev_id;
+ set_hid_driver_sticky(&hid_hidraw_driver);
+ result = hid_register_driver(&hid_hidraw_driver);
+ if (result)
+ goto out;
+
result = alloc_chrdev_region(&dev_id, HIDRAW_FIRST_MINOR,
HIDRAW_MAX_DEVICES, "hidraw");
@@ -388,8 +421,13 @@ void __exit hidraw_exit(void)
{
dev_t dev_id = MKDEV(hidraw_major, 0);
+ hid_unregister_driver(&hid_hidraw_driver);
cdev_del(&hidraw_cdev);
class_destroy(hidraw_class);
unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
}
+
+module_init(hidraw_init);
+module_exit(hidraw_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/Kconfig
linux-2.6.21-rc6-mm1.new/drivers/hid/Kconfig
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/Kconfig 2007-04-10
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/Kconfig 2007-04-16
13:44:21.000000000 +0800
@@ -37,7 +37,7 @@ config HID_DEBUG
If unsure, say N
config HIDRAW
- bool "/dev/hidraw raw HID device support"
+ tristate "/dev/hidraw raw HID device support"
depends on HID
---help---
Say Y here if you want to support HID devices (from the USB
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/Makefile
linux-2.6.21-rc6-mm1.new/drivers/hid/Makefile
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/Makefile 2007-04-10
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/Makefile 2007-04-17
09:23:27.000000000 +0800
@@ -1,7 +1,7 @@
#
# Makefile for the HID driver
#
-hid-objs := hid-core.o hid-input.o
+hid-objs := hid-core.o hid-input.o hid-al.o
obj-$(CONFIG_HID) += hid.o
@@ -9,6 +9,13 @@ hid-$(CONFIG_HID_DEBUG) += hid-debug.o
hid-$(CONFIG_HIDRAW) += hidraw.o
obj-$(CONFIG_USB_HID) += usbhid/
+obj-$(CONFIG_HID_PID) += usbhid/
+obj-$(CONFIG_THRUSTMASTER_FF) += usbhid/
+obj-$(CONFIG_ZEROPLUS_FF) += usbhid/
+obj-$(CONFIG_POWERBOOK) += usbhid/
+obj-$(CONFIG_LOGITECH_FF) += usbhid/
+obj-$(CONFIG_PANTHERLORD_FF) += usbhid/
+obj-$(CONFIG_USB_HIDDEV) += usbhid/
obj-$(CONFIG_USB_MOUSE) += usbhid/
obj-$(CONFIG_USB_KBD) += usbhid/
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel