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)
68 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-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
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/uhid.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 212c255b93472ada8cba2016b014eea3b7aa8369..833897c4ec962b8bfd8cab59a356e0382d8994ea 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 e7d6a13ec6a623ab1d4123d80a4aae37bb76aaa9..3d5294531ba5e348289510627223b00deb8e5945 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 b62215716b2fd66fda16b0084f077927a8c3f02f..93017043f6f8a6e5257d1a7be0be45db02559f81 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 0a239885e67cb77e8fd40564610dfb4afc06d8d9..7c5507e94820cc93b8867884dad993244431668a 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 d0f7662aacca05caf3596c9edcc8280dfed675e6..320a958d4139ce57fc386087a93bffa23054d13f 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 7968187ddf7b8c5834f1a7aa2b0139de451ef82a..340ba9d394a09045949c0adc26dc4839c589a65f 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 5be858dd9a158b004844a0a4ebc93351c1a58965..62f0cee032bada140bdcfcd84418c366c54c6015 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 a1a5a12c3a6b9fc3e772e939908120389c069694..cc4cf138bef59fb02a8f316561b10a903975a735 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 af034d3d925663200b8c08356a4e2e2c178e3892..1bdcccc54a1dda0e04d16fc9fbfe2d3d8e1e22b2 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 a2abb8e15727dfd3f0e0d37734e95096ff8c9db8..b613d5a7968457b5719acaf57d9c0bc98b47ed29 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 eb2ee11b6412ac43e9baa08596b881d92c8430e3..6e904155ded51332e1852a0f60ced082012847ee 100644 (file)
@@ -729,7 +729,7 @@ static int hid_scan_report(struct hid_device *hid)
                        item.type == HID_ITEM_TYPE_MAIN &&
                        item.tag == HID_MAIN_ITEM_TAG_BEGIN_COLLECTION &&
                        (item_udata(&item) & 0xff) == HID_COLLECTION_PHYSICAL &&
-                       hid->bus == BUS_USB)
+                       (hid->bus == BUS_USB || hid->bus == BUS_I2C))
                        hid->group = HID_GROUP_SENSOR_HUB;
        }
 
@@ -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 3e159a50dac724e1c974e32ea14b8a83e75153fb..c4ef3bc726e34e5e08aa947b64ddfa4dc7f772b0 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 e832f44ae38391ae05ba88879d0b6189371d51dd..0fe8f65ef01a64c7d68155946498a28acbeaf63e 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 79d0c61e7214a0057ce03b781bb8b40c6cbaaf16..d0bd13b62dc2dc542868262a6c38ab6d1c47b8f1 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 2630d483d2623a08eaf357fe41bef4bd29b7aaf0..2e093ab99b435885c1f4d0ba5c6511ffe64993b9 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 6540af2871a79a345a818f5703d052fa9b0e65a0..212ac6be24512ae97592ee1d706d5085107dc854 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 f1e1bcf674270d3f7c90cd41be3c21e50ff369a7..04d2e6aca77841983ba16bce0d1b312f2fb2e1bc 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 a8b3148e03a263bf4750be4ee803f6233ba304b9..e288a4a06fe89a5969dfd6bcf59b38fb673e1213 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 4442c30ef531d33182e4ad6461ad8f309727e99e..288d61c9748ecc5cfb00e419bb742582ce8a690a 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 e0a5d1739fc38ae5707fc9deff77d8e62ffde958..6e1a4a4fc0c109f7bf60083963d8c239a10939cf 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 ff295e60059b25e8d49d3fa31881decda3b0014c..f34d1186a3e1b16b4604c5f057ab411cff1bcc2f 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 1d6565e37ba3d2e0cae21c79f1056525581575d9..09dcc04595f35c7798b68aed97fdf79f64947328 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 865492c8b0e0c24ab6ed13e65b24007e80d8a6af..d15ed561136cb948f3889e2dbe52c07afaf56ff8 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_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 a5b4016e9bd7b54d34543048d9d7344bbb66704d..fe9a99dd8d0875bc7f0c42741acdb0c7fae0f4b2 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 07cd825f6f018c9799e71dea19343a1012c2d17c..3074671b7d6abb3d6ba9ac335e97e6468888aa06 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 b4f0d8216fd099bd69a2531600c02a241c42929f..ef72daecfa16337aa66b2a712d6c64457d4db777 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 22bc14abdfa3d23e0f187d0cf8eb2efb7cef223f..6424cfdb773708e51294644bece1b7e1fefe3216 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 cea016e94f43e336ec1a4d73eb2cbbdba9e1ace7..956c3b135f64fe61e4a4636e2e81e911ad3ee141 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 5d3c861e2c5bce104b02732497d81ae026d1b2aa..6f12ecd36c8834fa9c9cb77b79d883dd4c246dc8 100644 (file)
@@ -674,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 25ddf3e3aec641fd4d883843e87e59bc0e3b0c51..f7f113ba083eb43fb1073d189a4979f7d4d6d724 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 6fcd466d082512f675d027aafd7600eb34edebaf..29d27f65a1184b55cf40c8ca3c0940a5548d8324 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 cd3643e06fa657f4735b3f1e76a6fd95d59549ed..9e14c00eb1b6bb105ffd1326dc802183cfeb9a1a 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 61543c02ea0baf42c58fbfa5518dba229cb22901..7a1ebb867cf499596e9c4fe5b1a43860b86d4351 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 86a969f6329297f9b34c9866b1bb39c5a0c85638..7757e82416e7f2270a1ebba2ef44070161424985 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 0ffa1d2d64f0b8fe0c8e9931b6afc86ddd866397..6620f15fec228a21ccf6f1b12a5e7dfd7b73046d 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 4c521de4e7e646f913e2db76fc76645ecc56771a..736b2502df4f8b00473889f6abf0ac78dcf72fe3 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 86df26e58abac65f671601b70f15085faa4fdece..31cd93fc3d4bff26fb0275d102c90270483289e7 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 47ed74c46b6be73f8ce2001265dc783f21bc4ed9..b0199d27787b69a328d09488e5802f6e51b781a2 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 c15adb0c98a1d9a74475988360bc0182f63462e6..3a1c3c4c50dce62d1032ffe682aa66a849111171 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 ec8ca3336315ecd373a5eecdad4da847fa46c01f..4e1c4bcbdc039763ce170dbb7913bd56fd003d4d 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 03811e539d71db9187ac4124e7b9027aca94a6bf..f1239d3c5b140d27eee9b64587fbc36fcee3e331 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 5084fb4b7e91ac3921a2c78edfb94684d9eedd45..6adc0fa08d96fc57fcb6d078ca9ca18c08415801 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 45aea77bb611fda8dc07a0a3c4759dd54e783032..37961c7e397d8a0dcbdb1bcd0409a2defe33bd4c 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 a5821d31722932a1df634343421b562f05d93d20..7cbb067d4a9e399f62b57b54830d384956037cbc 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 0bc58bd8d4f5a9e496187310326aff7e031e74f0..6679788bf75ac0b93126de3b7cac920289c618bb 100644 (file)
@@ -605,16 +605,12 @@ static void sensor_hub_remove(struct hid_device *hdev)
 }
 
 static const struct hid_device_id sensor_hub_devices[] = {
-       { HID_DEVICE(BUS_USB, HID_GROUP_SENSOR_HUB, HID_ANY_ID, HID_ANY_ID) },
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
+                    HID_ANY_ID) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, sensor_hub_devices);
 
-static const struct hid_usage_id sensor_hub_grabbed_usages[] = {
-       { HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
-       { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1 }
-};
-
 static struct hid_driver sensor_hub_driver = {
        .name = "hid-sensor-hub",
        .id_table = sensor_hub_devices,
@@ -627,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 42257acfeb73fba84c2912db29f337a63ab0c706..28f774003f0381a97c58df8ab44ad11393a14d91 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 7f33ebf299c220fae74806f2d3aa44dd73c2507a..23fc762e8633e06a4298fb9bb06d1439a4046a49 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 602013741718c7c420759cc0f885a34318d9aa77..e94371a059cb3b65f53580d83f5dc40e51ee493c 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 45b4b066a2621dced695d55d7fd79462de4c5f0a..87fc91e1c8de4980d2f8e8721f476b6d21959adf 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 9f85f827607fd6fca72b03152ca7a51b061ec82c..d790d8d71f7fc6829f405b7665cc37f0af1bf5a8 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 83a933b9c2e98163004c7c6dc999133196375840..e4fcf3f702a519b95fdc9ca8ea73d1d80a777c42 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 613ff7b1d746a0d51d56dca6e17e2cc2e0e1e7dc..8a5b843e9dd6f904618ff790c872d48ff07a2aea 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 f23456b1fd4b6ff204f4d2077bbbc2700902942d..c08c36443f833dc5aa7e11385e628dc4e385fcf0 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 2e56a1fd2375ea2f73fb35ef109b077d989a0d58..fb8b516ff0ed5f7693912ece34c4ff372d3918fa 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 2f60da9ed066539a5b4c2e479118ec0763a1b9f0..a4a8bb0da688199e9f19a3bcc8e5d0737d5bdb27 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 bb536ab5941e413a7cbb624ef019d73aec847197..059931d7b3922ff064ea0f59b63f2d9b8d9ff745 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 84e2fbec5fbb8ecb84c5139766caafdcc8cc53af..0fb8ab93db68e275091a49462bd0bd40a356dded 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 eec329197c160e6739ccf1cbb0a24adc766b15ee..90124ffaa2a5211f3e7e11ec7c4a21aedd18b054 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 38ae87772e96d18144a5b2e256192fd67b4bde55..0472191d4a7272dff8ea9709aef2e7814dd6be2a 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 f6ba81df71bdedfe7b721c7e12970992fb1c53b0..af66452592e963c8a5e91f17921e166e50699800 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 1ad85f2257b4b46d4c48cd49f883fa95634c17e7..e4cddeccd6b51691bffc955a62569ead5e6d480e 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 413a73187d33d9f0313444f8c20288408cd001b9..f3bbbce8353b73990daa4a7a040904730bf659f0 100644 (file)
@@ -581,6 +581,7 @@ int __init hidraw_init(void)
        if (result < 0)
                goto error_class;
 
+       printk(KERN_INFO "hidraw: raw HID events driver (C) Jiri Kosina\n");
 out:
        return result;
 
index e766b5614ef59fcae45aaeff49a98df9de3e9693..ec7930217a6dff1fceb15b1a445ec0462cb47b82 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/hid.h>
 #include <linux/mutex.h>
+#include <linux/acpi.h>
 
 #include <linux/i2c/i2c-hid.h>
 
@@ -139,6 +140,8 @@ struct i2c_hid {
        unsigned long           flags;          /* device flags */
 
        wait_queue_head_t       wait;           /* For waiting the interrupt */
+
+       struct i2c_hid_platform_data pdata;
 };
 
 static int __i2c_hid_command(struct i2c_client *client,
@@ -821,6 +824,70 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
        return 0;
 }
 
+#ifdef CONFIG_ACPI
+static int i2c_hid_acpi_pdata(struct i2c_client *client,
+               struct i2c_hid_platform_data *pdata)
+{
+       static u8 i2c_hid_guid[] = {
+               0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
+               0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
+       };
+       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object params[4], *obj;
+       struct acpi_object_list input;
+       struct acpi_device *adev;
+       acpi_handle handle;
+
+       handle = ACPI_HANDLE(&client->dev);
+       if (!handle || acpi_bus_get_device(handle, &adev))
+               return -ENODEV;
+
+       input.count = ARRAY_SIZE(params);
+       input.pointer = params;
+
+       params[0].type = ACPI_TYPE_BUFFER;
+       params[0].buffer.length = sizeof(i2c_hid_guid);
+       params[0].buffer.pointer = i2c_hid_guid;
+       params[1].type = ACPI_TYPE_INTEGER;
+       params[1].integer.value = 1;
+       params[2].type = ACPI_TYPE_INTEGER;
+       params[2].integer.value = 1; /* HID function */
+       params[3].type = ACPI_TYPE_INTEGER;
+       params[3].integer.value = 0;
+
+       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) {
+               dev_err(&client->dev, "device _DSM execution failed\n");
+               return -ENODEV;
+       }
+
+       obj = (union acpi_object *)buf.pointer;
+       if (obj->type != ACPI_TYPE_INTEGER) {
+               dev_err(&client->dev, "device _DSM returned invalid type: %d\n",
+                       obj->type);
+               kfree(buf.pointer);
+               return -EINVAL;
+       }
+
+       pdata->hid_descriptor_address = obj->integer.value;
+
+       kfree(buf.pointer);
+       return 0;
+}
+
+static const struct acpi_device_id i2c_hid_acpi_match[] = {
+       {"ACPI0C50", 0 },
+       {"PNP0C50", 0 },
+       { },
+};
+MODULE_DEVICE_TABLE(acpi, i2c_hid_acpi_match);
+#else
+static inline int i2c_hid_acpi_pdata(struct i2c_client *client,
+               struct i2c_hid_platform_data *pdata)
+{
+       return -ENODEV;
+}
+#endif
+
 static int i2c_hid_probe(struct i2c_client *client,
                         const struct i2c_device_id *dev_id)
 {
@@ -832,11 +899,6 @@ static int i2c_hid_probe(struct i2c_client *client,
 
        dbg_hid("HID probe called for i2c 0x%02x\n", client->addr);
 
-       if (!platform_data) {
-               dev_err(&client->dev, "HID register address not provided\n");
-               return -EINVAL;
-       }
-
        if (!client->irq) {
                dev_err(&client->dev,
                        "HID over i2c has not been provided an Int IRQ\n");
@@ -847,11 +909,22 @@ static int i2c_hid_probe(struct i2c_client *client,
        if (!ihid)
                return -ENOMEM;
 
+       if (!platform_data) {
+               ret = i2c_hid_acpi_pdata(client, &ihid->pdata);
+               if (ret) {
+                       dev_err(&client->dev,
+                               "HID register address not provided\n");
+                       goto err;
+               }
+       } else {
+               ihid->pdata = *platform_data;
+       }
+
        i2c_set_clientdata(client, ihid);
 
        ihid->client = client;
 
-       hidRegister = platform_data->hid_descriptor_address;
+       hidRegister = ihid->pdata.hid_descriptor_address;
        ihid->wHIDDescRegister = cpu_to_le16(hidRegister);
 
        init_waitqueue_head(&ihid->wait);
@@ -884,6 +957,7 @@ static int i2c_hid_probe(struct i2c_client *client,
        hid->hid_get_raw_report = i2c_hid_get_raw_report;
        hid->hid_output_raw_report = i2c_hid_output_raw_report;
        hid->dev.parent = &client->dev;
+       ACPI_HANDLE_SET(&hid->dev, ACPI_HANDLE(&client->dev));
        hid->bus = BUS_I2C;
        hid->version = le16_to_cpu(ihid->hdesc.bcdVersion);
        hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID);
@@ -975,6 +1049,7 @@ static struct i2c_driver i2c_hid_driver = {
                .name   = "i2c_hid",
                .owner  = THIS_MODULE,
                .pm     = &i2c_hid_pm,
+               .acpi_match_table = ACPI_PTR(i2c_hid_acpi_match),
        },
 
        .probe          = i2c_hid_probe,
index 714cd8cc9579b6cd3c71b8a2aebb140e089f27e6..fc307e0422afc92c31bfac65d410244d5859e804 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/atomic.h>
+#include <linux/compat.h>
 #include <linux/device.h>
 #include <linux/fs.h>
 #include <linux/hid.h>
@@ -276,6 +277,94 @@ static struct hid_ll_driver uhid_hid_driver = {
        .parse = uhid_hid_parse,
 };
 
+#ifdef CONFIG_COMPAT
+
+/* Apparently we haven't stepped on these rakes enough times yet. */
+struct uhid_create_req_compat {
+       __u8 name[128];
+       __u8 phys[64];
+       __u8 uniq[64];
+
+       compat_uptr_t rd_data;
+       __u16 rd_size;
+
+       __u16 bus;
+       __u32 vendor;
+       __u32 product;
+       __u32 version;
+       __u32 country;
+} __attribute__((__packed__));
+
+static int uhid_event_from_user(const char __user *buffer, size_t len,
+                               struct uhid_event *event)
+{
+       if (is_compat_task()) {
+               u32 type;
+
+               if (get_user(type, buffer))
+                       return -EFAULT;
+
+               if (type == UHID_CREATE) {
+                       /*
+                        * This is our messed up request with compat pointer.
+                        * It is largish (more than 256 bytes) so we better
+                        * allocate it from the heap.
+                        */
+                       struct uhid_create_req_compat *compat;
+
+                       compat = kmalloc(sizeof(*compat), GFP_KERNEL);
+                       if (!compat)
+                               return -ENOMEM;
+
+                       buffer += sizeof(type);
+                       len -= sizeof(type);
+                       if (copy_from_user(compat, buffer,
+                                          min(len, sizeof(*compat)))) {
+                               kfree(compat);
+                               return -EFAULT;
+                       }
+
+                       /* Shuffle the data over to proper structure */
+                       event->type = type;
+
+                       memcpy(event->u.create.name, compat->name,
+                               sizeof(compat->name));
+                       memcpy(event->u.create.phys, compat->phys,
+                               sizeof(compat->phys));
+                       memcpy(event->u.create.uniq, compat->uniq,
+                               sizeof(compat->uniq));
+
+                       event->u.create.rd_data = compat_ptr(compat->rd_data);
+                       event->u.create.rd_size = compat->rd_size;
+
+                       event->u.create.bus = compat->bus;
+                       event->u.create.vendor = compat->vendor;
+                       event->u.create.product = compat->product;
+                       event->u.create.version = compat->version;
+                       event->u.create.country = compat->country;
+
+                       kfree(compat);
+                       return 0;
+               }
+               /* All others can be copied directly */
+       }
+
+       if (copy_from_user(event, buffer, min(len, sizeof(*event))))
+               return -EFAULT;
+
+       return 0;
+}
+#else
+static int uhid_event_from_user(const char __user *buffer, size_t len,
+                               struct uhid_event *event)
+{
+       if (copy_from_user(event, buffer, min(len, sizeof(*event))))
+               return -EFAULT;
+
+       return 0;
+}
+#endif
+
 static int uhid_dev_create(struct uhid_device *uhid,
                           const struct uhid_event *ev)
 {
@@ -498,10 +587,10 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
 
        memset(&uhid->input_buf, 0, sizeof(uhid->input_buf));
        len = min(count, sizeof(uhid->input_buf));
-       if (copy_from_user(&uhid->input_buf, buffer, len)) {
-               ret = -EFAULT;
+
+       ret = uhid_event_from_user(buffer, len, &uhid->input_buf);
+       if (ret)
                goto unlock;
-       }
 
        switch (uhid->input_buf.type) {
        case UHID_CREATE:
index 7330a0fef0c073b41a409882145eb36add87dc02..e14b465b11463d353553027e602d79499d8be01d 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 9c6974f169661d6495069e15018dad33a5b237f5..e9ed951e2b09c11bd010520e5ff0119b201ae1c9 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;