Merge branches 'for-3.9/logitech', 'for-3.9/multitouch', 'for-3.9/ntrig', 'for-3...
authorJiri Kosina <jkosina@suse.cz>
Thu, 21 Feb 2013 09:45:01 +0000 (10:45 +0100)
committerJiri Kosina <jkosina@suse.cz>
Thu, 21 Feb 2013 09:45:01 +0000 (10:45 +0100)
66 files changed:
Documentation/ABI/testing/sysfs-driver-hid-thingm [new file with mode: 0644]
MAINTAINERS
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-a4tech.c
drivers/hid/hid-apple.c
drivers/hid/hid-aureal.c
drivers/hid/hid-axff.c
drivers/hid/hid-belkin.c
drivers/hid/hid-cherry.c
drivers/hid/hid-chicony.c
drivers/hid/hid-core.c
drivers/hid/hid-cypress.c
drivers/hid/hid-dr.c
drivers/hid/hid-elecom.c
drivers/hid/hid-emsff.c
drivers/hid/hid-ezkey.c
drivers/hid/hid-gaff.c
drivers/hid/hid-generic.c
drivers/hid/hid-gyration.c
drivers/hid/hid-holtek-kbd.c
drivers/hid/hid-holtekff.c
drivers/hid/hid-icade.c
drivers/hid/hid-ids.h
drivers/hid/hid-kensington.c
drivers/hid/hid-keytouch.c
drivers/hid/hid-kye.c
drivers/hid/hid-lcpower.c
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-lg.c
drivers/hid/hid-lg4ff.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-monterey.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-ortek.c
drivers/hid/hid-petalynx.c
drivers/hid/hid-picolcd_core.c
drivers/hid/hid-pl.c
drivers/hid/hid-primax.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-ps3remote.c
drivers/hid/hid-roccat-lua.c
drivers/hid/hid-saitek.c
drivers/hid/hid-samsung.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sjoy.c
drivers/hid/hid-sony.c
drivers/hid/hid-speedlink.c
drivers/hid/hid-sunplus.c
drivers/hid/hid-thingm.c [new file with mode: 0644]
drivers/hid/hid-tivo.c
drivers/hid/hid-tmff.c
drivers/hid/hid-topseed.c
drivers/hid/hid-twinhan.c
drivers/hid/hid-uclogic.c
drivers/hid/hid-wacom.c
drivers/hid/hid-waltop.c
drivers/hid/hid-wiimote-core.c
drivers/hid/hid-wiimote-debug.c
drivers/hid/hid-wiimote-ext.c
drivers/hid/hid-zpff.c
drivers/hid/hid-zydacron.c
include/linux/hid.h
include/uapi/linux/uhid.h

diff --git a/Documentation/ABI/testing/sysfs-driver-hid-thingm b/Documentation/ABI/testing/sysfs-driver-hid-thingm
new file mode 100644 (file)
index 0000000..abcffee
--- /dev/null
@@ -0,0 +1,23 @@
+What:          /sys/class/leds/blink1::<serial>/rgb
+Date:          January 2013
+Contact:       Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+Description:   The ThingM blink1 is an USB RGB LED. The color notation is
+               3-byte hexadecimal. Read this attribute to get the last set
+               color. Write the 24-bit hexadecimal color to change the current
+               LED color. The default color is full white (0xFFFFFF).
+               For instance, set the color to green with: echo 00FF00 > rgb
+
+What:          /sys/class/leds/blink1::<serial>/fade
+Date:          January 2013
+Contact:       Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+Description:   This attribute allows to set a fade time in milliseconds for
+               the next color change. Read the attribute to know the current
+               fade time. The default value is set to 0 (no fade time). For
+               instance, set a fade time of 2 seconds with: echo 2000 > fade
+
+What:          /sys/class/leds/blink1::<serial>/play
+Date:          January 2013
+Contact:       Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+Description:   This attribute is used to play/pause the light patterns. Write 1
+               to start playing, 0 to stop. Reading this attribute returns the
+               current playing status.
index 212c255..833897c 100644 (file)
@@ -7585,6 +7585,11 @@ S:      Supported
 F:      drivers/thermal/
 F:      include/linux/thermal.h
 
+THINGM BLINK(1) USB RGB LED DRIVER
+M:     Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+S:     Maintained
+F:     drivers/hid/hid-thingm.c
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
index e7d6a13..3d52945 100644 (file)
@@ -655,6 +655,16 @@ config HID_TOPSEED
        Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
        CLLRCMCE remote control.
 
+config HID_THINGM
+       tristate "ThingM blink(1) USB RGB LED"
+       depends on USB_HID
+       depends on LEDS_CLASS
+       ---help---
+       Support for the ThingM blink(1) USB RGB LED. This driver registers a
+       Linux LED class instance, plus additional sysfs attributes to control
+       RGB colors, fade time and playing. The device is exposed through hidraw
+       to access other functions.
+
 config HID_THRUSTMASTER
        tristate "ThrustMaster devices support"
        depends on USB_HID
@@ -719,7 +729,7 @@ config HID_ZYDACRON
 
 config HID_SENSOR_HUB
        tristate "HID Sensors framework support"
-       depends on USB_HID
+       depends on USB_HID && GENERIC_HARDIRQS
        select MFD_CORE
        default n
        -- help---
index b622157..9301704 100644 (file)
@@ -103,6 +103,7 @@ obj-$(CONFIG_HID_SONY)              += hid-sony.o
 obj-$(CONFIG_HID_SPEEDLINK)    += hid-speedlink.o
 obj-$(CONFIG_HID_SUNPLUS)      += hid-sunplus.o
 obj-$(CONFIG_HID_GREENASIA)    += hid-gaff.o
+obj-$(CONFIG_HID_THINGM)       += hid-thingm.o
 obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
 obj-$(CONFIG_HID_TIVO)         += hid-tivo.o
 obj-$(CONFIG_HID_TOPSEED)      += hid-topseed.o
index 0a23988..7c5507e 100644 (file)
@@ -146,17 +146,6 @@ static struct hid_driver a4_driver = {
        .probe = a4_probe,
        .remove = a4_remove,
 };
+module_hid_driver(a4_driver);
 
-static int __init a4_init(void)
-{
-       return hid_register_driver(&a4_driver);
-}
-
-static void __exit a4_exit(void)
-{
-       hid_unregister_driver(&a4_driver);
-}
-
-module_init(a4_init);
-module_exit(a4_exit);
 MODULE_LICENSE("GPL");
index d0f7662..320a958 100644 (file)
@@ -555,23 +555,6 @@ static struct hid_driver apple_driver = {
        .input_mapping = apple_input_mapping,
        .input_mapped = apple_input_mapped,
 };
+module_hid_driver(apple_driver);
 
-static int __init apple_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&apple_driver);
-       if (ret)
-               pr_err("can't register apple driver\n");
-
-       return ret;
-}
-
-static void __exit apple_exit(void)
-{
-       hid_unregister_driver(&apple_driver);
-}
-
-module_init(apple_init);
-module_exit(apple_exit);
 MODULE_LICENSE("GPL");
index 7968187..340ba9d 100644 (file)
@@ -37,17 +37,6 @@ static struct hid_driver aureal_driver = {
        .id_table = aureal_devices,
        .report_fixup = aureal_report_fixup,
 };
+module_hid_driver(aureal_driver);
 
-static int __init aureal_init(void)
-{
-       return hid_register_driver(&aureal_driver);
-}
-
-static void __exit aureal_exit(void)
-{
-       hid_unregister_driver(&aureal_driver);
-}
-
-module_init(aureal_init);
-module_exit(aureal_exit);
 MODULE_LICENSE("GPL");
index 5be858d..62f0cee 100644 (file)
@@ -192,19 +192,7 @@ static struct hid_driver ax_driver = {
        .probe          = ax_probe,
        .remove         = ax_remove,
 };
-
-static int __init ax_init(void)
-{
-       return hid_register_driver(&ax_driver);
-}
-
-static void __exit ax_exit(void)
-{
-       hid_unregister_driver(&ax_driver);
-}
-
-module_init(ax_init);
-module_exit(ax_exit);
+module_hid_driver(ax_driver);
 
 MODULE_AUTHOR("Sergei Kolzun");
 MODULE_DESCRIPTION("Force feedback support for ACRUX game controllers");
index a1a5a12..cc4cf13 100644 (file)
@@ -86,17 +86,6 @@ static struct hid_driver belkin_driver = {
        .input_mapping = belkin_input_mapping,
        .probe = belkin_probe,
 };
+module_hid_driver(belkin_driver);
 
-static int __init belkin_init(void)
-{
-       return hid_register_driver(&belkin_driver);
-}
-
-static void __exit belkin_exit(void)
-{
-       hid_unregister_driver(&belkin_driver);
-}
-
-module_init(belkin_init);
-module_exit(belkin_exit);
 MODULE_LICENSE("GPL");
index af034d3..1bdcccc 100644 (file)
@@ -69,17 +69,6 @@ static struct hid_driver ch_driver = {
        .report_fixup = ch_report_fixup,
        .input_mapping = ch_input_mapping,
 };
+module_hid_driver(ch_driver);
 
-static int __init ch_init(void)
-{
-       return hid_register_driver(&ch_driver);
-}
-
-static void __exit ch_exit(void)
-{
-       hid_unregister_driver(&ch_driver);
-}
-
-module_init(ch_init);
-module_exit(ch_exit);
 MODULE_LICENSE("GPL");
index a2abb8e..b613d5a 100644 (file)
@@ -70,17 +70,6 @@ static struct hid_driver ch_driver = {
        .id_table = ch_devices,
        .input_mapping = ch_input_mapping,
 };
+module_hid_driver(ch_driver);
 
-static int __init ch_init(void)
-{
-       return hid_register_driver(&ch_driver);
-}
-
-static void __exit ch_exit(void)
-{
-       hid_unregister_driver(&ch_driver);
-}
-
-module_init(ch_init);
-module_exit(ch_exit);
 MODULE_LICENSE("GPL");
index fe3a59e..6e90415 100644 (file)
@@ -1195,6 +1195,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
 {
        struct hid_report_enum *report_enum = hid->report_enum + type;
        struct hid_report *report;
+       struct hid_driver *hdrv;
        unsigned int a;
        int rsize, csize = size;
        u8 *cdata = data;
@@ -1231,6 +1232,9 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
        if (hid->claimed != HID_CLAIMED_HIDRAW) {
                for (a = 0; a < report->maxfield; a++)
                        hid_input_field(hid, report->field[a], cdata, interrupt);
+               hdrv = hid->driver;
+               if (hdrv && hdrv->report)
+                       hdrv->report(hid, report);
        }
 
        if (hid->claimed & HID_CLAIMED_INPUT)
@@ -1599,6 +1603,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ION, USB_DEVICE_ID_ICADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
@@ -1698,6 +1703,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
        { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb323) },
@@ -2228,6 +2234,14 @@ bool hid_ignore(struct hid_device *hdev)
                    hdev->type != HID_TYPE_USBMOUSE)
                        return true;
                break;
+       case USB_VENDOR_ID_VELLEMAN:
+               /* These are not HID devices.  They are handled by comedi. */
+               if ((hdev->product >= USB_DEVICE_ID_VELLEMAN_K8055_FIRST &&
+                    hdev->product <= USB_DEVICE_ID_VELLEMAN_K8055_LAST) ||
+                   (hdev->product >= USB_DEVICE_ID_VELLEMAN_K8061_FIRST &&
+                    hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST))
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
index 3e159a5..c4ef3bc 100644 (file)
@@ -144,17 +144,6 @@ static struct hid_driver cp_driver = {
        .event = cp_event,
        .probe = cp_probe,
 };
+module_hid_driver(cp_driver);
 
-static int __init cp_init(void)
-{
-       return hid_register_driver(&cp_driver);
-}
-
-static void __exit cp_exit(void)
-{
-       hid_unregister_driver(&cp_driver);
-}
-
-module_init(cp_init);
-module_exit(cp_exit);
 MODULE_LICENSE("GPL");
index e832f44..0fe8f65 100644 (file)
@@ -297,17 +297,6 @@ static struct hid_driver dr_driver = {
        .report_fixup = dr_report_fixup,
        .probe = dr_probe,
 };
+module_hid_driver(dr_driver);
 
-static int __init dr_init(void)
-{
-       return hid_register_driver(&dr_driver);
-}
-
-static void __exit dr_exit(void)
-{
-       hid_unregister_driver(&dr_driver);
-}
-
-module_init(dr_init);
-module_exit(dr_exit);
 MODULE_LICENSE("GPL");
index 79d0c61..d0bd13b 100644 (file)
@@ -41,17 +41,6 @@ static struct hid_driver elecom_driver = {
        .id_table = elecom_devices,
        .report_fixup = elecom_report_fixup
 };
+module_hid_driver(elecom_driver);
 
-static int __init elecom_init(void)
-{
-       return hid_register_driver(&elecom_driver);
-}
-
-static void __exit elecom_exit(void)
-{
-       hid_unregister_driver(&elecom_driver);
-}
-
-module_init(elecom_init);
-module_exit(elecom_exit);
 MODULE_LICENSE("GPL");
index 2630d48..2e093ab 100644 (file)
@@ -150,18 +150,7 @@ static struct hid_driver ems_driver = {
        .id_table = ems_devices,
        .probe = ems_probe,
 };
+module_hid_driver(ems_driver);
 
-static int ems_init(void)
-{
-       return hid_register_driver(&ems_driver);
-}
-
-static void ems_exit(void)
-{
-       hid_unregister_driver(&ems_driver);
-}
-
-module_init(ems_init);
-module_exit(ems_exit);
 MODULE_LICENSE("GPL");
 
index 6540af2..212ac6b 100644 (file)
@@ -76,17 +76,6 @@ static struct hid_driver ez_driver = {
        .input_mapping = ez_input_mapping,
        .event = ez_event,
 };
+module_hid_driver(ez_driver);
 
-static int __init ez_init(void)
-{
-       return hid_register_driver(&ez_driver);
-}
-
-static void __exit ez_exit(void)
-{
-       hid_unregister_driver(&ez_driver);
-}
-
-module_init(ez_init);
-module_exit(ez_exit);
 MODULE_LICENSE("GPL");
index f1e1bcf..04d2e6a 100644 (file)
@@ -176,17 +176,6 @@ static struct hid_driver ga_driver = {
        .id_table = ga_devices,
        .probe = ga_probe,
 };
+module_hid_driver(ga_driver);
 
-static int __init ga_init(void)
-{
-       return hid_register_driver(&ga_driver);
-}
-
-static void __exit ga_exit(void)
-{
-       hid_unregister_driver(&ga_driver);
-}
-
-module_init(ga_init);
-module_exit(ga_exit);
 MODULE_LICENSE("GPL");
index a8b3148..e288a4a 100644 (file)
@@ -34,19 +34,7 @@ static struct hid_driver hid_generic = {
        .name = "hid-generic",
        .id_table = hid_table,
 };
-
-static int __init hid_init(void)
-{
-       return hid_register_driver(&hid_generic);
-}
-
-static void __exit hid_exit(void)
-{
-       hid_unregister_driver(&hid_generic);
-}
-
-module_init(hid_init);
-module_exit(hid_exit);
+module_hid_driver(hid_generic);
 
 MODULE_AUTHOR("Henrik Rydberg");
 MODULE_DESCRIPTION("HID generic driver");
index 4442c30..288d61c 100644 (file)
@@ -88,17 +88,6 @@ static struct hid_driver gyration_driver = {
        .input_mapping = gyration_input_mapping,
        .event = gyration_event,
 };
+module_hid_driver(gyration_driver);
 
-static int __init gyration_init(void)
-{
-       return hid_register_driver(&gyration_driver);
-}
-
-static void __exit gyration_exit(void)
-{
-       hid_unregister_driver(&gyration_driver);
-}
-
-module_init(gyration_init);
-module_exit(gyration_exit);
 MODULE_LICENSE("GPL");
index e0a5d17..6e1a4a4 100644 (file)
@@ -167,17 +167,6 @@ static struct hid_driver holtek_kbd_driver = {
        .report_fixup = holtek_kbd_report_fixup,
        .probe = holtek_kbd_probe
 };
+module_hid_driver(holtek_kbd_driver);
 
-static int __init holtek_kbd_init(void)
-{
-       return hid_register_driver(&holtek_kbd_driver);
-}
-
-static void __exit holtek_kbd_exit(void)
-{
-       hid_unregister_driver(&holtek_kbd_driver);
-}
-
-module_exit(holtek_kbd_exit);
-module_init(holtek_kbd_init);
 MODULE_LICENSE("GPL");
index ff295e6..f34d118 100644 (file)
@@ -224,17 +224,4 @@ static struct hid_driver holtek_driver = {
        .id_table = holtek_devices,
        .probe = holtek_probe,
 };
-
-static int __init holtek_init(void)
-{
-       return hid_register_driver(&holtek_driver);
-}
-
-static void __exit holtek_exit(void)
-{
-       hid_unregister_driver(&holtek_driver);
-}
-
-module_init(holtek_init);
-module_exit(holtek_exit);
-
+module_hid_driver(holtek_driver);
index 1d6565e..09dcc04 100644 (file)
@@ -235,25 +235,8 @@ static struct hid_driver icade_driver = {
        .input_mapped = icade_input_mapped,
        .input_mapping = icade_input_mapping,
 };
+module_hid_driver(icade_driver);
 
-static int __init icade_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&icade_driver);
-       if (ret)
-               pr_err("can't register icade driver\n");
-
-       return ret;
-}
-
-static void __exit icade_exit(void)
-{
-       hid_unregister_driver(&icade_driver);
-}
-
-module_init(icade_init);
-module_exit(icade_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
 MODULE_DESCRIPTION("ION iCade input driver");
index 34e2547..d15ed56 100644 (file)
 #define USB_VENDOR_ID_JESS             0x0c45
 #define USB_DEVICE_ID_JESS_YUREX       0x1010
 
+#define USB_VENDOR_ID_JESS2            0x0f30
+#define USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD 0x0111
+
 #define USB_VENDOR_ID_KBGEAR           0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
 
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_F3D     0xc283
 #define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO     0xc286
 #define USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940      0xc287
-#define USB_DEVICE_ID_LOGITECH_WHEEL   0xc294
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG     0xc293
+#define USB_DEVICE_ID_LOGITECH_WHEEL   0xc294
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL      0xc295
 #define USB_DEVICE_ID_LOGITECH_DFP_WHEEL       0xc298
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL       0xc299
 #define USB_VENDOR_ID_NEC              0x073e
 #define USB_DEVICE_ID_NEC_USB_GAME_PAD 0x0301
 
+#define USB_VENDOR_ID_NEXIO            0x1870
+#define USB_DEVICE_ID_NEXIO_MULTITOUCH_420     0x010d
+
 #define USB_VENDOR_ID_NEXTWINDOW       0x1926
 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN   0x0003
 
 #define USB_DEVICE_ID_SYNAPTICS_WTP    0x0010
 #define USB_DEVICE_ID_SYNAPTICS_DPAD   0x0013
 
+#define USB_VENDOR_ID_THINGM           0x27b8
+#define USB_DEVICE_ID_BLINK1           0x01ed
+
 #define USB_VENDOR_ID_THRUSTMASTER     0x044f
 
 #define USB_VENDOR_ID_TIVO             0x150a
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709    0x0709
 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19    0x0a19
 
+#define USB_VENDOR_ID_VELLEMAN         0x10cf
+#define USB_DEVICE_ID_VELLEMAN_K8055_FIRST     0x5500
+#define USB_DEVICE_ID_VELLEMAN_K8055_LAST      0x5503
+#define USB_DEVICE_ID_VELLEMAN_K8061_FIRST     0x8061
+#define USB_DEVICE_ID_VELLEMAN_K8061_LAST      0x8068
+
 #define USB_VENDOR_ID_VERNIER          0x08f7
 #define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
 #define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
index a5b4016..fe9a99d 100644 (file)
@@ -47,17 +47,6 @@ static struct hid_driver ks_driver = {
        .id_table = ks_devices,
        .input_mapping = ks_input_mapping,
 };
+module_hid_driver(ks_driver);
 
-static int __init ks_init(void)
-{
-       return hid_register_driver(&ks_driver);
-}
-
-static void __exit ks_exit(void)
-{
-       hid_unregister_driver(&ks_driver);
-}
-
-module_init(ks_init);
-module_exit(ks_exit);
 MODULE_LICENSE("GPL");
index 07cd825..3074671 100644 (file)
@@ -49,18 +49,7 @@ static struct hid_driver keytouch_driver = {
        .id_table = keytouch_devices,
        .report_fixup = keytouch_report_fixup,
 };
+module_hid_driver(keytouch_driver);
 
-static int __init keytouch_init(void)
-{
-       return hid_register_driver(&keytouch_driver);
-}
-
-static void __exit keytouch_exit(void)
-{
-       hid_unregister_driver(&keytouch_driver);
-}
-
-module_init(keytouch_init);
-module_exit(keytouch_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jiri Kosina");
index b4f0d82..ef72dae 100644 (file)
@@ -419,17 +419,6 @@ static struct hid_driver kye_driver = {
        .probe = kye_probe,
        .report_fixup = kye_report_fixup,
 };
+module_hid_driver(kye_driver);
 
-static int __init kye_init(void)
-{
-       return hid_register_driver(&kye_driver);
-}
-
-static void __exit kye_exit(void)
-{
-       hid_unregister_driver(&kye_driver);
-}
-
-module_init(kye_init);
-module_exit(kye_exit);
 MODULE_LICENSE("GPL");
index 22bc14a..6424cfd 100644 (file)
@@ -54,17 +54,6 @@ static struct hid_driver ts_driver = {
        .id_table = ts_devices,
        .input_mapping = ts_input_mapping,
 };
+module_hid_driver(ts_driver);
 
-static int __init ts_init(void)
-{
-       return hid_register_driver(&ts_driver);
-}
-
-static void __exit ts_exit(void)
-{
-       hid_unregister_driver(&ts_driver);
-}
-
-module_init(ts_init);
-module_exit(ts_exit);
 MODULE_LICENSE("GPL");
index cea016e..956c3b1 100644 (file)
@@ -468,18 +468,6 @@ static struct hid_driver tpkbd_driver = {
        .probe = tpkbd_probe,
        .remove = tpkbd_remove,
 };
-
-static int __init tpkbd_init(void)
-{
-       return hid_register_driver(&tpkbd_driver);
-}
-
-static void __exit tpkbd_exit(void)
-{
-       hid_unregister_driver(&tpkbd_driver);
-}
-
-module_init(tpkbd_init);
-module_exit(tpkbd_exit);
+module_hid_driver(tpkbd_driver);
 
 MODULE_LICENSE("GPL");
index a2f8e88..6f12ecd 100644 (file)
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/usb.h>
 #include <linux/wait.h>
 
+#include "usbhid/usbhid.h"
 #include "hid-ids.h"
 #include "hid-lg.h"
 
 #define LG_FF3                 0x1000
 #define LG_FF4                 0x2000
 
-/* Size of the original descriptor of the Driving Force Pro wheel */
+/* Size of the original descriptors of the Driving Force (and Pro) wheels */
+#define DF_RDESC_ORIG_SIZE     130
 #define DFP_RDESC_ORIG_SIZE    97
+#define MOMO_RDESC_ORIG_SIZE   87
 
-/* Fixed report descriptor for Logitech Driving Force Pro wheel controller
+/* Fixed report descriptors for Logitech Driving Force (and Pro)
+ * wheel controllers
  *
- * The original descriptor hides the separate throttle and brake axes in
+ * The original descriptors hide the separate throttle and brake axes in
  * a custom vendor usage page, providing only a combined value as
  * GenericDesktop.Y.
- * This descriptor removes the combined Y axis and instead reports
+ * These descriptors remove the combined Y axis and instead report
  * separate throttle (Y) and brake (RZ).
  */
+static __u8 df_rdesc_fixed[] = {
+0x05, 0x01,         /*  Usage Page (Desktop),                   */
+0x09, 0x04,         /*  Usage (Joystik),                        */
+0xA1, 0x01,         /*  Collection (Application),               */
+0xA1, 0x02,         /*      Collection (Logical),               */
+0x95, 0x01,         /*          Report Count (1),               */
+0x75, 0x0A,         /*          Report Size (10),               */
+0x14,               /*          Logical Minimum (0),            */
+0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),         */
+0x34,               /*          Physical Minimum (0),           */
+0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),        */
+0x09, 0x30,         /*          Usage (X),                      */
+0x81, 0x02,         /*          Input (Variable),               */
+0x95, 0x0C,         /*          Report Count (12),              */
+0x75, 0x01,         /*          Report Size (1),                */
+0x25, 0x01,         /*          Logical Maximum (1),            */
+0x45, 0x01,         /*          Physical Maximum (1),           */
+0x05, 0x09,         /*          Usage (Buttons),                */
+0x19, 0x01,         /*          Usage Minimum (1),              */
+0x29, 0x0c,         /*          Usage Maximum (12),             */
+0x81, 0x02,         /*          Input (Variable),               */
+0x95, 0x02,         /*          Report Count (2),               */
+0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
+0x09, 0x01,         /*          Usage (?: 1),                   */
+0x81, 0x02,         /*          Input (Variable),               */
+0x05, 0x01,         /*          Usage Page (Desktop),           */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+0x95, 0x01,         /*          Report Count (1),               */
+0x75, 0x08,         /*          Report Size (8),                */
+0x81, 0x02,         /*          Input (Variable),               */
+0x25, 0x07,         /*          Logical Maximum (7),            */
+0x46, 0x3B, 0x01,   /*          Physical Maximum (315),         */
+0x75, 0x04,         /*          Report Size (4),                */
+0x65, 0x14,         /*          Unit (Degrees),                 */
+0x09, 0x39,         /*          Usage (Hat Switch),             */
+0x81, 0x42,         /*          Input (Variable, Null State),   */
+0x75, 0x01,         /*          Report Size (1),                */
+0x95, 0x04,         /*          Report Count (4),               */
+0x65, 0x00,         /*          Unit (none),                    */
+0x06, 0x00, 0xFF,   /*          Usage Page (Vendor: 65280),     */
+0x09, 0x01,         /*          Usage (?: 1),                   */
+0x25, 0x01,         /*          Logical Maximum (1),            */
+0x45, 0x01,         /*          Physical Maximum (1),           */
+0x81, 0x02,         /*          Input (Variable),               */
+0x05, 0x01,         /*          Usage Page (Desktop),           */
+0x95, 0x01,         /*          Report Count (1),               */
+0x75, 0x08,         /*          Report Size (8),                */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+0x09, 0x31,         /*          Usage (Y),                      */
+0x81, 0x02,         /*          Input (Variable),               */
+0x09, 0x35,         /*          Usage (Rz),                     */
+0x81, 0x02,         /*          Input (Variable),               */
+0xC0,               /*      End Collection,                     */
+0xA1, 0x02,         /*      Collection (Logical),               */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),          */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),         */
+0x95, 0x07,         /*          Report Count (7),               */
+0x75, 0x08,         /*          Report Size (8),                */
+0x09, 0x03,         /*          Usage (?: 3),                   */
+0x91, 0x02,         /*          Output (Variable),              */
+0xC0,               /*      End Collection,                     */
+0xC0                /*  End Collection                          */
+};
+
 static __u8 dfp_rdesc_fixed[] = {
 0x05, 0x01,         /*  Usage Page (Desktop),                   */
 0x09, 0x04,         /*  Usage (Joystik),                        */
@@ -99,6 +170,51 @@ static __u8 dfp_rdesc_fixed[] = {
 0xC0                /*  End Collection                          */
 };
 
+static __u8 momo_rdesc_fixed[] = {
+0x05, 0x01,         /*  Usage Page (Desktop),               */
+0x09, 0x04,         /*  Usage (Joystik),                    */
+0xA1, 0x01,         /*  Collection (Application),           */
+0xA1, 0x02,         /*      Collection (Logical),           */
+0x95, 0x01,         /*          Report Count (1),           */
+0x75, 0x0A,         /*          Report Size (10),           */
+0x15, 0x00,         /*          Logical Minimum (0),        */
+0x26, 0xFF, 0x03,   /*          Logical Maximum (1023),     */
+0x35, 0x00,         /*          Physical Minimum (0),       */
+0x46, 0xFF, 0x03,   /*          Physical Maximum (1023),    */
+0x09, 0x30,         /*          Usage (X),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x95, 0x08,         /*          Report Count (8),           */
+0x75, 0x01,         /*          Report Size (1),            */
+0x25, 0x01,         /*          Logical Maximum (1),        */
+0x45, 0x01,         /*          Physical Maximum (1),       */
+0x05, 0x09,         /*          Usage Page (Button),        */
+0x19, 0x01,         /*          Usage Minimum (01h),        */
+0x29, 0x08,         /*          Usage Maximum (08h),        */
+0x81, 0x02,         /*          Input (Variable),           */
+0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+0x75, 0x0E,         /*          Report Size (14),           */
+0x95, 0x01,         /*          Report Count (1),           */
+0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
+0x46, 0xFF, 0x00,   /*          Physical Maximum (255),     */
+0x09, 0x00,         /*          Usage (00h),                */
+0x81, 0x02,         /*          Input (Variable),           */
+0x05, 0x01,         /*          Usage Page (Desktop),       */
+0x75, 0x08,         /*          Report Size (8),            */
+0x09, 0x31,         /*          Usage (Y),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x09, 0x32,         /*          Usage (Z),                  */
+0x81, 0x02,         /*          Input (Variable),           */
+0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
+0x09, 0x01,         /*          Usage (01h),                */
+0x81, 0x02,         /*          Input (Variable),           */
+0xC0,               /*      End Collection,                 */
+0xA1, 0x02,         /*      Collection (Logical),           */
+0x09, 0x02,         /*          Usage (02h),                */
+0x95, 0x07,         /*          Report Count (7),           */
+0x91, 0x02,         /*          Output (Variable),          */
+0xC0,               /*      End Collection,                 */
+0xC0                /*  End Collection                      */
+};
 
 /*
  * Certain Logitech keyboards send in report #3 keys which are far
@@ -109,6 +225,8 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
        struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
+       struct usb_device_descriptor *udesc;
+       __u16 bcdDevice, rev_maj, rev_min;
 
        if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
                        rdesc[84] == 0x8c && rdesc[85] == 0x02) {
@@ -124,17 +242,39 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                         "fixing up rel/abs in Logitech report descriptor\n");
                rdesc[33] = rdesc[50] = 0x02;
        }
-       if ((drv_data->quirks & LG_FF4) && *rsize >= 101 &&
-                       rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
-                       rdesc[47] == 0x05 && rdesc[48] == 0x09) {
-               hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n");
-               rdesc[41] = 0x05;
-               rdesc[42] = 0x09;
-               rdesc[47] = 0x95;
-               rdesc[48] = 0x0B;
-       }
 
        switch (hdev->product) {
+
+       /* Several wheels report as this id when operating in emulation mode. */
+       case USB_DEVICE_ID_LOGITECH_WHEEL:
+               udesc = &(hid_to_usb_dev(hdev)->descriptor);
+               if (!udesc) {
+                       hid_err(hdev, "NULL USB device descriptor\n");
+                       break;
+               }
+               bcdDevice = le16_to_cpu(udesc->bcdDevice);
+               rev_maj = bcdDevice >> 8;
+               rev_min = bcdDevice & 0xff;
+
+               /* Update the report descriptor for only the Driving Force wheel */
+               if (rev_maj == 1 && rev_min == 2 &&
+                               *rsize == DF_RDESC_ORIG_SIZE) {
+                       hid_info(hdev,
+                               "fixing up Logitech Driving Force report descriptor\n");
+                       rdesc = df_rdesc_fixed;
+                       *rsize = sizeof(df_rdesc_fixed);
+               }
+               break;
+
+       case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+               if (*rsize == MOMO_RDESC_ORIG_SIZE) {
+                       hid_info(hdev,
+                               "fixing up Logitech Momo Force (Red) report descriptor\n");
+                       rdesc = momo_rdesc_fixed;
+                       *rsize = sizeof(momo_rdesc_fixed);
+               }
+               break;
+
        case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
                if (*rsize == DFP_RDESC_ORIG_SIZE) {
                        hid_info(hdev,
@@ -143,6 +283,17 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        *rsize = sizeof(dfp_rdesc_fixed);
                }
                break;
+
+       case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+               if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
+                               rdesc[47] == 0x05 && rdesc[48] == 0x09) {
+                       hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
+                       rdesc[41] = 0x05;
+                       rdesc[42] = 0x09;
+                       rdesc[47] = 0x95;
+                       rdesc[48] = 0x0B;
+               }
+               break;
        }
 
        return rdesc;
@@ -328,6 +479,26 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
                         usage->type == EV_REL || usage->type == EV_ABS))
                clear_bit(usage->code, *bit);
 
+       /* Ensure that Logitech wheels are not given a default fuzz/flat value */
+       if (usage->type == EV_ABS && (usage->code == ABS_X ||
+                       usage->code == ABS_Y || usage->code == ABS_Z ||
+                       usage->code == ABS_RZ)) {
+               switch (hdev->product) {
+               case USB_DEVICE_ID_LOGITECH_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
+               case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
+                       field->application = HID_GD_MULTIAXIS;
+                       break;
+               default:
+                       break;
+               }
+       }
+
        return 0;
 }
 
@@ -465,7 +636,7 @@ static const struct hid_device_id lg_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO),
                .driver_data = LG_FF },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL),
-               .driver_data = LG_FF4 },
+               .driver_data = LG_NOGET | LG_FF4 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
                .driver_data = LG_FF4 },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
@@ -503,17 +674,6 @@ static struct hid_driver lg_driver = {
        .probe = lg_probe,
        .remove = lg_remove,
 };
+module_hid_driver(lg_driver);
 
-static int __init lg_init(void)
-{
-       return hid_register_driver(&lg_driver);
-}
-
-static void __exit lg_exit(void)
-{
-       hid_unregister_driver(&lg_driver);
-}
-
-module_init(lg_init);
-module_exit(lg_exit);
 MODULE_LICENSE("GPL");
index d7947c7..65a6ec8 100644 (file)
 #define G27_REV_MAJ 0x12
 #define G27_REV_MIN 0x38
 
-#define DFP_X_MIN 0
-#define DFP_X_MAX 16383
-#define DFP_PEDAL_MIN 0
-#define DFP_PEDAL_MAX 255
-
 #define to_hid_device(pdev) container_of(pdev, struct hid_device, dev)
 
 static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range);
@@ -598,18 +593,6 @@ int lg4ff_init(struct hid_device *hid)
                return error;
        dbg_hid("sysfs interface created\n");
 
-       /* Set default axes parameters */
-       switch (lg4ff_devices[i].product_id) {
-       case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
-               dbg_hid("Setting axes parameters for Driving Force Pro\n");
-               input_set_abs_params(dev, ABS_X, DFP_X_MIN, DFP_X_MAX, 0, 0);
-               input_set_abs_params(dev, ABS_Y, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
-               input_set_abs_params(dev, ABS_RZ, DFP_PEDAL_MIN, DFP_PEDAL_MAX, 0, 0);
-               break;
-       default:
-               break;
-       }
-
        /* Set the maximum range to start with */
        entry->range = entry->max_range;
        if (entry->set_range != NULL)
index 25ddf3e..f7f113b 100644 (file)
@@ -569,23 +569,6 @@ static struct hid_driver magicmouse_driver = {
        .raw_event = magicmouse_raw_event,
        .input_mapping = magicmouse_input_mapping,
 };
+module_hid_driver(magicmouse_driver);
 
-static int __init magicmouse_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&magicmouse_driver);
-       if (ret)
-               pr_err("can't register magicmouse driver\n");
-
-       return ret;
-}
-
-static void __exit magicmouse_exit(void)
-{
-       hid_unregister_driver(&magicmouse_driver);
-}
-
-module_init(magicmouse_init);
-module_exit(magicmouse_exit);
 MODULE_LICENSE("GPL");
index 6fcd466..29d27f6 100644 (file)
@@ -221,17 +221,6 @@ static struct hid_driver ms_driver = {
        .event = ms_event,
        .probe = ms_probe,
 };
+module_hid_driver(ms_driver);
 
-static int __init ms_init(void)
-{
-       return hid_register_driver(&ms_driver);
-}
-
-static void __exit ms_exit(void)
-{
-       hid_unregister_driver(&ms_driver);
-}
-
-module_init(ms_init);
-module_exit(ms_exit);
 MODULE_LICENSE("GPL");
index cd3643e..9e14c00 100644 (file)
@@ -63,17 +63,6 @@ static struct hid_driver mr_driver = {
        .report_fixup = mr_report_fixup,
        .input_mapping = mr_input_mapping,
 };
+module_hid_driver(mr_driver);
 
-static int __init mr_init(void)
-{
-       return hid_register_driver(&mr_driver);
-}
-
-static void __exit mr_exit(void)
-{
-       hid_unregister_driver(&mr_driver);
-}
-
-module_init(mr_init);
-module_exit(mr_exit);
 MODULE_LICENSE("GPL");
index 61543c0..7a1ebb8 100644 (file)
@@ -54,6 +54,7 @@ MODULE_LICENSE("GPL");
 #define MT_QUIRK_NO_AREA               (1 << 9)
 #define MT_QUIRK_IGNORE_DUPLICATES     (1 << 10)
 #define MT_QUIRK_HOVERING              (1 << 11)
+#define MT_QUIRK_CONTACT_CNT_ACCURATE  (1 << 12)
 
 struct mt_slot {
        __s32 x, y, cx, cy, p, w, h;
@@ -83,8 +84,11 @@ struct mt_device {
        struct mt_class mtclass;        /* our mt device class */
        struct mt_fields *fields;       /* temporary placeholder for storing the
                                           multitouch fields */
+       int cc_index;   /* contact count field index in the report */
+       int cc_value_index;     /* contact count value index in the field */
        unsigned last_field_index;      /* last field index of the report */
        unsigned last_slot_field;       /* the last field of a slot */
+       unsigned mt_report_id;  /* the report ID of the multitouch device */
        __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
        __s8 inputmode_index;   /* InputMode HID feature index in the report */
        __s8 maxcontact_report_id;      /* Maximum Contact Number HID feature,
@@ -111,6 +115,9 @@ struct mt_device {
 #define MT_CLS_DUAL_INRANGE_CONTACTNUMBER      0x0007
 #define MT_CLS_DUAL_NSMU_CONTACTID             0x0008
 #define MT_CLS_INRANGE_CONTACTNUMBER           0x0009
+#define MT_CLS_NSMU                            0x000a
+#define MT_CLS_DUAL_CONTACT_NUMBER             0x0010
+#define MT_CLS_DUAL_CONTACT_ID                 0x0011
 
 /* vendor specific classes */
 #define MT_CLS_3M                              0x0101
@@ -144,6 +151,9 @@ static int cypress_compute_slot(struct mt_device *td)
 
 static struct mt_class mt_classes[] = {
        { .name = MT_CLS_DEFAULT,
+               .quirks = MT_QUIRK_ALWAYS_VALID |
+                       MT_QUIRK_CONTACT_CNT_ACCURATE },
+       { .name = MT_CLS_NSMU,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP },
        { .name = MT_CLS_SERIAL,
                .quirks = MT_QUIRK_ALWAYS_VALID},
@@ -170,6 +180,16 @@ static struct mt_class mt_classes[] = {
        { .name = MT_CLS_INRANGE_CONTACTNUMBER,
                .quirks = MT_QUIRK_VALID_IS_INRANGE |
                        MT_QUIRK_SLOT_IS_CONTACTNUMBER },
+       { .name = MT_CLS_DUAL_CONTACT_NUMBER,
+               .quirks = MT_QUIRK_ALWAYS_VALID |
+                       MT_QUIRK_CONTACT_CNT_ACCURATE |
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
+               .maxcontacts = 2 },
+       { .name = MT_CLS_DUAL_CONTACT_ID,
+               .quirks = MT_QUIRK_ALWAYS_VALID |
+                       MT_QUIRK_CONTACT_CNT_ACCURATE |
+                       MT_QUIRK_SLOT_IS_CONTACTID,
+               .maxcontacts = 2 },
 
        /*
         * vendor specific classes
@@ -250,6 +270,9 @@ static ssize_t mt_set_quirks(struct device *dev,
 
        td->mtclass.quirks = val;
 
+       if (td->cc_index < 0)
+               td->mtclass.quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+
        return count;
 }
 
@@ -301,6 +324,7 @@ static void mt_feature_mapping(struct hid_device *hdev,
                        *quirks |= MT_QUIRK_ALWAYS_VALID;
                        *quirks |= MT_QUIRK_IGNORE_DUPLICATES;
                        *quirks |= MT_QUIRK_HOVERING;
+                       *quirks |= MT_QUIRK_CONTACT_CNT_ACCURATE;
                        *quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
                        *quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
                        *quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
@@ -428,6 +452,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        mt_store_field(usage, td, hi);
                        td->last_field_index = field->index;
                        td->touches_by_report++;
+                       td->mt_report_id = field->report->id;
                        return 1;
                case HID_DG_WIDTH:
                        hid_map_usage(hi, usage, bit, max,
@@ -459,6 +484,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTCOUNT:
+                       td->cc_index = field->index;
+                       td->cc_value_index = usage->usage_index;
                        td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTMAX:
@@ -523,6 +550,10 @@ static int mt_compute_slot(struct mt_device *td, struct input_dev *input)
  */
 static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
 {
+       if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
+           td->num_received >= td->num_expected)
+               return;
+
        if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
                int slotnum = mt_compute_slot(td, input);
                struct mt_slot *s = &td->curdata;
@@ -577,6 +608,16 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input)
 
 static int mt_event(struct hid_device *hid, struct hid_field *field,
                                struct hid_usage *usage, __s32 value)
+{
+       /* we will handle the hidinput part later, now remains hiddev */
+       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
+               hid->hiddev_hid_event(hid, field, usage, value);
+
+       return 1;
+}
+
+static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
+                               struct hid_usage *usage, __s32 value)
 {
        struct mt_device *td = hid_get_drvdata(hid);
        __s32 quirks = td->mtclass.quirks;
@@ -623,20 +664,13 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                        td->curdata.h = value;
                        break;
                case HID_DG_CONTACTCOUNT:
-                       /*
-                        * Includes multi-packet support where subsequent
-                        * packets are sent with zero contactcount.
-                        */
-                       if (value)
-                               td->num_expected = value;
                        break;
                case HID_DG_TOUCH:
                        /* do nothing */
                        break;
 
                default:
-                       /* fallback to the generic hidinput handling */
-                       return 0;
+                       return;
                }
 
                if (usage->usage_index + 1 == field->report_count) {
@@ -650,12 +684,43 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
                }
 
        }
+}
 
-       /* we have handled the hidinput part, now remains hiddev */
-       if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
-               hid->hiddev_hid_event(hid, field, usage, value);
+static void mt_report(struct hid_device *hid, struct hid_report *report)
+{
+       struct mt_device *td = hid_get_drvdata(hid);
+       struct hid_field *field;
+       unsigned count;
+       int r, n;
 
-       return 1;
+       if (report->id != td->mt_report_id)
+               return;
+
+       if (!(hid->claimed & HID_CLAIMED_INPUT))
+               return;
+
+       /*
+        * Includes multi-packet support where subsequent
+        * packets are sent with zero contactcount.
+        */
+       if (td->cc_index >= 0) {
+               struct hid_field *field = report->field[td->cc_index];
+               int value = field->value[td->cc_value_index];
+               if (value)
+                       td->num_expected = value;
+       }
+
+       for (r = 0; r < report->maxfield; r++) {
+               field = report->field[r];
+               count = field->report_count;
+
+               if (!(HID_MAIN_ITEM_VARIABLE & field->flags))
+                       continue;
+
+               for (n = 0; n < count; n++)
+                       mt_process_mt_event(hid, field, &field->usage[n],
+                                       field->value[n]);
+       }
 }
 
 static void mt_set_input_mode(struct hid_device *hdev)
@@ -711,6 +776,7 @@ static void mt_post_parse_default_settings(struct mt_device *td)
                quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP;
                quirks &= ~MT_QUIRK_VALID_IS_INRANGE;
                quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE;
+               quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
        }
 
        td->mtclass.quirks = quirks;
@@ -719,11 +785,15 @@ static void mt_post_parse_default_settings(struct mt_device *td)
 static void mt_post_parse(struct mt_device *td)
 {
        struct mt_fields *f = td->fields;
+       struct mt_class *cls = &td->mtclass;
 
        if (td->touches_by_report > 0) {
                int field_count_per_touch = f->length / td->touches_by_report;
                td->last_slot_field = f->usages[field_count_per_touch - 1];
        }
+
+       if (td->cc_index < 0)
+               cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
 }
 
 static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
@@ -781,6 +851,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        td->mtclass = *mtclass;
        td->inputmode = -1;
        td->maxcontact_report_id = -1;
+       td->cc_index = -1;
        hid_set_drvdata(hdev, td);
 
        td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL);
@@ -875,7 +946,7 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_3M3266) },
 
        /* ActionStar panels */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_ACTIONSTAR,
                        USB_DEVICE_ID_ACTIONSTAR_1011) },
 
@@ -888,14 +959,14 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) },
 
        /* Baanto multitouch devices */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_BAANTO,
                        USB_DEVICE_ID_BAANTO_MT_190W2) },
        /* Cando panels */
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH) },
-       { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
+       { .driver_data = MT_CLS_DUAL_CONTACT_NUMBER,
                MT_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH_10_1) },
        { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
@@ -906,12 +977,12 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 
        /* Chunghwa Telecom touch panels */
-       {  .driver_data = MT_CLS_DEFAULT,
+       {  .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
                        USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
 
        /* CVTouch panels */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
                        USB_DEVICE_ID_CVTOUCH_SCREEN) },
 
@@ -982,7 +1053,7 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72C4) },
 
        /* Elo TouchSystems IntelliTouch Plus panel */
-       { .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
+       { .driver_data = MT_CLS_DUAL_CONTACT_ID,
                MT_USB_DEVICE(USB_VENDOR_ID_ELO,
                        USB_DEVICE_ID_ELO_TS2515) },
 
@@ -1000,12 +1071,12 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PWT_TENFINGERS) },
 
        /* Gametel game controller */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_BT_DEVICE(USB_VENDOR_ID_FRUCTEL,
                        USB_DEVICE_ID_GAMETEL_MT_MODE) },
 
        /* GoodTouch panels */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_GOODTOUCH,
                        USB_DEVICE_ID_GOODTOUCH_000f) },
 
@@ -1023,7 +1094,7 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_IDEACOM_IDC6651) },
 
        /* Ilitek dual touch panel */
-       {  .driver_data = MT_CLS_DEFAULT,
+       {  .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
                        USB_DEVICE_ID_ILITEK_MULTITOUCH) },
 
@@ -1056,6 +1127,11 @@ static const struct hid_device_id mt_devices[] = {
                MT_USB_DEVICE(USB_VENDOR_ID_TURBOX,
                        USB_DEVICE_ID_TURBOX_TOUCHSCREEN_MOSART) },
 
+       /* Nexio panels */
+       { .driver_data = MT_CLS_DEFAULT,
+               MT_USB_DEVICE(USB_VENDOR_ID_NEXIO,
+                       USB_DEVICE_ID_NEXIO_MULTITOUCH_420)},
+
        /* Panasonic panels */
        { .driver_data = MT_CLS_PANASONIC,
                MT_USB_DEVICE(USB_VENDOR_ID_PANASONIC,
@@ -1065,7 +1141,7 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_PANABOARD_UBT880) },
 
        /* Novatek Panel */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_NOVATEK,
                        USB_DEVICE_ID_NOVATEK_PCT) },
 
@@ -1111,7 +1187,7 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_CONFIDENCE,
                MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
                        USB_DEVICE_ID_MTP_STM)},
-       { .driver_data = MT_CLS_CONFIDENCE,
+       { .driver_data = MT_CLS_DEFAULT,
                MT_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
                        USB_DEVICE_ID_MTP_SITRONIX)},
 
@@ -1121,48 +1197,48 @@ static const struct hid_device_id mt_devices[] = {
                        USB_DEVICE_ID_TOPSEED2_PERIPAD_701) },
 
        /* Touch International panels */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_TOUCH_INTL,
                        USB_DEVICE_ID_TOUCH_INTL_MULTI_TOUCH) },
 
        /* Unitec panels */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
                        USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_UNITEC,
                        USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) },
        /* XAT */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XAT,
                        USB_DEVICE_ID_XAT_CSR) },
 
        /* Xiroku */
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_SPX) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_MPX) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_CSR) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_SPX1) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_MPX1) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_CSR1) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_SPX2) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_MPX2) },
-       { .driver_data = MT_CLS_DEFAULT,
+       { .driver_data = MT_CLS_NSMU,
                MT_USB_DEVICE(USB_VENDOR_ID_XIROKU,
                        USB_DEVICE_ID_XIROKU_CSR2) },
 
@@ -1193,21 +1269,10 @@ static struct hid_driver mt_driver = {
        .feature_mapping = mt_feature_mapping,
        .usage_table = mt_grabbed_usages,
        .event = mt_event,
+       .report = mt_report,
 #ifdef CONFIG_PM
        .reset_resume = mt_reset_resume,
        .resume = mt_resume,
 #endif
 };
-
-static int __init mt_init(void)
-{
-       return hid_register_driver(&mt_driver);
-}
-
-static void __exit mt_exit(void)
-{
-       hid_unregister_driver(&mt_driver);
-}
-
-module_init(mt_init);
-module_exit(mt_exit);
+module_hid_driver(mt_driver);
index 86a969f..7757e82 100644 (file)
@@ -858,12 +858,43 @@ not_claimed_input:
        return 1;
 }
 
+static void ntrig_input_configured(struct hid_device *hid,
+               struct hid_input *hidinput)
+
+{
+       struct input_dev *input = hidinput->input;
+
+       if (hidinput->report->maxfield < 1)
+               return;
+
+       switch (hidinput->report->field[0]->application) {
+       case HID_DG_PEN:
+               input->name = "N-Trig Pen";
+               break;
+       case HID_DG_TOUCHSCREEN:
+               /* These keys are redundant for fingers, clear them
+                * to prevent incorrect identification */
+               __clear_bit(BTN_TOOL_PEN, input->keybit);
+               __clear_bit(BTN_TOOL_FINGER, input->keybit);
+               __clear_bit(BTN_0, input->keybit);
+               __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
+               /*
+                * The physical touchscreen (single touch)
+                * input has a value for physical, whereas
+                * the multitouch only has logical input
+                * fields.
+                */
+               input->name = (hidinput->report->field[0]->physical) ?
+                                                       "N-Trig Touchscreen" :
+                                                       "N-Trig MultiTouch";
+               break;
+       }
+}
+
 static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
        struct ntrig_data *nd;
-       struct hid_input *hidinput;
-       struct input_dev *input;
        struct hid_report *report;
 
        if (id->driver_data)
@@ -901,38 +932,6 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto err_free;
        }
 
-
-       list_for_each_entry(hidinput, &hdev->inputs, list) {
-               if (hidinput->report->maxfield < 1)
-                       continue;
-
-               input = hidinput->input;
-               switch (hidinput->report->field[0]->application) {
-               case HID_DG_PEN:
-                       input->name = "N-Trig Pen";
-                       break;
-               case HID_DG_TOUCHSCREEN:
-                       /* These keys are redundant for fingers, clear them
-                        * to prevent incorrect identification */
-                       __clear_bit(BTN_TOOL_PEN, input->keybit);
-                       __clear_bit(BTN_TOOL_FINGER, input->keybit);
-                       __clear_bit(BTN_0, input->keybit);
-                       __set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
-                       /*
-                        * The physical touchscreen (single touch)
-                        * input has a value for physical, whereas
-                        * the multitouch only has logical input
-                        * fields.
-                        */
-                       input->name =
-                               (hidinput->report->field[0]
-                                ->physical) ?
-                               "N-Trig Touchscreen" :
-                               "N-Trig MultiTouch";
-                       break;
-               }
-       }
-
        /* This is needed for devices with more recent firmware versions */
        report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
        if (report) {
@@ -1023,20 +1022,10 @@ static struct hid_driver ntrig_driver = {
        .remove = ntrig_remove,
        .input_mapping = ntrig_input_mapping,
        .input_mapped = ntrig_input_mapped,
+       .input_configured = ntrig_input_configured,
        .usage_table = ntrig_grabbed_usages,
        .event = ntrig_event,
 };
+module_hid_driver(ntrig_driver);
 
-static int __init ntrig_init(void)
-{
-       return hid_register_driver(&ntrig_driver);
-}
-
-static void __exit ntrig_exit(void)
-{
-       hid_unregister_driver(&ntrig_driver);
-}
-
-module_init(ntrig_init);
-module_exit(ntrig_exit);
 MODULE_LICENSE("GPL");
index 0ffa1d2..6620f15 100644 (file)
@@ -50,17 +50,6 @@ static struct hid_driver ortek_driver = {
        .id_table = ortek_devices,
        .report_fixup = ortek_report_fixup
 };
+module_hid_driver(ortek_driver);
 
-static int __init ortek_init(void)
-{
-       return hid_register_driver(&ortek_driver);
-}
-
-static void __exit ortek_exit(void)
-{
-       hid_unregister_driver(&ortek_driver);
-}
-
-module_init(ortek_init);
-module_exit(ortek_exit);
 MODULE_LICENSE("GPL");
index 4c521de..736b250 100644 (file)
@@ -103,17 +103,6 @@ static struct hid_driver pl_driver = {
        .input_mapping = pl_input_mapping,
        .probe = pl_probe,
 };
+module_hid_driver(pl_driver);
 
-static int __init pl_init(void)
-{
-       return hid_register_driver(&pl_driver);
-}
-
-static void __exit pl_exit(void)
-{
-       hid_unregister_driver(&pl_driver);
-}
-
-module_init(pl_init);
-module_exit(pl_exit);
 MODULE_LICENSE("GPL");
index 86df26e..31cd93f 100644 (file)
@@ -672,18 +672,7 @@ static struct hid_driver picolcd_driver = {
        .reset_resume =  picolcd_reset_resume,
 #endif
 };
+module_hid_driver(picolcd_driver);
 
-static int __init picolcd_init(void)
-{
-       return hid_register_driver(&picolcd_driver);
-}
-
-static void __exit picolcd_exit(void)
-{
-       hid_unregister_driver(&picolcd_driver);
-}
-
-module_init(picolcd_init);
-module_exit(picolcd_exit);
 MODULE_DESCRIPTION("Minibox graphics PicoLCD Driver");
 MODULE_LICENSE("GPL v2");
index 47ed74c..b0199d2 100644 (file)
@@ -14,6 +14,8 @@
  *  0e8f:0003 "GASIA USB Gamepad"
  *   - another version of the König gamepad
  *
+ *  0f30:0111 "Saitek Color Rumble Pad"
+ *
  *  Copyright (c) 2007, 2009 Anssi Hannula <anssi.hannula@gmail.com>
  */
 
@@ -51,6 +53,7 @@
 
 struct plff_device {
        struct hid_report *report;
+       s32 maxval;
        s32 *strong;
        s32 *weak;
 };
@@ -66,8 +69,8 @@ static int hid_plff_play(struct input_dev *dev, void *data,
        right = effect->u.rumble.weak_magnitude;
        debug("called with 0x%04x 0x%04x", left, right);
 
-       left = left * 0x7f / 0xffff;
-       right = right * 0x7f / 0xffff;
+       left = left * plff->maxval / 0xffff;
+       right = right * plff->maxval / 0xffff;
 
        *plff->strong = left;
        *plff->weak = right;
@@ -87,6 +90,7 @@ static int plff_init(struct hid_device *hid)
        struct list_head *report_ptr = report_list;
        struct input_dev *dev;
        int error;
+       s32 maxval;
        s32 *strong;
        s32 *weak;
 
@@ -123,6 +127,7 @@ static int plff_init(struct hid_device *hid)
                        return -ENODEV;
                }
 
+               maxval = 0x7f;
                if (report->field[0]->report_count >= 4) {
                        report->field[0]->value[0] = 0x00;
                        report->field[0]->value[1] = 0x00;
@@ -135,6 +140,8 @@ static int plff_init(struct hid_device *hid)
                        report->field[1]->value[0] = 0x00;
                        strong = &report->field[2]->value[0];
                        weak = &report->field[3]->value[0];
+                       if (hid->vendor == USB_VENDOR_ID_JESS2)
+                               maxval = 0xff;
                        debug("detected 4-field device");
                } else {
                        hid_err(hid, "not enough fields or values\n");
@@ -158,6 +165,7 @@ static int plff_init(struct hid_device *hid)
                plff->report = report;
                plff->strong = strong;
                plff->weak = weak;
+               plff->maxval = maxval;
 
                *strong = 0x00;
                *weak = 0x00;
@@ -207,6 +215,7 @@ static const struct hid_device_id pl_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_GAMERON, USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR),
                .driver_data = 1 }, /* Twin USB Joystick */
        { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0003), },
+       { HID_USB_DEVICE(USB_VENDOR_ID_JESS2, USB_DEVICE_ID_JESS2_COLOR_RUMBLE_PAD), },
        { }
 };
 MODULE_DEVICE_TABLE(hid, pl_devices);
@@ -216,17 +225,6 @@ static struct hid_driver pl_driver = {
        .id_table = pl_devices,
        .probe = pl_probe,
 };
+module_hid_driver(pl_driver);
 
-static int __init pl_init(void)
-{
-       return hid_register_driver(&pl_driver);
-}
-
-static void __exit pl_exit(void)
-{
-       hid_unregister_driver(&pl_driver);
-}
-
-module_init(pl_init);
-module_exit(pl_exit);
 MODULE_LICENSE("GPL");
index c15adb0..3a1c3c4 100644 (file)
@@ -75,18 +75,7 @@ static struct hid_driver px_driver = {
        .id_table = px_devices,
        .raw_event = px_raw_event,
 };
+module_hid_driver(px_driver);
 
-static int __init px_init(void)
-{
-       return hid_register_driver(&px_driver);
-}
-
-static void __exit px_exit(void)
-{
-       hid_unregister_driver(&px_driver);
-}
-
-module_init(px_init);
-module_exit(px_exit);
 MODULE_AUTHOR("Terry Lambert <tlambert@google.com>");
 MODULE_LICENSE("GPL");
index ec8ca33..4e1c4bc 100644 (file)
@@ -889,23 +889,6 @@ static struct hid_driver pk_driver = {
        .probe = pk_probe,
        .remove = pk_remove,
 };
+module_hid_driver(pk_driver);
 
-static int pk_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&pk_driver);
-       if (ret)
-               pr_err("can't register prodikeys driver\n");
-
-       return ret;
-}
-
-static void pk_exit(void)
-{
-       hid_unregister_driver(&pk_driver);
-}
-
-module_init(pk_init);
-module_exit(pk_exit);
 MODULE_LICENSE("GPL");
index 03811e5..f1239d3 100644 (file)
@@ -198,18 +198,7 @@ static struct hid_driver ps3remote_driver = {
        .report_fixup  = ps3remote_fixup,
        .input_mapping = ps3remote_mapping,
 };
+module_hid_driver(ps3remote_driver);
 
-static int __init ps3remote_init(void)
-{
-       return hid_register_driver(&ps3remote_driver);
-}
-
-static void __exit ps3remote_exit(void)
-{
-       hid_unregister_driver(&ps3remote_driver);
-}
-
-module_init(ps3remote_init);
-module_exit(ps3remote_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>, Antonio Ospite <ospite@studenti.unina.it>");
index 5084fb4..6adc0fa 100644 (file)
@@ -208,19 +208,7 @@ static struct hid_driver lua_driver = {
                .probe = lua_probe,
                .remove = lua_remove
 };
-
-static int __init lua_init(void)
-{
-       return hid_register_driver(&lua_driver);
-}
-
-static void __exit lua_exit(void)
-{
-       hid_unregister_driver(&lua_driver);
-}
-
-module_init(lua_init);
-module_exit(lua_exit);
+module_hid_driver(lua_driver);
 
 MODULE_AUTHOR("Stefan Achatz");
 MODULE_DESCRIPTION("USB Roccat Lua driver");
index 45aea77..37961c7 100644 (file)
@@ -54,17 +54,6 @@ static struct hid_driver saitek_driver = {
        .id_table = saitek_devices,
        .report_fixup = saitek_report_fixup
 };
+module_hid_driver(saitek_driver);
 
-static int __init saitek_init(void)
-{
-       return hid_register_driver(&saitek_driver);
-}
-
-static void __exit saitek_exit(void)
-{
-       hid_unregister_driver(&saitek_driver);
-}
-
-module_init(saitek_init);
-module_exit(saitek_exit);
 MODULE_LICENSE("GPL");
index a5821d3..7cbb067 100644 (file)
@@ -196,17 +196,6 @@ static struct hid_driver samsung_driver = {
        .input_mapping = samsung_input_mapping,
        .probe = samsung_probe,
 };
+module_hid_driver(samsung_driver);
 
-static int __init samsung_init(void)
-{
-       return hid_register_driver(&samsung_driver);
-}
-
-static void __exit samsung_exit(void)
-{
-       hid_unregister_driver(&samsung_driver);
-}
-
-module_init(samsung_init);
-module_exit(samsung_exit);
 MODULE_LICENSE("GPL");
index 7d96db3..6679788 100644 (file)
@@ -623,19 +623,7 @@ static struct hid_driver sensor_hub_driver = {
        .reset_resume =  sensor_hub_reset_resume,
 #endif
 };
-
-static int __init sensor_hub_init(void)
-{
-       return hid_register_driver(&sensor_hub_driver);
-}
-
-static void __exit sensor_hub_exit(void)
-{
-       hid_unregister_driver(&sensor_hub_driver);
-}
-
-module_init(sensor_hub_init);
-module_exit(sensor_hub_exit);
+module_hid_driver(sensor_hub_driver);
 
 MODULE_DESCRIPTION("HID Sensor Hub driver");
 MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
index 42257ac..28f7740 100644 (file)
@@ -177,19 +177,8 @@ static struct hid_driver sjoy_driver = {
        .id_table = sjoy_devices,
        .probe = sjoy_probe,
 };
+module_hid_driver(sjoy_driver);
 
-static int __init sjoy_init(void)
-{
-       return hid_register_driver(&sjoy_driver);
-}
-
-static void __exit sjoy_exit(void)
-{
-       hid_unregister_driver(&sjoy_driver);
-}
-
-module_init(sjoy_init);
-module_exit(sjoy_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jussi Kivilinna");
 
index 7f33ebf..23fc762 100644 (file)
@@ -229,17 +229,6 @@ static struct hid_driver sony_driver = {
        .report_fixup = sony_report_fixup,
        .raw_event = sony_raw_event
 };
+module_hid_driver(sony_driver);
 
-static int __init sony_init(void)
-{
-       return hid_register_driver(&sony_driver);
-}
-
-static void __exit sony_exit(void)
-{
-       hid_unregister_driver(&sony_driver);
-}
-
-module_init(sony_init);
-module_exit(sony_exit);
 MODULE_LICENSE("GPL");
index 6020137..e94371a 100644 (file)
@@ -73,17 +73,6 @@ static struct hid_driver speedlink_driver = {
        .input_mapping = speedlink_input_mapping,
        .event = speedlink_event,
 };
+module_hid_driver(speedlink_driver);
 
-static int __init speedlink_init(void)
-{
-       return hid_register_driver(&speedlink_driver);
-}
-
-static void __exit speedlink_exit(void)
-{
-       hid_unregister_driver(&speedlink_driver);
-}
-
-module_init(speedlink_init);
-module_exit(speedlink_exit);
 MODULE_LICENSE("GPL");
index 45b4b06..87fc91e 100644 (file)
@@ -63,17 +63,6 @@ static struct hid_driver sp_driver = {
        .report_fixup = sp_report_fixup,
        .input_mapping = sp_input_mapping,
 };
+module_hid_driver(sp_driver);
 
-static int __init sp_init(void)
-{
-       return hid_register_driver(&sp_driver);
-}
-
-static void __exit sp_exit(void)
-{
-       hid_unregister_driver(&sp_driver);
-}
-
-module_init(sp_init);
-module_exit(sp_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-thingm.c b/drivers/hid/hid-thingm.c
new file mode 100644 (file)
index 0000000..2055a52
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * ThingM blink(1) USB RGB LED driver
+ *
+ * Copyright 2013 Savoir-faire Linux Inc.
+ *     Vivien Didelot <vivien.didelot@savoirfairelinux.com>
+ *
+ * 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, version 2.
+ */
+
+#include <linux/hid.h>
+#include <linux/leds.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "hid-ids.h"
+
+#define BLINK1_CMD_SIZE                9
+
+#define blink1_rgb_to_r(rgb)   ((rgb & 0xFF0000) >> 16)
+#define blink1_rgb_to_g(rgb)   ((rgb & 0x00FF00) >> 8)
+#define blink1_rgb_to_b(rgb)   ((rgb & 0x0000FF) >> 0)
+
+/**
+ * struct blink1_data - blink(1) device specific data
+ * @hdev:              HID device.
+ * @led_cdev:          LED class instance.
+ * @rgb:               8-bit per channel RGB notation.
+ * @fade:              fade time in hundredths of a second.
+ * @brightness:                brightness coefficient.
+ * @play:              play/pause in-memory patterns.
+ */
+struct blink1_data {
+       struct hid_device *hdev;
+       struct led_classdev led_cdev;
+       u32 rgb;
+       u16 fade;
+       u8 brightness;
+       bool play;
+};
+
+static int blink1_send_command(struct blink1_data *data,
+               u8 buf[BLINK1_CMD_SIZE])
+{
+       int ret;
+
+       hid_dbg(data->hdev, "command: %d%c%.2x%.2x%.2x%.2x%.2x%.2x%.2x\n",
+                       buf[0], buf[1], buf[2], buf[3], buf[4],
+                       buf[5], buf[6], buf[7], buf[8]);
+
+       ret = data->hdev->hid_output_raw_report(data->hdev, buf,
+                       BLINK1_CMD_SIZE, HID_FEATURE_REPORT);
+
+       return ret < 0 ? ret : 0;
+}
+
+static int blink1_update_color(struct blink1_data *data)
+{
+       u8 buf[BLINK1_CMD_SIZE] = { 1, 'n', 0, 0, 0, 0, 0, 0, 0 };
+
+       if (data->brightness) {
+               unsigned int coef = DIV_ROUND_CLOSEST(255, data->brightness);
+
+               buf[2] = DIV_ROUND_CLOSEST(blink1_rgb_to_r(data->rgb), coef);
+               buf[3] = DIV_ROUND_CLOSEST(blink1_rgb_to_g(data->rgb), coef);
+               buf[4] = DIV_ROUND_CLOSEST(blink1_rgb_to_b(data->rgb), coef);
+       }
+
+       if (data->fade) {
+               buf[1] = 'c';
+               buf[5] = (data->fade & 0xFF00) >> 8;
+               buf[6] = (data->fade & 0x00FF);
+       }
+
+       return blink1_send_command(data, buf);
+}
+
+static void blink1_led_set(struct led_classdev *led_cdev,
+               enum led_brightness brightness)
+{
+       struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent);
+
+       data->brightness = brightness;
+       if (blink1_update_color(data))
+               hid_err(data->hdev, "failed to update color\n");
+}
+
+static enum led_brightness blink1_led_get(struct led_classdev *led_cdev)
+{
+       struct blink1_data *data = dev_get_drvdata(led_cdev->dev->parent);
+
+       return data->brightness;
+}
+
+static ssize_t blink1_show_rgb(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+
+       return sprintf(buf, "%.6X\n", data->rgb);
+}
+
+static ssize_t blink1_store_rgb(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+       long unsigned int rgb;
+       int ret;
+
+       ret = kstrtoul(buf, 16, &rgb);
+       if (ret)
+               return ret;
+
+       /* RGB triplet notation is 24-bit hexadecimal */
+       if (rgb > 0xFFFFFF)
+               return -EINVAL;
+
+       data->rgb = rgb;
+       ret = blink1_update_color(data);
+
+       return ret ? ret : count;
+}
+
+static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR, blink1_show_rgb, blink1_store_rgb);
+
+static ssize_t blink1_show_fade(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+
+       return sprintf(buf, "%d\n", data->fade * 10);
+}
+
+static ssize_t blink1_store_fade(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+       long unsigned int fade;
+       int ret;
+
+       ret = kstrtoul(buf, 10, &fade);
+       if (ret)
+               return ret;
+
+       /* blink(1) accepts 16-bit fade time, number of 10ms ticks */
+       fade = DIV_ROUND_CLOSEST(fade, 10);
+       if (fade > 65535)
+               return -EINVAL;
+
+       data->fade = fade;
+
+       return count;
+}
+
+static DEVICE_ATTR(fade, S_IRUGO | S_IWUSR,
+               blink1_show_fade, blink1_store_fade);
+
+static ssize_t blink1_show_play(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+
+       return sprintf(buf, "%d\n", data->play);
+}
+
+static ssize_t blink1_store_play(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct blink1_data *data = dev_get_drvdata(dev->parent);
+       u8 cmd[BLINK1_CMD_SIZE] = { 1, 'p', 0, 0, 0, 0, 0, 0, 0 };
+       long unsigned int play;
+       int ret;
+
+       ret = kstrtoul(buf, 10, &play);
+       if (ret)
+               return ret;
+
+       data->play = !!play;
+       cmd[2] = data->play;
+       ret = blink1_send_command(data, cmd);
+
+       return ret ? ret : count;
+}
+
+static DEVICE_ATTR(play, S_IRUGO | S_IWUSR,
+               blink1_show_play, blink1_store_play);
+
+static const struct attribute_group blink1_sysfs_group = {
+       .attrs = (struct attribute *[]) {
+               &dev_attr_rgb.attr,
+               &dev_attr_fade.attr,
+               &dev_attr_play.attr,
+               NULL
+       },
+};
+
+static int thingm_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+       struct blink1_data *data;
+       struct led_classdev *led;
+       char led_name[13];
+       int ret;
+
+       data = devm_kzalloc(&hdev->dev, sizeof(struct blink1_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       hid_set_drvdata(hdev, data);
+       data->hdev = hdev;
+       data->rgb = 0xFFFFFF; /* set a default white color */
+
+       ret = hid_parse(hdev);
+       if (ret)
+               goto error;
+
+       ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+       if (ret)
+               goto error;
+
+       /* blink(1) serial numbers range is 0x1A001000 to 0x1A002FFF */
+       led = &data->led_cdev;
+       snprintf(led_name, sizeof(led_name), "blink1::%s", hdev->uniq + 4);
+       led->name = led_name;
+       led->brightness_set = blink1_led_set;
+       led->brightness_get = blink1_led_get;
+       ret = led_classdev_register(&hdev->dev, led);
+       if (ret)
+               goto stop;
+
+       ret = sysfs_create_group(&led->dev->kobj, &blink1_sysfs_group);
+       if (ret)
+               goto remove_led;
+
+       return 0;
+
+remove_led:
+       led_classdev_unregister(led);
+stop:
+       hid_hw_stop(hdev);
+error:
+       return ret;
+}
+
+static void thingm_remove(struct hid_device *hdev)
+{
+       struct blink1_data *data = hid_get_drvdata(hdev);
+       struct led_classdev *led = &data->led_cdev;
+
+       sysfs_remove_group(&led->dev->kobj, &blink1_sysfs_group);
+       led_classdev_unregister(led);
+       hid_hw_stop(hdev);
+}
+
+static const struct hid_device_id thingm_table[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_THINGM, USB_DEVICE_ID_BLINK1) },
+       { }
+};
+MODULE_DEVICE_TABLE(hid, thingm_table);
+
+static struct hid_driver thingm_driver = {
+       .name = "thingm",
+       .probe = thingm_probe,
+       .remove = thingm_remove,
+       .id_table = thingm_table,
+};
+
+module_hid_driver(thingm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Vivien Didelot <vivien.didelot@savoirfairelinux.com>");
+MODULE_DESCRIPTION("ThingM blink(1) USB RGB LED driver");
index 9f85f82..d790d8d 100644 (file)
@@ -73,18 +73,7 @@ static struct hid_driver tivo_driver = {
        .id_table = tivo_devices,
        .input_mapping = tivo_input_mapping,
 };
+module_hid_driver(tivo_driver);
 
-static int __init tivo_init(void)
-{
-       return hid_register_driver(&tivo_driver);
-}
-
-static void __exit tivo_exit(void)
-{
-       hid_unregister_driver(&tivo_driver);
-}
-
-module_init(tivo_init);
-module_exit(tivo_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
index 83a933b..e4fcf3f 100644 (file)
@@ -261,17 +261,6 @@ static struct hid_driver tm_driver = {
        .id_table = tm_devices,
        .probe = tm_probe,
 };
+module_hid_driver(tm_driver);
 
-static int __init tm_init(void)
-{
-       return hid_register_driver(&tm_driver);
-}
-
-static void __exit tm_exit(void)
-{
-       hid_unregister_driver(&tm_driver);
-}
-
-module_init(tm_init);
-module_exit(tm_exit);
 MODULE_LICENSE("GPL");
index 613ff7b..8a5b843 100644 (file)
@@ -76,17 +76,6 @@ static struct hid_driver ts_driver = {
        .id_table = ts_devices,
        .input_mapping = ts_input_mapping,
 };
+module_hid_driver(ts_driver);
 
-static int __init ts_init(void)
-{
-       return hid_register_driver(&ts_driver);
-}
-
-static void __exit ts_exit(void)
-{
-       hid_unregister_driver(&ts_driver);
-}
-
-module_init(ts_init);
-module_exit(ts_exit);
 MODULE_LICENSE("GPL");
index f23456b..c08c364 100644 (file)
@@ -131,17 +131,6 @@ static struct hid_driver twinhan_driver = {
        .id_table = twinhan_devices,
        .input_mapping = twinhan_input_mapping,
 };
+module_hid_driver(twinhan_driver);
 
-static int __init twinhan_init(void)
-{
-       return hid_register_driver(&twinhan_driver);
-}
-
-static void __exit twinhan_exit(void)
-{
-       hid_unregister_driver(&twinhan_driver);
-}
-
-module_init(twinhan_init);
-module_exit(twinhan_exit);
 MODULE_LICENSE("GPL");
index 2e56a1f..fb8b516 100644 (file)
@@ -650,17 +650,6 @@ static struct hid_driver uclogic_driver = {
        .id_table = uclogic_devices,
        .report_fixup = uclogic_report_fixup,
 };
+module_hid_driver(uclogic_driver);
 
-static int __init uclogic_init(void)
-{
-       return hid_register_driver(&uclogic_driver);
-}
-
-static void __exit uclogic_exit(void)
-{
-       hid_unregister_driver(&uclogic_driver);
-}
-
-module_init(uclogic_init);
-module_exit(uclogic_exit);
 MODULE_LICENSE("GPL");
index 2f60da9..a4a8bb0 100644 (file)
@@ -953,23 +953,7 @@ static struct hid_driver wacom_driver = {
        .raw_event = wacom_raw_event,
        .input_mapped = wacom_input_mapped,
 };
+module_hid_driver(wacom_driver);
 
-static int __init wacom_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&wacom_driver);
-       if (ret)
-               pr_err("can't register wacom driver\n");
-       return ret;
-}
-
-static void __exit wacom_exit(void)
-{
-       hid_unregister_driver(&wacom_driver);
-}
-
-module_init(wacom_init);
-module_exit(wacom_exit);
 MODULE_DESCRIPTION("Driver for Wacom Graphire Bluetooth and Wacom Intuos4 WL");
 MODULE_LICENSE("GPL");
index bb536ab..059931d 100644 (file)
@@ -779,17 +779,6 @@ static struct hid_driver waltop_driver = {
        .report_fixup = waltop_report_fixup,
        .raw_event = waltop_raw_event,
 };
+module_hid_driver(waltop_driver);
 
-static int __init waltop_init(void)
-{
-       return hid_register_driver(&waltop_driver);
-}
-
-static void __exit waltop_exit(void)
-{
-       hid_unregister_driver(&waltop_driver);
-}
-
-module_init(waltop_init);
-module_exit(waltop_exit);
 MODULE_LICENSE("GPL");
index 84e2fbe..0fb8ab9 100644 (file)
@@ -1294,25 +1294,8 @@ static struct hid_driver wiimote_hid_driver = {
        .remove = wiimote_hid_remove,
        .raw_event = wiimote_hid_event,
 };
+module_hid_driver(wiimote_hid_driver);
 
-static int __init wiimote_init(void)
-{
-       int ret;
-
-       ret = hid_register_driver(&wiimote_hid_driver);
-       if (ret)
-               pr_err("Can't register wiimote hid driver\n");
-
-       return ret;
-}
-
-static void __exit wiimote_exit(void)
-{
-       hid_unregister_driver(&wiimote_hid_driver);
-}
-
-module_init(wiimote_init);
-module_exit(wiimote_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
 MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver");
index eec3291..90124ff 100644 (file)
@@ -31,7 +31,7 @@ static ssize_t wiidebug_eeprom_read(struct file *f, char __user *u, size_t s,
        unsigned long flags;
        ssize_t ret;
        char buf[16];
-       __u16 size;
+       __u16 size = 0;
 
        if (s == 0)
                return -EINVAL;
index 38ae877..0472191 100644 (file)
@@ -403,14 +403,14 @@ static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload)
 
        if (ext->motionp) {
                input_report_key(ext->input,
-                       wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04));
+                       wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04));
                input_report_key(ext->input,
-                       wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08));
+                       wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08));
        } else {
                input_report_key(ext->input,
-                       wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01));
+                       wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01));
                input_report_key(ext->input,
-                       wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02));
+                       wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02));
        }
 
        input_sync(ext->input);
index f6ba81d..af66452 100644 (file)
@@ -152,17 +152,6 @@ static struct hid_driver zp_driver = {
        .id_table = zp_devices,
        .probe = zp_probe,
 };
+module_hid_driver(zp_driver);
 
-static int __init zp_init(void)
-{
-       return hid_register_driver(&zp_driver);
-}
-
-static void __exit zp_exit(void)
-{
-       hid_unregister_driver(&zp_driver);
-}
-
-module_init(zp_init);
-module_exit(zp_exit);
 MODULE_LICENSE("GPL");
index 1ad85f2..e4cddec 100644 (file)
@@ -219,17 +219,6 @@ static struct hid_driver zc_driver = {
        .probe = zc_probe,
        .remove = zc_remove,
 };
+module_hid_driver(zc_driver);
 
-static int __init zc_init(void)
-{
-       return hid_register_driver(&zc_driver);
-}
-
-static void __exit zc_exit(void)
-{
-       hid_unregister_driver(&zc_driver);
-}
-
-module_init(zc_init);
-module_exit(zc_exit);
 MODULE_LICENSE("GPL");
index 7330a0f..e14b465 100644 (file)
@@ -589,6 +589,7 @@ struct hid_usage_id {
  * @raw_event: if report in report_table, this hook is called (NULL means nop)
  * @usage_table: on which events to call event (NULL means all)
  * @event: if usage in usage_table, this hook is called (NULL means nop)
+ * @report: this hook is called after parsing a report (NULL means nop)
  * @report_fixup: called before report descriptor parsing (NULL means nop)
  * @input_mapping: invoked on input registering before mapping an usage
  * @input_mapped: invoked on input registering after mapping an usage
@@ -627,6 +628,7 @@ struct hid_driver {
        const struct hid_usage_id *usage_table;
        int (*event)(struct hid_device *hdev, struct hid_field *field,
                        struct hid_usage *usage, __s32 value);
+       void (*report)(struct hid_device *hdev, struct hid_report *report);
 
        __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf,
                        unsigned int *size);
@@ -700,6 +702,18 @@ extern int __must_check __hid_register_driver(struct hid_driver *,
 
 extern void hid_unregister_driver(struct hid_driver *);
 
+/**
+ * module_hid_driver() - Helper macro for registering a HID driver
+ * @__hid_driver: hid_driver struct
+ *
+ * Helper macro for HID drivers which do not do anything special in module
+ * init/exit. This eliminates a lot of boilerplate. Each module may only
+ * use this macro once, and calling it replaces module_init() and module_exit()
+ */
+#define module_hid_driver(__hid_driver) \
+       module_driver(__hid_driver, hid_register_driver, \
+                     hid_unregister_driver)
+
 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report);
 extern int hidinput_connect(struct hid_device *hid, unsigned int force);
@@ -872,9 +886,6 @@ static inline int hid_hw_power(struct hid_device *hdev, int level)
 int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size,
                int interrupt);
 
-extern int hid_generic_init(void);
-extern void hid_generic_exit(void);
-
 /* HID quirks API */
 u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct);
 int usbhid_quirks_init(char **quirks_param);
index 9c6974f..e9ed951 100644 (file)
@@ -86,7 +86,7 @@ struct uhid_feature_answer_req {
        __u16 err;
        __u16 size;
        __u8 data[UHID_DATA_MAX];
-};
+} __attribute__((__packed__));
 
 struct uhid_event {
        __u32 type;