diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hiddev.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hiddev.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hiddev.c       2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hiddev.c        2007-04-15 
21:29:44.000000000 +0800
@@ -36,6 +36,11 @@
 #include <linux/hiddev.h>
 #include "usbhid.h"
 
+#define DRIVER_VERSION "v0.9.0"
+#define DRIVER_AUTHOR "Paul Stewart, Vojtech Pavlik"
+#define DRIVER_DESC "USB HIDDEV driver"
+#define DRIVER_LICENSE "GPL"
+
 #ifdef CONFIG_USB_DYNAMIC_MINORS
 #define HIDDEV_MINOR_BASE      0
 #define HIDDEV_MINORS          256
@@ -48,9 +53,11 @@
 struct hiddev {
        int exist;
        int open;
+       int minor;
        wait_queue_head_t wait;
        struct hid_device *hid;
        struct list_head list;
+       void *private;
 };
 
 struct hiddev_list {
@@ -159,7 +166,7 @@ hiddev_lookup_usage(struct hid_device *h
 static void hiddev_send_event(struct hid_device *hid,
                              struct hiddev_usage_ref *uref)
 {
-       struct hiddev *hiddev = hid->hiddev;
+       struct hiddev *hiddev = hid->private;
        struct hiddev_list *list;
 
        list_for_each_entry(list, &hiddev->list, node) {
@@ -179,9 +186,10 @@ static void hiddev_send_event(struct hid
  * This is where hid.c calls into hiddev to pass an event that occurred over
  * the interrupt pipe
  */
-void hiddev_hid_event(struct hid_device *hid, struct hid_field *field,
-                     struct hid_usage *usage, __s32 value)
+static int hiddev_hid_event(struct hid_field *field, struct hid_usage *usage,
+                                                       __s32 value, int 
interrupt)
 {
+       struct hid_device *hid = field->report->device;
        unsigned type = field->report_type;
        struct hiddev_usage_ref uref;
 
@@ -196,6 +204,8 @@ void hiddev_hid_event(struct hid_device 
        uref.value = value;
 
        hiddev_send_event(hid, &uref);
+       /* We always let HID core continue to dispatch this event here. */
+       return 1;
 }
 EXPORT_SYMBOL_GPL(hiddev_hid_event);
 
@@ -393,7 +403,7 @@ static int hiddev_ioctl(struct inode *in
        struct hiddev_devinfo dinfo;
        struct hid_report *report;
        struct hid_field *field;
-       struct usbhid_device *usbhid = hid->driver_data;
+       struct usbhid_device *usbhid = hid->tl_data;
        void __user *user_arg = (void __user *)arg;
        int i;
 
@@ -742,15 +752,15 @@ static struct usb_class_driver hiddev_cl
        .minor_base =   HIDDEV_MINOR_BASE,
 };
 
-/*
- * This is where hid.c calls us to connect a hid device to the hiddev driver
- */
-int hiddev_connect(struct hid_device *hid)
+static int hiddev_connect(struct hid_device *hid)
 {
        struct hiddev *hiddev;
-       struct usbhid_device *usbhid = hid->driver_data;
+       struct usbhid_device *usbhid = hid->tl_data;
        int i;
        int retval;
+       
+       if (hid->bus != BUS_USB)
+               return -1;
 
        for (i = 0; i < hid->maxcollection; i++)
                if (hid->collection[i].type ==
@@ -776,8 +786,8 @@ int hiddev_connect(struct hid_device *hi
        hiddev->hid = hid;
        hiddev->exist = 1;
 
-       hid->minor = usbhid->intf->minor;
-       hid->hiddev = hiddev;
+       hiddev->minor = usbhid->intf->minor;
+       hid->private = hiddev;
 
        hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
 
@@ -788,15 +798,17 @@ int hiddev_connect(struct hid_device *hi
  * This is where hid.c calls us to disconnect a hiddev device from the
  * corresponding hid device (usually because the usb device has disconnected)
  */
-static struct usb_class_driver hiddev_class;
-void hiddev_disconnect(struct hid_device *hid)
+static void hiddev_disconnect(struct hid_device *hid)
 {
-       struct hiddev *hiddev = hid->hiddev;
-       struct usbhid_device *usbhid = hid->driver_data;
+       struct hiddev *hiddev = hid->private;
+       struct usbhid_device *usbhid = hid->tl_data;
+
+       if (hid->bus != BUS_USB)
+               return;
 
        hiddev->exist = 0;
 
-       hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
+       hiddev_table[hiddev->minor - HIDDEV_MINOR_BASE] = NULL;
        usb_deregister_dev(usbhid->intf, &hiddev_class);
 
        if (hiddev->open) {
@@ -807,41 +819,34 @@ void hiddev_disconnect(struct hid_device
        }
 }
 
-/* Currently this driver is a USB driver.  It's not a conventional one in
- * the sense that it doesn't probe at the USB level.  Instead it waits to
- * be connected by HID through the hiddev_connect / hiddev_disconnect
- * routines.  The reason to register as a USB device is to gain part of the
- * minor number space from the USB major.
- *
- * In theory, should the HID code be generalized to more than one physical
- * medium (say, IEEE 1384), this driver will probably need to register its
- * own major number, and in doing so, no longer need to register with USB.
- * At that point the probe routine and hiddev_driver struct below will no
- * longer be useful.
- */
-
-
-/* We never attach in this manner, and rely on HID to connect us.  This
- * is why there is no disconnect routine defined in the usb_driver either.
- */
-static int hiddev_usbd_probe(struct usb_interface *intf,
-                            const struct usb_device_id *hiddev_info)
-{
-       return -ENODEV;
-}
-
+static struct hid_hook hiddev_hook = {
+       .hid_event = hiddev_hid_event,
+};
 
-static /* const */ struct usb_driver hiddev_driver = {
-       .name =         "hiddev",
-       .probe =        hiddev_usbd_probe,
+static struct hid_driver hid_hiddev_driver = {
+       .name = "hiddev",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .probe = hiddev_connect,
+       .remove = hiddev_disconnect,
+       .hook = &hiddev_hook,
 };
 
 int __init hiddev_init(void)
 {
-       return usb_register(&hiddev_driver);
+       set_hid_driver_sticky(&hid_hiddev_driver); 
+       return hid_register_driver(&hid_hiddev_driver);
 }
 
-void hiddev_exit(void)
+void __exit hiddev_exit(void)
 {
-       usb_deregister(&hiddev_driver);
+       hid_unregister_driver(&hid_hiddev_driver);
 }
+
+module_init(hiddev_init);
+module_exit(hiddev_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-ff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-ff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-ff.c       2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-ff.c        1970-01-01 
08:00:00.000000000 +0800
@@ -1,90 +0,0 @@
-/*
- * $Id: hid-ff.c,v 1.2 2002/04/18 22:02:47 jdeneux Exp $
- *
- *  Force feedback support for hid devices.
- *  Not all hid devices use the same protocol. For example, some use PID,
- *  other use their own proprietary procotol.
- *
- *  Copyright (c) 2002-2004 Johann Deneux
- */
-
-/*
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Should you need to contact me, the author, you can do so by
- * e-mail - mail your message to <[EMAIL PROTECTED]>
- */
-
-#include <linux/input.h>
-
-#undef DEBUG
-#include <linux/usb.h>
-
-#include <linux/hid.h>
-#include "usbhid.h"
-
-/*
- * This table contains pointers to initializers. To add support for new
- * devices, you need to add the USB vendor and product ids here.
- */
-struct hid_ff_initializer {
-       u16 idVendor;
-       u16 idProduct;
-       int (*init)(struct hid_device*);
-};
-
-/*
- * We try pidff when no other driver is found because PID is the
- * standards compliant way of implementing force feedback in HID.
- * pidff_init() will quickly abort if the device doesn't appear to
- * be a PID device
- */
-static struct hid_ff_initializer inits[] = {
-#ifdef CONFIG_LOGITECH_FF
-       { 0x46d, 0xc211, hid_lgff_init }, /* Logitech Cordless rumble pad */
-       { 0x46d, 0xc219, hid_lgff_init }, /* Logitech Cordless rumble pad 2 */
-       { 0x46d, 0xc283, hid_lgff_init }, /* Logitech Wingman Force 3d */
-       { 0x46d, 0xc294, hid_lgff_init }, /* Logitech Formula Force EX */
-       { 0x46d, 0xc295, hid_lgff_init }, /* Logitech MOMO force wheel */
-       { 0x46d, 0xca03, hid_lgff_init }, /* Logitech MOMO force wheel */
-#endif
-#ifdef CONFIG_PANTHERLORD_FF
-       { 0x810, 0x0001, hid_plff_init },
-#endif
-#ifdef CONFIG_THRUSTMASTER_FF
-       { 0x44f, 0xb300, hid_tmff_init },
-       { 0x44f, 0xb304, hid_tmff_init },
-#endif
-#ifdef CONFIG_ZEROPLUS_FF
-       { 0xc12, 0x0005, hid_zpff_init },
-       { 0xc12, 0x0030, hid_zpff_init },
-#endif
-       { 0,     0,      hid_pidff_init}  /* Matches anything */
-};
-
-int hid_ff_init(struct hid_device* hid)
-{
-       struct hid_ff_initializer *init;
-       int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
-       int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);
-
-       for (init = inits; init->idVendor; init++)
-               if (init->idVendor == vendor && init->idProduct == product)
-                       break;
-
-       return init->init(hid);
-}
-EXPORT_SYMBOL_GPL(hid_ff_init);
-
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-lgff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-lgff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-lgff.c     2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-lgff.c      2007-04-15 
21:29:54.000000000 +0800
@@ -29,9 +29,10 @@
 
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <linux/hid.h>
 #include "usbhid.h"
 
+#define DRIVER_VERSION "0.1.0"
+
 struct dev_type {
        u16 idVendor;
        u16 idProduct;
@@ -99,7 +100,7 @@ static int hid_lgff_play(struct input_de
        return 0;
 }
 
-int hid_lgff_init(struct hid_device* hid)
+static int hid_lgff_init_device(struct hid_device* hid)
 {
        struct hid_input *hidinput = list_entry(hid->inputs.next, struct 
hid_input, list);
        struct list_head *report_list = 
&hid->report_enum[HID_OUTPUT_REPORT].report_list;
@@ -148,3 +149,53 @@ int hid_lgff_init(struct hid_device* hid
 
        return 0;
 }
+
+static struct usb_device_id hid_lgff_ids[] = {
+       { USB_DEVICE(0x46d, 0xc211) }, /* Logitech Cordless rumble pad */
+       { USB_DEVICE(0x46d, 0xc219) }, /* Logitech Cordless rumble pad 2 */
+       { USB_DEVICE(0x46d, 0xc283) }, /* Logitech Wingman Force 3d */
+       { USB_DEVICE(0x46d, 0xc294) }, /* Logitech Formula Force EX */
+       { USB_DEVICE(0x46d, 0xc295) }, /* Logitech MOMO force wheel */
+       { USB_DEVICE(0x46d, 0xca03) }, /* Logitech MOMO force wheel */
+       {}
+};
+
+MODULE_DEVICE_TABLE (usb, hid_lgff_ids);
+
+static int hid_lgff_match(struct hid_driver *driver, struct hid_device *device)
+{
+       struct usbhid_device *usbhid;
+
+       usbhid = device->tl_data;
+       return (int)usb_match_id(usbhid->intf, hid_lgff_ids);
+}
+
+static int hid_lgff_probe(struct hid_device *device)
+{
+       if (hidinput_connect(device))
+               return -ENODEV;
+       return hid_lgff_init_device(device);
+}
+
+static struct hid_driver hid_lgff_driver = {
+       .name = "hid-lgff",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .match = hid_lgff_match,
+       .probe = hid_lgff_probe,
+};
+
+static int __init hid_lgff_init(void)
+{
+       return hid_register_driver(&hid_lgff_driver);
+}
+
+static void __exit hid_lgff_exit(void)
+{
+       hid_unregister_driver(&hid_lgff_driver);
+}
+
+module_init(hid_lgff_init);
+module_exit(hid_lgff_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-pb.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-pb.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-pb.c       1970-01-01 
08:00:00.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-pb.c        2007-04-15 
21:30:02.000000000 +0800
@@ -0,0 +1,334 @@
+/*
+ * $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
+ *
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2006-2007 Jiri Kosina
+ *
+ *  iBook/PowerBook special keys support.
+ */
+
+/*
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <[EMAIL PROTECTED]>, or by paper mail:
+ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/usb.h>
+#include <linux/input.h>
+
+#include "usbhid.h"
+
+#define DRIVER_VERSION "0.1.0"
+
+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)");
+
+#define USB_VENDOR_ID_APPLE            0x05ac
+#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE        0x0304
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI      0x020e
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO       0x020f
+#define USB_DEVICE_ID_APPLE_GEYSER_ANSI        0x0214
+#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
+#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
+#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI       0x0217
+#define USB_DEVICE_ID_APPLE_GEYSER3_ISO        0x0218
+#define USB_DEVICE_ID_APPLE_GEYSER3_JIS        0x0219
+#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI       0x021a
+#define USB_DEVICE_ID_APPLE_GEYSER4_ISO        0x021b
+#define USB_DEVICE_ID_APPLE_GEYSER4_JIS        0x021c
+#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY   0x030a
+#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY    0x030b
+#define USB_DEVICE_ID_APPLE_IR         0x8240
+
+#define USB_VENDOR_ID_CHERRY           0x046a
+#define USB_DEVICE_ID_CHERRY_CYMOTION  0x0023
+
+struct hids_pb_data {
+       unsigned long pressed_fn[NBITS(KEY_MAX)];
+       unsigned long pressed_numlock[NBITS(KEY_MAX)];
+};
+
+static const struct pb_feature {
+       __u16 idProduct;
+       unsigned quirks;
+} pb_feature_list[] = {
+       { USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_FOUNTAIN_ISO,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER_ANSI,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER_ISO,  HID_QUIRK_IGNORE_MOUSE | 
HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_DEVICE_ID_APPLE_GEYSER_JIS,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER3_ANSI,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER3_ISO,  HID_QUIRK_IGNORE_MOUSE | 
HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_DEVICE_ID_APPLE_GEYSER3_JIS,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER4_ANSI,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER4_ISO,  HID_QUIRK_IGNORE_MOUSE | 
HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+       { USB_DEVICE_ID_APPLE_GEYSER4_JIS,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY,  HID_QUIRK_IGNORE_MOUSE },
+       { USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY,  HID_QUIRK_IGNORE_MOUSE },
+       { 0, 0 }
+};
+
+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 hids_pb_hid_event(struct hid_field *field, struct hid_usage *usage,
+                                                       __s32 value, int 
interrupt)
+{
+       struct hidinput_key_translation *trans;
+       struct hid_input *hidinput = field->hidinput;
+       struct hid_device *hid = field->report->device;
+       struct hids_pb_data *pb_data = hid->driver->private;
+       
+       if (!pb_data)
+               return -1;
+       
+       if (usage->code == KEY_FN) {
+               if (value) hid->quirks |=  HID_QUIRK_POWERBOOK_FN_ON;
+               else       hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
+
+               input_event(hidinput->input, usage->type, usage->code, value);
+               return 0;
+       }
+
+       if (hid_pb_fnmode) {
+               int do_translate;
+
+               trans = find_translation(powerbook_fn_keys, usage->code);
+               if (trans) {
+                       if (test_bit(usage->code, pb_data->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, 
pb_data->pressed_fn);
+                               else
+                                       clear_bit(usage->code, 
pb_data->pressed_fn);
+
+                               input_event(hidinput->input, usage->type,
+                                                               trans->to, 
value);
+
+                               return 0;
+                       }
+               }
+
+               if (test_bit(usage->code, pb_data->pressed_numlock) ||
+                               test_bit(LED_NUML, hidinput->input->led)) {
+                       trans = find_translation(powerbook_numlock_keys, 
usage->code);
+
+                       if (trans) {
+                               if (value)
+                                       set_bit(usage->code, 
pb_data->pressed_numlock);
+                               else
+                                       clear_bit(usage->code, 
pb_data->pressed_numlock);
+
+                               input_event(hidinput->input, usage->type, 
trans->to, value);
+                       }
+                       return 0;
+               }
+       }
+
+       if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
+               trans = find_translation(powerbook_iso_keyboard, usage->code);
+               if (trans) {
+                       input_event(hidinput->input, usage->type, trans->to, 
value);
+                       return 0;
+               }
+       }
+       
+       hidinput_hid_event(hid, field, usage, value);
+       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);
+}
+
+static struct usb_device_id hids_pb_ids[] = {
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS) },    
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO) },   
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS) },
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) 
},
+       { USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) 
},
+       {}
+};
+MODULE_DEVICE_TABLE (usb, hids_pb_ids);
+
+static int hid_pb_match(struct hid_driver *driver, struct hid_device *device)
+{
+       struct usbhid_device *usbhid;
+
+       if (!driver || !device)
+               return 0;
+       usbhid = device->tl_data;
+       return !!usb_match_id(usbhid->intf, hids_pb_ids);
+}
+
+static int hid_pb_probe(struct hid_device *dev)
+{
+       int i;
+       struct hid_driver *drv = dev->driver;
+
+       for (i=0; pb_feature_list[i].quirks; ++i) {
+               if (pb_feature_list[i].idProduct == dev->product)
+                       dev->quirks = pb_feature_list[i].quirks;
+       }
+       drv->private = kzalloc(sizeof(struct hids_pb_data), GFP_KERNEL);
+       if (!drv->private)
+               return 0;
+       return hidinput_connect(dev);
+}
+
+static void hids_pb_setup_usage(struct hid_field *field, struct hid_usage 
*usage)
+{
+       unsigned long *bit;
+       struct input_dev* input = field->hidinput->input;
+       
+       if (0x003 != (usage->hid & HID_USAGE))
+               return;
+       usage->code = KEY_FN;
+       usage->type = EV_KEY;
+       bit = input->keybit;
+       clear_bit(KEY_FN, input->keybit);
+       hidinput_pb_setup(input);
+}
+
+static struct hid_hook hid_pb_hook = {
+       .hid_event = hids_pb_hid_event,
+       .setup_usage = hids_pb_setup_usage,
+};
+
+static struct hid_driver hids_pb_driver = {
+       .name = "hid-pb",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .match = hid_pb_match,
+       .probe = hid_pb_probe,
+       .hook = &hid_pb_hook,
+};
+
+static int __init hids_pb_init(void)
+{
+       return hid_register_driver(&hids_pb_driver);
+}
+
+static void __exit hids_pb_exit(void)
+{
+       hid_unregister_driver(&hids_pb_driver);
+}
+
+module_init(hids_pb_init);
+module_exit(hids_pb_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-pidff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-pidff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-pidff.c    2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-pidff.c     2007-04-15 
21:30:14.000000000 +0800
@@ -27,10 +27,10 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 
-#include <linux/hid.h>
-
 #include "usbhid.h"
 
+#define DRIVER_VERSION "0.1.0"
+
 #define        PID_EFFECTS_MAX         64
 
 /* Report usage table used to put reports into an array */
@@ -1236,7 +1236,7 @@ static int pidff_check_autocenter(struct
 /*
  * Check if the device is PID and initialize it
  */
-int hid_pidff_init(struct hid_device *hid)
+int hid_pidff_init_device(struct hid_device *hid)
 {
        struct pidff_device *pidff;
        struct hid_input *hidinput = list_entry(hid->inputs.next,
@@ -1329,3 +1329,33 @@ int hid_pidff_init(struct hid_device *hi
        kfree(pidff);
        return error;
 }
+
+static int hid_pidff_probe(struct hid_device *device)
+{
+       if (hidinput_connect(device))
+               return -ENODEV;
+       return hid_pidff_init_device(device);
+}
+
+static struct hid_driver hid_pidff_driver = {
+       .name = "hid-pidff",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .probe = hid_pidff_probe,
+};
+
+static int __init hid_pidff_init(void)
+{
+       set_hid_driver_sticky(&hid_pidff_driver);
+       return hid_register_driver(&hid_pidff_driver);
+}
+
+static void __exit hid_pidff_exit(void)
+{
+       hid_unregister_driver(&hid_pidff_driver);
+}
+
+module_init(hid_pidff_init);
+module_exit(hid_pidff_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-plff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-plff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-plff.c     2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-plff.c      2007-04-15 
21:30:26.000000000 +0800
@@ -27,9 +27,10 @@
 
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <linux/hid.h>
 #include "usbhid.h"
 
+#define DRIVER_VERSION "0.1.0"
+
 struct plff_device {
        struct hid_report *report;
 };
@@ -56,7 +57,7 @@ static int hid_plff_play(struct input_de
        return 0;
 }
 
-int hid_plff_init(struct hid_device *hid)
+int hid_plff_init_device(struct hid_device *hid)
 {
        struct plff_device *plff;
        struct hid_report *report;
@@ -127,3 +128,48 @@ int hid_plff_init(struct hid_device *hid
 
        return 0;
 }
+
+static struct usb_device_id hid_plff_ids[] = {
+       { USB_DEVICE(0x810, 0x0001) },
+       {}
+};
+
+MODULE_DEVICE_TABLE (usb, hid_plff_ids);
+
+static int hid_plff_match(struct hid_driver *driver, struct hid_device *device)
+{
+       struct usbhid_device *usbhid;
+
+       usbhid = device->tl_data;
+       return (int)usb_match_id(usbhid->intf, hid_plff_ids);
+}
+
+static int hid_plff_probe(struct hid_device *device)
+{
+       if (hidinput_connect(device))
+               return -ENODEV;
+       return hid_plff_init_device(device);
+}
+
+static struct hid_driver hid_plff_driver = {
+       .name = "hid-plff",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .match = hid_plff_match,
+       .probe = hid_plff_probe,
+};
+
+static int __init hid_plff_init(void)
+{
+       return hid_register_driver(&hid_plff_driver);
+}
+
+static void __exit hid_plff_exit(void)
+{
+       hid_unregister_driver(&hid_plff_driver);
+}
+
+module_init(hid_plff_init);
+module_exit(hid_plff_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-tmff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-tmff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-tmff.c     2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-tmff.c      2007-04-15 
21:30:35.000000000 +0800
@@ -32,9 +32,10 @@
 #undef DEBUG
 #include <linux/usb.h>
 
-#include <linux/hid.h>
 #include "usbhid.h"
 
+#define DRIVER_VERSION "0.1.0"
+
 /* Usages for thrustmaster devices I know about */
 #define THRUSTMASTER_USAGE_RUMBLE_LR   (HID_UP_GENDESK | 0xbb)
 
@@ -76,7 +77,7 @@ static int hid_tmff_play(struct input_de
        return 0;
 }
 
-int hid_tmff_init(struct hid_device *hid)
+int hid_tmff_init_device(struct hid_device *hid)
 {
        struct tmff_device *tmff;
        struct list_head *pos;
@@ -145,3 +146,48 @@ int hid_tmff_init(struct hid_device *hid
        return 0;
 }
 
+
+static struct usb_device_id hid_tmff_ids[] = {
+       { USB_DEVICE(0x44f, 0xb304) },
+       {}
+};
+
+MODULE_DEVICE_TABLE (usb, hid_tmff_ids);
+
+static int hid_tmff_match(struct hid_driver *driver, struct hid_device *device)
+{
+       struct usbhid_device *usbhid;
+
+       usbhid = device->tl_data;
+       return (int)usb_match_id(usbhid->intf, hid_tmff_ids);
+}
+
+static int hid_tmff_probe(struct hid_device *device)
+{
+       if (hidinput_connect(device))
+               return -ENODEV;
+       return hid_tmff_init_device(device);
+}
+
+static struct hid_driver hid_tmff_driver = {
+       .name = "hid-tmff",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .match = hid_tmff_match,
+       .probe = hid_tmff_probe,
+};
+
+static int __init hid_tmff_init(void)
+{
+       return hid_register_driver(&hid_tmff_driver);
+}
+
+static void __exit hid_tmff_exit(void)
+{
+       hid_unregister_driver(&hid_tmff_driver);
+}
+
+module_init(hid_tmff_init);
+module_exit(hid_tmff_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-zpff.c 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-zpff.c
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/hid-zpff.c     2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/hid-zpff.c      2007-04-15 
21:30:44.000000000 +0800
@@ -27,9 +27,10 @@
 
 #include <linux/input.h>
 #include <linux/usb.h>
-#include <linux/hid.h>
 #include "usbhid.h"
 
+#define DRIVER_VERSION "0.1.0"
+
 struct zpff_device {
        struct hid_report *report;
 };
@@ -62,7 +63,7 @@ static int hid_zpff_play(struct input_de
        return 0;
 }
 
-int hid_zpff_init(struct hid_device *hid)
+int hid_zpff_init_device(struct hid_device *hid)
 {
        struct zpff_device *zpff;
        struct hid_report *report;
@@ -109,3 +110,50 @@ int hid_zpff_init(struct hid_device *hid
 
        return 0;
 }
+
+static struct usb_device_id hid_zpff_ids[] = {
+       { USB_DEVICE(0x46d, 0x0005) },
+       { USB_DEVICE(0xc12, 0x0030) },
+       {}
+};
+
+MODULE_DEVICE_TABLE (usb, hid_zpff_ids);
+
+static int hid_zpff_match(struct hid_driver *driver, struct hid_device *device)
+{
+       struct usbhid_device *usbhid;
+
+       usbhid = device->tl_data;
+       return (int)usb_match_id(usbhid->intf, hid_zpff_ids);
+}
+
+static int hid_zpff_probe(struct hid_device *device)
+{
+       if (hidinput_connect(device))
+               return -ENODEV;
+       return hid_zpff_init_device(device);
+}
+
+
+static struct hid_driver hid_zpff_driver = {
+       .name = "hid-zpff",
+       .version = DRIVER_VERSION,
+       .bus = BUS_USB,
+       .module = THIS_MODULE,
+       .match = hid_zpff_match,
+       .probe = hid_zpff_probe,
+};
+
+static int __init hid_zpff_init(void)
+{
+       return hid_register_driver(&hid_zpff_driver);
+}
+
+static void __exit hid_zpff_exit(void)
+{
+       hid_unregister_driver(&hid_zpff_driver);
+}
+
+module_init(hid_zpff_init);
+module_exit(hid_zpff_exit);
+MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/Kconfig 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/Kconfig
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/Kconfig        2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/Kconfig 2007-04-10 
10:24:51.000000000 +0800
@@ -24,8 +24,8 @@ config USB_HID
 comment "Input core support is needed for USB HID input layer or HIDBP support"
        depends on USB_HID && INPUT=n
 
-config USB_HIDINPUT_POWERBOOK
-       bool "Enable support for iBook/PowerBook special keys"
+config POWERBOOK
+       tristate "Enable support for iBook/PowerBook special keys"
        default n
        depends on USB_HID
        help
@@ -34,29 +34,17 @@ config USB_HIDINPUT_POWERBOOK
 
          If unsure, say N.
 
-config HID_FF
-       bool "Force feedback support (EXPERIMENTAL)"
-       depends on USB_HID && EXPERIMENTAL
-       help
-         Say Y here is you want force feedback support for a few HID devices.
-         See below for a list of supported devices.
-
-         See <file:Documentation/input/ff.txt> for a description of the force
-         feedback API.
-
-         If unsure, say N.
-
 config HID_PID
-       bool "PID device support"
-       depends on HID_FF
+       tristate "PID device support"
+       depends on USB_HID
        help
          Say Y here if you have a PID-compliant device and wish to enable force
          feedback for it. Microsoft Sidewinder Force Feedback 2 is one of such
          devices.
 
 config LOGITECH_FF
-       bool "Logitech devices support"
-       depends on HID_FF
+       tristate "Logitech devices support"
+       depends on USB_HID
        select INPUT_FF_MEMLESS if USB_HID
        help
          Say Y here if you have one of these devices:
@@ -71,16 +59,16 @@ config LOGITECH_FF
          force feedback.
 
 config PANTHERLORD_FF
-       bool "PantherLord USB/PS2 2in1 Adapter support"
-       depends on HID_FF
+       tristate "PantherLord USB/PS2 2in1 Adapter support"
+       depends on USB_HID
        select INPUT_FF_MEMLESS if USB_HID
        help
          Say Y here if you have a PantherLord USB/PS2 2in1 Adapter and want
          to enable force feedback support for it.
 
 config THRUSTMASTER_FF
-       bool "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
-       depends on HID_FF && EXPERIMENTAL
+       tristate "ThrustMaster FireStorm Dual Power 2 support (EXPERIMENTAL)"
+       depends on USB_HID && EXPERIMENTAL
        select INPUT_FF_MEMLESS if USB_HID
        help
          Say Y here if you have a THRUSTMASTER FireStore Dual Power 2,
@@ -89,15 +77,15 @@ config THRUSTMASTER_FF
          force feedback.
 
 config ZEROPLUS_FF
-       bool "Zeroplus based game controller support"
-       depends on HID_FF
+       tristate "Zeroplus based game controller support"
+       depends on USB_HID
        select INPUT_FF_MEMLESS if USB_HID
        help
          Say Y here if you have a Zeroplus based game controller and want to
          enable force feedback for it.
 
 config USB_HIDDEV
-       bool "/dev/hiddev raw HID device support"
+       tristate "/dev/hiddev raw HID device support"
        depends on USB_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/usbhid/Makefile 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/Makefile
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/Makefile       2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/Makefile        2007-04-17 
09:23:33.000000000 +0800
@@ -6,29 +6,13 @@
 usbhid-objs    := hid-core.o
 
 # Optional parts of multipart objects.
-
-ifeq ($(CONFIG_USB_HIDDEV),y)
-       usbhid-objs     += hiddev.o
-endif
-ifeq ($(CONFIG_HID_PID),y)
-       usbhid-objs     += hid-pidff.o
-endif
-ifeq ($(CONFIG_LOGITECH_FF),y)
-       usbhid-objs     += hid-lgff.o
-endif
-ifeq ($(CONFIG_PANTHERLORD_FF),y)
-       usbhid-objs     += hid-plff.o
-endif
-ifeq ($(CONFIG_THRUSTMASTER_FF),y)
-       usbhid-objs     += hid-tmff.o
-endif
-ifeq ($(CONFIG_ZEROPLUS_FF),y)
-       usbhid-objs     += hid-zpff.o
-endif
-ifeq ($(CONFIG_HID_FF),y)
-       usbhid-objs     += hid-ff.o
-endif
-
+obj-$(CONFIG_HID_PID)          += hid-pidff.o
+obj-$(CONFIG_THRUSTMASTER_FF)   += hid-tmff.o
+obj-$(CONFIG_ZEROPLUS_FF)       += hid-zpff.o
+obj-$(CONFIG_POWERBOOK)                += hid-pb.o
+obj-$(CONFIG_LOGITECH_FF)       += hid-lgff.o
+obj-$(CONFIG_PANTHERLORD_FF)    += hid-plff.o
+obj-$(CONFIG_USB_HIDDEV)       += hiddev.o
 obj-$(CONFIG_USB_HID)          += usbhid.o
 obj-$(CONFIG_USB_KBD)          += usbkbd.o
 obj-$(CONFIG_USB_MOUSE)                += usbmouse.o
diff -Naurp linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/usbhid.h 
linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/usbhid.h
--- linux-2.6.21-rc6-mm1.orig/drivers/hid/usbhid/usbhid.h       2007-04-10 
09:16:46.000000000 +0800
+++ linux-2.6.21-rc6-mm1.new/drivers/hid/usbhid/usbhid.h        2007-04-10 
10:24:51.000000000 +0800
@@ -30,6 +30,9 @@
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/input.h>
+#include <linux/wait.h>
+#include <linux/hid.h>
+#include <linux/hid-debug.h>
 
 /*  API provided by hid-core.c for USB HID drivers */
 int usbhid_wait_io(struct hid_device* hid);
@@ -77,6 +80,7 @@ struct usbhid_device {
        unsigned long stop_retry;                                       /* Time 
to give up, in jiffies */
        unsigned int retry_delay;                                       /* 
Delay length in ms */
        struct work_struct reset_work;                                  /* Task 
context for resets */
+       wait_queue_head_t wait;
 
 };
 




-------------------------------------------------------------------------
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

Reply via email to