]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'hid/for-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 00:33:15 +0000 (11:33 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 00:33:15 +0000 (11:33 +1100)
42 files changed:
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-arvo [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo with 100% similarity]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-isku [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-isku with 100% similarity]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-konepure [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure with 100% similarity]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-lua [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-lua with 100% similarity]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-ryos [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos with 100% similarity]
Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu [moved from Documentation/ABI/testing/sysfs-driver-hid-roccat-savu with 100% similarity]
Documentation/ABI/testing/sysfs-driver-hid-corsair [new file with mode: 0644]
Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus [deleted file]
Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus [deleted file]
Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra [deleted file]
drivers/hid/Kconfig
drivers/hid/Makefile
drivers/hid/hid-appleir.c
drivers/hid/hid-aureal.c
drivers/hid/hid-core.c
drivers/hid/hid-corsair.c [new file with mode: 0644]
drivers/hid/hid-dr.c
drivers/hid/hid-elecom.c
drivers/hid/hid-elo.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-lenovo.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-magicmouse.c
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-ntrig.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-rmi.c
drivers/hid/hid-saitek.c
drivers/hid/hid-sensor-hub.c
drivers/hid/hid-sony.c
drivers/hid/hid-uclogic.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h
include/linux/hid.h

index 833fd59926a73c1f3725559400b60b598f2446fa..545e69f432292aa3051a0f14e6880d51ca6f257c 100644 (file)
@@ -1,3 +1,14 @@
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 0-4.
+                When read, this attribute returns the number of the actual
+                profile. This value is persistent, so its equivalent to the
+                profile that's active when the mouse is powered on next time.
+               When written, this file sets the number of the startup profile
+               and the mouse activates this profile immediately.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
 Date:          October 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -22,6 +33,40 @@ Description: When read, this file returns the raw integer version number of the
                Please read binary attribute info which contains firmware version.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
+Date:          November 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 8 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store a macro with max 500 key/button strokes
+               internally.
+               When written, this file lets one set the sequence for a specific
+               button for a specific profile. Button and profile numbers are
+               included in written data. The data has to be 2082 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When written, this file lets one write the respective profile
+               buttons back to the mouse. The data has to be 77 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
 Date:          August 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -34,6 +79,22 @@ Description: The mouse can store 5 profiles which can be switched by the
                Write control to select profile and read profile_buttons instead.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When written, this file lets one write the respective profile
+               settings back to the mouse. The data has to be 43 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
 Date:          August 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -45,4 +106,40 @@ Description:        The mouse can store 5 profiles which can be switched by the
                The returned data is 43 bytes in size.
                This file is readonly.
                Write control to select profile and read profile_settings instead.
-Users:         http://roccat.sourceforge.net
\ No newline at end of file
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse has a tracking- and a distance-control-unit. These
+               can be activated/deactivated and the lift-off distance can be
+               set. The data has to be 6 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk
+Date:          May 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   Used to active some easy* functions of the mouse from outside.
+               The data has to be 16 bytes long.
+               This file is writeonly.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When written a calibration process for the tracking control unit
+               can be initiated/cancelled. Also lets one read/write sensor
+               registers.
+               The data has to be 4 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
+Date:          October 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read the mouse returns a 30x30 pixel image of the
+               sampled underground. This works only in the course of a
+               calibration process initiated with tcu.
+               The returned data is 1028 bytes in size.
+               This file is readonly.
+Users:         http://roccat.sourceforge.net
index 4a98e02b6c6a969460d050dfcff5ab16f7d52a54..ab01631e1e0f2828c05841a4a645b85a3d38885c 100644 (file)
@@ -8,6 +8,17 @@ Description:   The integer value of this attribute ranges from 1-4.
                Has never been used. If bookkeeping is done, it's done in userland tools.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The integer value of this attribute ranges from 0-4.
+               When read, this attribute returns the number of the active
+               profile.
+               When written, the mouse activates this profile immediately.
+               The profile that's active when powered down is the same that's
+               active when the mouse is powered on.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
 Date:          January 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -40,6 +51,29 @@ Description: When read, this file returns the raw integer version number of the
                Obsoleted by binary sysfs attribute "info".
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
+Date:          November 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 6 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When written, this file lets one write the respective profile
+               buttons back to the mouse. The data has to be 23 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
 Date:          January 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -52,6 +86,22 @@ Description: The mouse can store 5 profiles which can be switched by the
                Write control to select profile and read profile_buttons instead.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
+Date:          January 2011
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When written, this file lets one write the respective profile
+               settings back to the mouse. The data has to be 16 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
 Date:          January 2011
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
index 87ac87e9556dbce80da807efed3baa084574215a..16020b31ae640eddda12cae66d54f48a7c4cb65b 100644 (file)
@@ -37,6 +37,29 @@ Description: When read, this file returns the raw integer version number of the
                Please use binary attribute "info" which provides this information.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
+Date:          November 2012
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns general data like firmware version.
+               When written, the device can be reset.
+               The data is 6 bytes long.
+Users:         http://roccat.sourceforge.net
+
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_buttons holds information about button layout.
+               When written, this file lets one write the respective profile
+               buttons back to the mouse. The data has to be 19 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
 Date:          August 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -49,6 +72,22 @@ Description: The mouse can store 5 profiles which can be switched by the
                Write control to select profile and read profile_buttons instead.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   The mouse can store 5 profiles which can be switched by the
+               press of a button. A profile is split in settings and buttons.
+               profile_settings holds information like resolution, sensitivity
+               and light effects.
+               When written, this file lets one write the respective profile
+               settings back to the mouse. The data has to be 13 bytes long.
+               The mouse will reject invalid data.
+               Which profile to write is determined by the profile number
+               contained in the data.
+               Before reading this file, control has to be written to select
+               which profile to read.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
 Date:          August 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
@@ -62,6 +101,17 @@ Description:        The mouse can store 5 profiles which can be switched by the
                Write control to select profile and read profile_settings instead.
 Users:         http://roccat.sourceforge.net
 
+What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
+Date:          August 2010
+Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:   When read, this file returns the settings stored in the mouse.
+               The size of the data is 3 bytes and holds information on the
+               startup_profile.
+               When written, this file lets write settings back to the mouse.
+               The data has to be 3 bytes long. The mouse will reject invalid
+               data.
+Users:         http://roccat.sourceforge.net
+
 What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
 Date:          August 2010
 Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-corsair b/Documentation/ABI/testing/sysfs-driver-hid-corsair
new file mode 100644 (file)
index 0000000..b8827f0
--- /dev/null
@@ -0,0 +1,15 @@
+What:          /sys/bus/drivers/corsair/<dev>/macro_mode
+Date:          August 2015
+KernelVersion: 4.2
+Contact:       Clement Vuchener <clement.vuchener@gmail.com>
+Description:   Get/set the current playback mode. "SW" for software mode
+               where G-keys triggers their regular key codes. "HW" for
+               hardware playback mode where the G-keys play their macro
+               from the on-board memory.
+
+
+What:          /sys/bus/drivers/corsair/<dev>/current_profile
+Date:          August 2015
+KernelVersion: 4.2
+Contact:       Clement Vuchener <clement.vuchener@gmail.com>
+Description:   Get/set the current selected profile. Values are from 1 to 3.
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
deleted file mode 100644 (file)
index 7bd776f..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 0-4.
-                When read, this attribute returns the number of the actual
-                profile. This value is persistent, so its equivalent to the
-                profile that's active when the mouse is powered on next time.
-               When written, this file sets the number of the startup profile
-               and the mouse activates this profile immediately.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info
-Date:          November 2012
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns general data like firmware version.
-               When written, the device can be reset.
-               The data is 8 bytes long.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store a macro with max 500 key/button strokes
-               internally.
-               When written, this file lets one set the sequence for a specific
-               button for a specific profile. Button and profile numbers are
-               included in written data. The data has to be 2082 bytes long.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When written, this file lets one write the respective profile
-               buttons back to the mouse. The data has to be 77 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When written, this file lets one write the respective profile
-               settings back to the mouse. The data has to be 43 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse has a tracking- and a distance-control-unit. These
-               can be activated/deactivated and the lift-off distance can be
-               set. The data has to be 6 bytes long.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk
-Date:          May 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   Used to active some easy* functions of the mouse from outside.
-               The data has to be 16 bytes long.
-               This file is writeonly.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When written a calibration process for the tracking control unit
-               can be initiated/cancelled. Also lets one read/write sensor
-               registers.
-               The data has to be 4 bytes long.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
-Date:          October 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read the mouse returns a 30x30 pixel image of the
-               sampled underground. This works only in the course of a
-               calibration process initiated with tcu.
-               The returned data is 1028 bytes in size.
-               This file is readonly.
-Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
deleted file mode 100644 (file)
index a10404f..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The integer value of this attribute ranges from 0-4.
-               When read, this attribute returns the number of the active
-               profile.
-               When written, the mouse activates this profile immediately.
-               The profile that's active when powered down is the same that's
-               active when the mouse is powered on.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info
-Date:          November 2012
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns general data like firmware version.
-               When written, the device can be reset.
-               The data is 6 bytes long.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When written, this file lets one write the respective profile
-               buttons back to the mouse. The data has to be 23 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
-Date:          January 2011
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When written, this file lets one write the respective profile
-               settings back to the mouse. The data has to be 16 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
deleted file mode 100644 (file)
index 9fa9de3..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info
-Date:          November 2012
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns general data like firmware version.
-               When written, the device can be reset.
-               The data is 6 bytes long.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_settings holds information like resolution, sensitivity
-               and light effects.
-               When written, this file lets one write the respective profile
-               settings back to the mouse. The data has to be 13 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   The mouse can store 5 profiles which can be switched by the
-               press of a button. A profile is split in settings and buttons.
-               profile_buttons holds information about button layout.
-               When written, this file lets one write the respective profile
-               buttons back to the mouse. The data has to be 19 bytes long.
-               The mouse will reject invalid data.
-               Which profile to write is determined by the profile number
-               contained in the data.
-               Before reading this file, control has to be written to select
-               which profile to read.
-Users:         http://roccat.sourceforge.net
-
-What:          /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
-Date:          August 2010
-Contact:       Stefan Achatz <erazor_de@users.sourceforge.net>
-Description:   When read, this file returns the settings stored in the mouse.
-               The size of the data is 3 bytes and holds information on the
-               startup_profile.
-               When written, this file lets write settings back to the mouse.
-               The data has to be 3 bytes long. The mouse will reject invalid
-               data.
-Users:         http://roccat.sourceforge.net
index 7245b7f8767ff36a7df4596de8fea0ffb75c28a5..513a16cc6e18536e1e38e23bf2068b99bb65f197 100644 (file)
@@ -171,6 +171,16 @@ config HID_CHICONY
        ---help---
        Support for Chicony Tactical pad.
 
+config HID_CORSAIR
+       tristate "Corsair devices"
+       depends on HID && USB && LEDS_CLASS
+       ---help---
+       Support for Corsair devices that are not fully compliant with the
+       HID standard.
+
+       Supported devices:
+       - Vengeance K90
+
 config HID_PRODIKEYS
        tristate "Prodikeys PC-MIDI Keyboard support"
        depends on HID && SND
@@ -678,9 +688,8 @@ config HID_SAITEK
 
        Supported devices:
        - PS1000 Dual Analog Pad
-       - R.A.T.9 Gaming Mouse
-       - R.A.T.7 Gaming Mouse
-       - M.M.O.7 Gaming Mouse
+       - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice
+       - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice
 
 config HID_SAMSUNG
        tristate "Samsung InfraRed remote control or keyboards"
index 571d176d22dfd739373b41dbd62c9df4b256fa77..00011fee08b98f80fb032244041a1e3e7c45cb44 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN)      += hid-belkin.o
 obj-$(CONFIG_HID_BETOP_FF)     += hid-betopff.o
 obj-$(CONFIG_HID_CHERRY)       += hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)      += hid-chicony.o
+obj-$(CONFIG_HID_CORSAIR)      += hid-corsair.o
 obj-$(CONFIG_HID_CP2112)       += hid-cp2112.o
 obj-$(CONFIG_HID_CYPRESS)      += hid-cypress.o
 obj-$(CONFIG_HID_DRAGONRISE)   += hid-dr.o
index 0e6a42d37eb6f374ef864f383fc23d15bf844736..07cbc70f00e7dfc8ddbfc7554f8e9c134721bc1f 100644 (file)
@@ -256,7 +256,7 @@ out:
        return 0;
 }
 
-static void appleir_input_configured(struct hid_device *hid,
+static int appleir_input_configured(struct hid_device *hid,
                struct hid_input *hidinput)
 {
        struct input_dev *input_dev = hidinput->input;
@@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid,
        for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
                set_bit(appleir->keymap[i], input_dev->keybit);
        clear_bit(KEY_RESERVED, input_dev->keybit);
+
+       return 0;
 }
 
 static int appleir_input_mapping(struct hid_device *hid,
index 340ba9d394a09045949c0adc26dc4839c589a65f..3280aff28e907dfc910fbafcfbb00316ccf2a13b 100644 (file)
@@ -23,7 +23,8 @@ static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
                dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n");
                rdesc[53] = 0x65;
-       } return rdesc;
+       }
+       return rdesc;
 }
 
 static const struct hid_device_id aureal_devices[] = {
index 70a11ac3811926733826129674e292bc907202f1..efed99fd2103a93b0a064ce88832f2123e949571 100644 (file)
@@ -725,6 +725,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
 
        if (hid->vendor == USB_VENDOR_ID_MICROSOFT &&
            (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
+            hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
             hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
             hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
             hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
@@ -1611,7 +1612,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
                "Multi-Axis Controller"
        };
        const char *type, *bus;
-       char buf[64];
+       char buf[64] = "";
        unsigned int i;
        int len;
        int ret;
@@ -1678,6 +1679,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
        case BUS_BLUETOOTH:
                bus = "BLUETOOTH";
                break;
+       case BUS_I2C:
+               bus = "I2C";
+               break;
        default:
                bus = "<UNKNOWN>";
        }
@@ -1828,6 +1832,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
@@ -1928,6 +1933,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
@@ -1981,6 +1987,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
 #endif
        { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c
new file mode 100644 (file)
index 0000000..bcefb9e
--- /dev/null
@@ -0,0 +1,673 @@
+/*
+ * HID driver for Corsair devices
+ *
+ * Supported devices:
+ *  - Vengeance K90 Keyboard
+ *
+ * Copyright (c) 2015 Clement Vuchener
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/leds.h>
+
+#include "hid-ids.h"
+
+#define CORSAIR_USE_K90_MACRO  (1<<0)
+#define CORSAIR_USE_K90_BACKLIGHT      (1<<1)
+
+struct k90_led {
+       struct led_classdev cdev;
+       int brightness;
+       struct work_struct work;
+       bool removed;
+};
+
+struct k90_drvdata {
+       struct k90_led record_led;
+};
+
+struct corsair_drvdata {
+       unsigned long quirks;
+       struct k90_drvdata *k90;
+       struct k90_led *backlight;
+};
+
+#define K90_GKEY_COUNT 18
+
+static int corsair_usage_to_gkey(unsigned int usage)
+{
+       /* G1 (0xd0) to G16 (0xdf) */
+       if (usage >= 0xd0 && usage <= 0xdf)
+               return usage - 0xd0 + 1;
+       /* G17 (0xe8) to G18 (0xe9) */
+       if (usage >= 0xe8 && usage <= 0xe9)
+               return usage - 0xe8 + 17;
+       return 0;
+}
+
+static unsigned short corsair_gkey_map[K90_GKEY_COUNT] = {
+       BTN_TRIGGER_HAPPY1,
+       BTN_TRIGGER_HAPPY2,
+       BTN_TRIGGER_HAPPY3,
+       BTN_TRIGGER_HAPPY4,
+       BTN_TRIGGER_HAPPY5,
+       BTN_TRIGGER_HAPPY6,
+       BTN_TRIGGER_HAPPY7,
+       BTN_TRIGGER_HAPPY8,
+       BTN_TRIGGER_HAPPY9,
+       BTN_TRIGGER_HAPPY10,
+       BTN_TRIGGER_HAPPY11,
+       BTN_TRIGGER_HAPPY12,
+       BTN_TRIGGER_HAPPY13,
+       BTN_TRIGGER_HAPPY14,
+       BTN_TRIGGER_HAPPY15,
+       BTN_TRIGGER_HAPPY16,
+       BTN_TRIGGER_HAPPY17,
+       BTN_TRIGGER_HAPPY18,
+};
+
+module_param_array_named(gkey_codes, corsair_gkey_map, ushort, NULL, S_IRUGO);
+MODULE_PARM_DESC(gkey_codes, "Key codes for the G-keys");
+
+static unsigned short corsair_record_keycodes[2] = {
+       BTN_TRIGGER_HAPPY19,
+       BTN_TRIGGER_HAPPY20
+};
+
+module_param_array_named(recordkey_codes, corsair_record_keycodes, ushort,
+                        NULL, S_IRUGO);
+MODULE_PARM_DESC(recordkey_codes, "Key codes for the MR (start and stop record) button");
+
+static unsigned short corsair_profile_keycodes[3] = {
+       BTN_TRIGGER_HAPPY21,
+       BTN_TRIGGER_HAPPY22,
+       BTN_TRIGGER_HAPPY23
+};
+
+module_param_array_named(profilekey_codes, corsair_profile_keycodes, ushort,
+                        NULL, S_IRUGO);
+MODULE_PARM_DESC(profilekey_codes, "Key codes for the profile buttons");
+
+#define CORSAIR_USAGE_SPECIAL_MIN 0xf0
+#define CORSAIR_USAGE_SPECIAL_MAX 0xff
+
+#define CORSAIR_USAGE_MACRO_RECORD_START 0xf6
+#define CORSAIR_USAGE_MACRO_RECORD_STOP 0xf7
+
+#define CORSAIR_USAGE_PROFILE 0xf1
+#define CORSAIR_USAGE_M1 0xf1
+#define CORSAIR_USAGE_M2 0xf2
+#define CORSAIR_USAGE_M3 0xf3
+#define CORSAIR_USAGE_PROFILE_MAX 0xf3
+
+#define CORSAIR_USAGE_META_OFF 0xf4
+#define CORSAIR_USAGE_META_ON  0xf5
+
+#define CORSAIR_USAGE_LIGHT 0xfa
+#define CORSAIR_USAGE_LIGHT_OFF 0xfa
+#define CORSAIR_USAGE_LIGHT_DIM 0xfb
+#define CORSAIR_USAGE_LIGHT_MEDIUM 0xfc
+#define CORSAIR_USAGE_LIGHT_BRIGHT 0xfd
+#define CORSAIR_USAGE_LIGHT_MAX 0xfd
+
+/* USB control protocol */
+
+#define K90_REQUEST_BRIGHTNESS 49
+#define K90_REQUEST_MACRO_MODE 2
+#define K90_REQUEST_STATUS 4
+#define K90_REQUEST_GET_MODE 5
+#define K90_REQUEST_PROFILE 20
+
+#define K90_MACRO_MODE_SW 0x0030
+#define K90_MACRO_MODE_HW 0x0001
+
+#define K90_MACRO_LED_ON  0x0020
+#define K90_MACRO_LED_OFF 0x0040
+
+/*
+ * LED class devices
+ */
+
+#define K90_BACKLIGHT_LED_SUFFIX "::backlight"
+#define K90_RECORD_LED_SUFFIX "::record"
+
+static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev)
+{
+       int ret;
+       struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+       struct device *dev = led->cdev.dev->parent;
+       struct usb_interface *usbif = to_usb_interface(dev->parent);
+       struct usb_device *usbdev = interface_to_usbdev(usbif);
+       int brightness;
+       char data[8];
+
+       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+                             K90_REQUEST_STATUS,
+                             USB_DIR_IN | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, 0, 0, data, 8,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret < 0) {
+               dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
+                        ret);
+               return -EIO;
+       }
+       brightness = data[4];
+       if (brightness < 0 || brightness > 3) {
+               dev_warn(dev,
+                        "Read invalid backlight brightness: %02hhx.\n",
+                        data[4]);
+               return -EIO;
+       }
+       return brightness;
+}
+
+static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev)
+{
+       struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+
+       return led->brightness;
+}
+
+static void k90_brightness_set(struct led_classdev *led_cdev,
+                              enum led_brightness brightness)
+{
+       struct k90_led *led = container_of(led_cdev, struct k90_led, cdev);
+
+       led->brightness = brightness;
+       schedule_work(&led->work);
+}
+
+static void k90_backlight_work(struct work_struct *work)
+{
+       int ret;
+       struct k90_led *led = container_of(work, struct k90_led, work);
+       struct device *dev;
+       struct usb_interface *usbif;
+       struct usb_device *usbdev;
+
+       if (led->removed)
+               return;
+
+       dev = led->cdev.dev->parent;
+       usbif = to_usb_interface(dev->parent);
+       usbdev = interface_to_usbdev(usbif);
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                             K90_REQUEST_BRIGHTNESS,
+                             USB_DIR_OUT | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, led->brightness, 0,
+                             NULL, 0, USB_CTRL_SET_TIMEOUT);
+       if (ret != 0)
+               dev_warn(dev, "Failed to set backlight brightness (error: %d).\n",
+                        ret);
+}
+
+static void k90_record_led_work(struct work_struct *work)
+{
+       int ret;
+       struct k90_led *led = container_of(work, struct k90_led, work);
+       struct device *dev;
+       struct usb_interface *usbif;
+       struct usb_device *usbdev;
+       int value;
+
+       if (led->removed)
+               return;
+
+       dev = led->cdev.dev->parent;
+       usbif = to_usb_interface(dev->parent);
+       usbdev = interface_to_usbdev(usbif);
+
+       if (led->brightness > 0)
+               value = K90_MACRO_LED_ON;
+       else
+               value = K90_MACRO_LED_OFF;
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                             K90_REQUEST_MACRO_MODE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, value, 0, NULL, 0,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret != 0)
+               dev_warn(dev, "Failed to set record LED state (error: %d).\n",
+                        ret);
+}
+
+/*
+ * Keyboard attributes
+ */
+
+static ssize_t k90_show_macro_mode(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret;
+       struct usb_interface *usbif = to_usb_interface(dev->parent);
+       struct usb_device *usbdev = interface_to_usbdev(usbif);
+       const char *macro_mode;
+       char data[8];
+
+       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+                             K90_REQUEST_GET_MODE,
+                             USB_DIR_IN | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, 0, 0, data, 2,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret < 0) {
+               dev_warn(dev, "Failed to get K90 initial mode (error %d).\n",
+                        ret);
+               return -EIO;
+       }
+
+       switch (data[0]) {
+       case K90_MACRO_MODE_HW:
+               macro_mode = "HW";
+               break;
+
+       case K90_MACRO_MODE_SW:
+               macro_mode = "SW";
+               break;
+       default:
+               dev_warn(dev, "K90 in unknown mode: %02hhx.\n",
+                        data[0]);
+               return -EIO;
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode);
+}
+
+static ssize_t k90_store_macro_mode(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int ret;
+       struct usb_interface *usbif = to_usb_interface(dev->parent);
+       struct usb_device *usbdev = interface_to_usbdev(usbif);
+       __u16 value;
+
+       if (strncmp(buf, "SW", 2) == 0)
+               value = K90_MACRO_MODE_SW;
+       else if (strncmp(buf, "HW", 2) == 0)
+               value = K90_MACRO_MODE_HW;
+       else
+               return -EINVAL;
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                             K90_REQUEST_MACRO_MODE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, value, 0, NULL, 0,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret != 0) {
+               dev_warn(dev, "Failed to set macro mode.\n");
+               return ret;
+       }
+
+       return count;
+}
+
+static ssize_t k90_show_current_profile(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       int ret;
+       struct usb_interface *usbif = to_usb_interface(dev->parent);
+       struct usb_device *usbdev = interface_to_usbdev(usbif);
+       int current_profile;
+       char data[8];
+
+       ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0),
+                             K90_REQUEST_STATUS,
+                             USB_DIR_IN | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, 0, 0, data, 8,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret < 0) {
+               dev_warn(dev, "Failed to get K90 initial state (error %d).\n",
+                        ret);
+               return -EIO;
+       }
+       current_profile = data[7];
+       if (current_profile < 1 || current_profile > 3) {
+               dev_warn(dev, "Read invalid current profile: %02hhx.\n",
+                        data[7]);
+               return -EIO;
+       }
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", current_profile);
+}
+
+static ssize_t k90_store_current_profile(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       int ret;
+       struct usb_interface *usbif = to_usb_interface(dev->parent);
+       struct usb_device *usbdev = interface_to_usbdev(usbif);
+       int profile;
+
+       if (kstrtoint(buf, 10, &profile))
+               return -EINVAL;
+       if (profile < 1 || profile > 3)
+               return -EINVAL;
+
+       ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
+                             K90_REQUEST_PROFILE,
+                             USB_DIR_OUT | USB_TYPE_VENDOR |
+                             USB_RECIP_DEVICE, profile, 0, NULL, 0,
+                             USB_CTRL_SET_TIMEOUT);
+       if (ret != 0) {
+               dev_warn(dev, "Failed to change current profile (error %d).\n",
+                        ret);
+               return ret;
+       }
+
+       return count;
+}
+
+static DEVICE_ATTR(macro_mode, 0644, k90_show_macro_mode, k90_store_macro_mode);
+static DEVICE_ATTR(current_profile, 0644, k90_show_current_profile,
+                  k90_store_current_profile);
+
+static struct attribute *k90_attrs[] = {
+       &dev_attr_macro_mode.attr,
+       &dev_attr_current_profile.attr,
+       NULL
+};
+
+static const struct attribute_group k90_attr_group = {
+       .attrs = k90_attrs,
+};
+
+/*
+ * Driver functions
+ */
+
+static int k90_init_backlight(struct hid_device *dev)
+{
+       int ret;
+       struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+       size_t name_sz;
+       char *name;
+
+       drvdata->backlight = kzalloc(sizeof(struct k90_led), GFP_KERNEL);
+       if (!drvdata->backlight) {
+               ret = -ENOMEM;
+               goto fail_backlight_alloc;
+       }
+
+       name_sz =
+           strlen(dev_name(&dev->dev)) + sizeof(K90_BACKLIGHT_LED_SUFFIX);
+       name = kzalloc(name_sz, GFP_KERNEL);
+       if (!name) {
+               ret = -ENOMEM;
+               goto fail_name_alloc;
+       }
+       snprintf(name, name_sz, "%s" K90_BACKLIGHT_LED_SUFFIX,
+                dev_name(&dev->dev));
+       drvdata->backlight->removed = false;
+       drvdata->backlight->cdev.name = name;
+       drvdata->backlight->cdev.max_brightness = 3;
+       drvdata->backlight->cdev.brightness_set = k90_brightness_set;
+       drvdata->backlight->cdev.brightness_get = k90_backlight_get;
+       INIT_WORK(&drvdata->backlight->work, k90_backlight_work);
+       ret = led_classdev_register(&dev->dev, &drvdata->backlight->cdev);
+       if (ret != 0)
+               goto fail_register_cdev;
+
+       return 0;
+
+fail_register_cdev:
+       kfree(drvdata->backlight->cdev.name);
+fail_name_alloc:
+       kfree(drvdata->backlight);
+       drvdata->backlight = NULL;
+fail_backlight_alloc:
+       return ret;
+}
+
+static int k90_init_macro_functions(struct hid_device *dev)
+{
+       int ret;
+       struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+       struct k90_drvdata *k90;
+       size_t name_sz;
+       char *name;
+
+       k90 = kzalloc(sizeof(struct k90_drvdata), GFP_KERNEL);
+       if (!k90) {
+               ret = -ENOMEM;
+               goto fail_drvdata;
+       }
+       drvdata->k90 = k90;
+
+       /* Init LED device for record LED */
+       name_sz = strlen(dev_name(&dev->dev)) + sizeof(K90_RECORD_LED_SUFFIX);
+       name = kzalloc(name_sz, GFP_KERNEL);
+       if (!name) {
+               ret = -ENOMEM;
+               goto fail_record_led_alloc;
+       }
+       snprintf(name, name_sz, "%s" K90_RECORD_LED_SUFFIX,
+                dev_name(&dev->dev));
+       k90->record_led.removed = false;
+       k90->record_led.cdev.name = name;
+       k90->record_led.cdev.max_brightness = 1;
+       k90->record_led.cdev.brightness_set = k90_brightness_set;
+       k90->record_led.cdev.brightness_get = k90_record_led_get;
+       INIT_WORK(&k90->record_led.work, k90_record_led_work);
+       k90->record_led.brightness = 0;
+       ret = led_classdev_register(&dev->dev, &k90->record_led.cdev);
+       if (ret != 0)
+               goto fail_record_led;
+
+       /* Init attributes */
+       ret = sysfs_create_group(&dev->dev.kobj, &k90_attr_group);
+       if (ret != 0)
+               goto fail_sysfs;
+
+       return 0;
+
+fail_sysfs:
+       k90->record_led.removed = true;
+       led_classdev_unregister(&k90->record_led.cdev);
+       cancel_work_sync(&k90->record_led.work);
+fail_record_led:
+       kfree(k90->record_led.cdev.name);
+fail_record_led_alloc:
+       kfree(k90);
+fail_drvdata:
+       drvdata->k90 = NULL;
+       return ret;
+}
+
+static void k90_cleanup_backlight(struct hid_device *dev)
+{
+       struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+
+       if (drvdata->backlight) {
+               drvdata->backlight->removed = true;
+               led_classdev_unregister(&drvdata->backlight->cdev);
+               cancel_work_sync(&drvdata->backlight->work);
+               kfree(drvdata->backlight->cdev.name);
+               kfree(drvdata->backlight);
+       }
+}
+
+static void k90_cleanup_macro_functions(struct hid_device *dev)
+{
+       struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+       struct k90_drvdata *k90 = drvdata->k90;
+
+       if (k90) {
+               sysfs_remove_group(&dev->dev.kobj, &k90_attr_group);
+
+               k90->record_led.removed = true;
+               led_classdev_unregister(&k90->record_led.cdev);
+               cancel_work_sync(&k90->record_led.work);
+               kfree(k90->record_led.cdev.name);
+
+               kfree(k90);
+       }
+}
+
+static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
+{
+       int ret;
+       unsigned long quirks = id->driver_data;
+       struct corsair_drvdata *drvdata;
+       struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
+
+       drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
+                              GFP_KERNEL);
+       if (drvdata == NULL)
+               return -ENOMEM;
+       drvdata->quirks = quirks;
+       hid_set_drvdata(dev, drvdata);
+
+       ret = hid_parse(dev);
+       if (ret != 0) {
+               hid_err(dev, "parse failed\n");
+               return ret;
+       }
+       ret = hid_hw_start(dev, HID_CONNECT_DEFAULT);
+       if (ret != 0) {
+               hid_err(dev, "hw start failed\n");
+               return ret;
+       }
+
+       if (usbif->cur_altsetting->desc.bInterfaceNumber == 0) {
+               if (quirks & CORSAIR_USE_K90_MACRO) {
+                       ret = k90_init_macro_functions(dev);
+                       if (ret != 0)
+                               hid_warn(dev, "Failed to initialize K90 macro functions.\n");
+               }
+               if (quirks & CORSAIR_USE_K90_BACKLIGHT) {
+                       ret = k90_init_backlight(dev);
+                       if (ret != 0)
+                               hid_warn(dev, "Failed to initialize K90 backlight.\n");
+               }
+       }
+
+       return 0;
+}
+
+static void corsair_remove(struct hid_device *dev)
+{
+       k90_cleanup_macro_functions(dev);
+       k90_cleanup_backlight(dev);
+
+       hid_hw_stop(dev);
+}
+
+static int corsair_event(struct hid_device *dev, struct hid_field *field,
+                        struct hid_usage *usage, __s32 value)
+{
+       struct corsair_drvdata *drvdata = hid_get_drvdata(dev);
+
+       if (!drvdata->k90)
+               return 0;
+
+       switch (usage->hid & HID_USAGE) {
+       case CORSAIR_USAGE_MACRO_RECORD_START:
+               drvdata->k90->record_led.brightness = 1;
+               break;
+       case CORSAIR_USAGE_MACRO_RECORD_STOP:
+               drvdata->k90->record_led.brightness = 0;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int corsair_input_mapping(struct hid_device *dev,
+                                struct hid_input *input,
+                                struct hid_field *field,
+                                struct hid_usage *usage, unsigned long **bit,
+                                int *max)
+{
+       int gkey;
+
+       gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE);
+       if (gkey != 0) {
+               hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                   corsair_gkey_map[gkey - 1]);
+               return 1;
+       }
+       if ((usage->hid & HID_USAGE) >= CORSAIR_USAGE_SPECIAL_MIN &&
+           (usage->hid & HID_USAGE) <= CORSAIR_USAGE_SPECIAL_MAX) {
+               switch (usage->hid & HID_USAGE) {
+               case CORSAIR_USAGE_MACRO_RECORD_START:
+                       hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                           corsair_record_keycodes[0]);
+                       return 1;
+
+               case CORSAIR_USAGE_MACRO_RECORD_STOP:
+                       hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                           corsair_record_keycodes[1]);
+                       return 1;
+
+               case CORSAIR_USAGE_M1:
+                       hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                           corsair_profile_keycodes[0]);
+                       return 1;
+
+               case CORSAIR_USAGE_M2:
+                       hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                           corsair_profile_keycodes[1]);
+                       return 1;
+
+               case CORSAIR_USAGE_M3:
+                       hid_map_usage_clear(input, usage, bit, max, EV_KEY,
+                                           corsair_profile_keycodes[2]);
+                       return 1;
+
+               default:
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+static const struct hid_device_id corsair_devices[] = {
+       { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90),
+               .driver_data = CORSAIR_USE_K90_MACRO |
+                              CORSAIR_USE_K90_BACKLIGHT },
+       {}
+};
+
+MODULE_DEVICE_TABLE(hid, corsair_devices);
+
+static struct hid_driver corsair_driver = {
+       .name = "corsair",
+       .id_table = corsair_devices,
+       .probe = corsair_probe,
+       .event = corsair_event,
+       .remove = corsair_remove,
+       .input_mapping = corsair_input_mapping,
+};
+
+static int __init corsair_init(void)
+{
+       return hid_register_driver(&corsair_driver);
+}
+
+static void corsair_exit(void)
+{
+       hid_unregister_driver(&corsair_driver);
+}
+
+module_init(corsair_init);
+module_exit(corsair_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Clement Vuchener");
+MODULE_DESCRIPTION("HID driver for Corsair devices");
index ce0644424f587707e68023f066eefecc50048d6b..1d78ba3b799e6f020eee8f9e16c9cab5b8f61627 100644 (file)
@@ -234,6 +234,58 @@ static __u8 pid0011_rdesc_fixed[] = {
        0xC0                /*  End Collection                  */
 };
 
+static __u8 pid0006_rdesc_fixed[] = {
+       0x05, 0x01,        /* Usage Page (Generic Desktop)      */
+       0x09, 0x04,        /* Usage (Joystick)                  */
+       0xA1, 0x01,        /* Collection (Application)          */
+       0xA1, 0x02,        /*   Collection (Logical)            */
+       0x75, 0x08,        /*     Report Size (8)               */
+       0x95, 0x05,        /*     Report Count (5)              */
+       0x15, 0x00,        /*     Logical Minimum (0)           */
+       0x26, 0xFF, 0x00,  /*     Logical Maximum (255)         */
+       0x35, 0x00,        /*     Physical Minimum (0)          */
+       0x46, 0xFF, 0x00,  /*     Physical Maximum (255)        */
+       0x09, 0x30,        /*     Usage (X)                     */
+       0x09, 0x33,        /*     Usage (Ry)                    */
+       0x09, 0x32,        /*     Usage (Z)                     */
+       0x09, 0x31,        /*     Usage (Y)                     */
+       0x09, 0x34,        /*     Usage (Ry)                    */
+       0x81, 0x02,        /*     Input (Variable)              */
+       0x75, 0x04,        /*     Report Size (4)               */
+       0x95, 0x01,        /*     Report Count (1)              */
+       0x25, 0x07,        /*     Logical Maximum (7)           */
+       0x46, 0x3B, 0x01,  /*     Physical Maximum (315)        */
+       0x65, 0x14,        /*     Unit (Centimeter)             */
+       0x09, 0x39,        /*     Usage (Hat switch)            */
+       0x81, 0x42,        /*     Input (Variable)              */
+       0x65, 0x00,        /*     Unit (None)                   */
+       0x75, 0x01,        /*     Report Size (1)               */
+       0x95, 0x0C,        /*     Report Count (12)             */
+       0x25, 0x01,        /*     Logical Maximum (1)           */
+       0x45, 0x01,        /*     Physical Maximum (1)          */
+       0x05, 0x09,        /*     Usage Page (Button)           */
+       0x19, 0x01,        /*     Usage Minimum (0x01)          */
+       0x29, 0x0C,        /*     Usage Maximum (0x0C)          */
+       0x81, 0x02,        /*     Input (Variable)              */
+       0x06, 0x00, 0xFF,  /*     Usage Page (Vendor Defined)   */
+       0x75, 0x01,        /*     Report Size (1)               */
+       0x95, 0x08,        /*     Report Count (8)              */
+       0x25, 0x01,        /*     Logical Maximum (1)           */
+       0x45, 0x01,        /*     Physical Maximum (1)          */
+       0x09, 0x01,        /*     Usage (0x01)                  */
+       0x81, 0x02,        /*     Input (Variable)              */
+       0xC0,              /*   End Collection                  */
+       0xA1, 0x02,        /*   Collection (Logical)            */
+       0x75, 0x08,        /*     Report Size (8)               */
+       0x95, 0x07,        /*     Report Count (7)              */
+       0x46, 0xFF, 0x00,  /*     Physical Maximum (255)        */
+       0x26, 0xFF, 0x00,  /*     Logical Maximum (255)         */
+       0x09, 0x02,        /*     Usage (0x02)                  */
+       0x91, 0x02,        /*     Output (Variable)             */
+       0xC0,              /*   End Collection                  */
+       0xC0               /* End Collection                    */
+};
+
 static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                                unsigned int *rsize)
 {
@@ -244,6 +296,12 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                        *rsize = sizeof(pid0011_rdesc_fixed);
                }
                break;
+       case 0x0006:
+               if (*rsize == sizeof(pid0006_rdesc_fixed)) {
+                       rdesc = pid0006_rdesc_fixed;
+                       *rsize = sizeof(pid0006_rdesc_fixed);
+               }
+               break;
        }
        return rdesc;
 }
index d0bd13b62dc2dc542868262a6c38ab6d1c47b8f1..6e3848a8d8dd1416a0091ce0e7d263325dd8910b 100644 (file)
@@ -27,7 +27,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
                rdesc[47] = 0x00;
        }
-    return rdesc;
+       return rdesc;
 }
 
 static const struct hid_device_id elecom_devices[] = {
index 4e49462870abdf2f265c1528ae6c07fa4f783ec8..aad8c162a825dc60516700b1bd8caf8efeec4244 100644 (file)
@@ -37,7 +37,7 @@ static bool use_fw_quirk = true;
 module_param(use_fw_quirk, bool, S_IRUGO);
 MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)");
 
-static void elo_input_configured(struct hid_device *hdev,
+static int elo_input_configured(struct hid_device *hdev,
                struct hid_input *hidinput)
 {
        struct input_dev *input = hidinput->input;
@@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev,
        set_bit(BTN_TOUCH, input->keybit);
        set_bit(ABS_PRESSURE, input->absbit);
        input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0);
+
+       return 0;
 }
 
 static void elo_process_data(struct input_dev *input, const u8 *data, int size)
index f769208276ae4966dff54b1a1c6bf6aa680b84af..ac1feea51be365e3a4c81042b56be75fec26a6a1 100644 (file)
 #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST      0x1500
 #define USB_DEVICE_ID_CODEMERCS_IOW_LAST       0x15ff
 
+#define USB_VENDOR_ID_CORSAIR          0x1b1c
+#define USB_DEVICE_ID_CORSAIR_K90      0x1b02
+
 #define USB_VENDOR_ID_CREATIVELABS     0x041e
 #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
 
 #define USB_DEVICE_ID_DMI_ENC          0x5fab
 
 #define USB_VENDOR_ID_DRAGONRISE       0x0079
+#define USB_DEVICE_ID_DRAGONRISE_WIIU  0x1800
 
 #define USB_VENDOR_ID_DWAV             0x0eef
 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER   0x0001
 
 #define USB_VENDOR_ID_ITE               0x048d
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
+#define USB_DEVICE_ID_ITE_LENOVO_YOGA2  0x8350
 
 #define USB_VENDOR_ID_JABRA            0x0b0e
 #define USB_DEVICE_ID_JABRA_SPEAK_410  0x0412
 
 #define USB_VENDOR_ID_MADCATZ          0x0738
 #define USB_DEVICE_ID_MADCATZ_BEATPAD  0x4540
+#define USB_DEVICE_ID_MADCATZ_RAT5     0x1705
 #define USB_DEVICE_ID_MADCATZ_RAT9     0x1709
 
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MS_TOUCH_COVER_2   0x07a7
 #define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3    0x07dc
+#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2  0x07e2
 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
 #define USB_DEVICE_ID_MS_TYPE_COVER_3    0x07de
 #define USB_DEVICE_ID_MS_POWER_COVER     0x07da
index 53aeaf6252c75a039cb94a13af27fffbb0f2bddb..2ba6bf69b7d0c45c3ca76b612de5d647d513e3ba 100644 (file)
@@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                 * UGCI) cram a lot of unrelated inputs into the
                                 * same interface. */
                                hidinput->report = report;
-                               if (drv->input_configured)
-                                       drv->input_configured(hid, hidinput);
+                               if (drv->input_configured &&
+                                   drv->input_configured(hid, hidinput))
+                                       goto out_cleanup;
                                if (input_register_device(hidinput->input))
                                        goto out_cleanup;
                                hidinput = NULL;
@@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
        }
 
        if (hidinput) {
-               if (drv->input_configured)
-                       drv->input_configured(hid, hidinput);
+               if (drv->input_configured &&
+                   drv->input_configured(hid, hidinput))
+                       goto out_cleanup;
                if (input_register_device(hidinput->input))
                        goto out_cleanup;
        }
index e4bc6cb6d7fa5d5481f650c87fde01a7348fdb6a..8979f1fd5208f95e9f707c46b77373f4c975b3b4 100644 (file)
@@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev)
        hid_hw_stop(hdev);
 }
 
-static void lenovo_input_configured(struct hid_device *hdev,
+static int lenovo_input_configured(struct hid_device *hdev,
                struct hid_input *hi)
 {
        switch (hdev->product) {
@@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev,
                        }
                        break;
        }
+
+       return 0;
 }
 
 
index 484196459305577c19433fe4fe35b21c2ac39905..5fd97860aec4d8ec1e92b02031e715e8644367e8 100644 (file)
@@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644);
 MODULE_PARM_DESC(disable_raw_mode,
        "Disable Raw mode reporting for touchpads and keep firmware gestures.");
 
+static bool disable_tap_to_click;
+module_param(disable_tap_to_click, bool, 0644);
+MODULE_PARM_DESC(disable_tap_to_click,
+       "Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently).");
+
 #define REPORT_ID_HIDPP_SHORT                  0x10
 #define REPORT_ID_HIDPP_LONG                   0x11
 
@@ -41,10 +46,15 @@ MODULE_PARM_DESC(disable_raw_mode,
 
 #define HIDPP_QUIRK_CLASS_WTP                  BIT(0)
 #define HIDPP_QUIRK_CLASS_M560                 BIT(1)
+#define HIDPP_QUIRK_CLASS_K400                 BIT(2)
 
 /* bits 2..20 are reserved for classes */
-#define HIDPP_QUIRK_DELAYED_INIT               BIT(21)
+#define HIDPP_QUIRK_CONNECT_EVENTS             BIT(21)
 #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS       BIT(22)
+#define HIDPP_QUIRK_NO_HIDINPUT                        BIT(23)
+
+#define HIDPP_QUIRK_DELAYED_INIT               (HIDPP_QUIRK_NO_HIDINPUT | \
+                                                HIDPP_QUIRK_CONNECT_EVENTS)
 
 /*
  * There are two hidpp protocols in use, the first version hidpp10 is known
@@ -552,6 +562,52 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp)
        return name;
 }
 
+/* -------------------------------------------------------------------------- */
+/* 0x6010: Touchpad FW items                                                  */
+/* -------------------------------------------------------------------------- */
+
+#define HIDPP_PAGE_TOUCHPAD_FW_ITEMS                   0x6010
+
+#define CMD_TOUCHPAD_FW_ITEMS_SET                      0x10
+
+struct hidpp_touchpad_fw_items {
+       uint8_t presence;
+       uint8_t desired_state;
+       uint8_t state;
+       uint8_t persistent;
+};
+
+/**
+ * send a set state command to the device by reading the current items->state
+ * field. items is then filled with the current state.
+ */
+static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp,
+                                      u8 feature_index,
+                                      struct hidpp_touchpad_fw_items *items)
+{
+       struct hidpp_report response;
+       int ret;
+       u8 *params = (u8 *)response.fap.params;
+
+       ret = hidpp_send_fap_command_sync(hidpp, feature_index,
+               CMD_TOUCHPAD_FW_ITEMS_SET, &items->state, 1, &response);
+
+       if (ret > 0) {
+               hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n",
+                       __func__, ret);
+               return -EPROTO;
+       }
+       if (ret)
+               return ret;
+
+       items->presence = params[0];
+       items->desired_state = params[1];
+       items->state = params[2];
+       items->persistent = params[3];
+
+       return 0;
+}
+
 /* -------------------------------------------------------------------------- */
 /* 0x6100: TouchPadRawXY                                                      */
 /* -------------------------------------------------------------------------- */
@@ -1132,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        return -1;
 }
 
+/* ------------------------------------------------------------------------- */
+/* Logitech K400 devices                                                     */
+/* ------------------------------------------------------------------------- */
+
+/*
+ * The Logitech K400 keyboard has an embedded touchpad which is seen
+ * as a mouse from the OS point of view. There is a hardware shortcut to disable
+ * tap-to-click but the setting is not remembered accross reset, annoying some
+ * users.
+ *
+ * We can toggle this feature from the host by using the feature 0x6010:
+ * Touchpad FW items
+ */
+
+struct k400_private_data {
+       u8 feature_index;
+};
+
+static int k400_disable_tap_to_click(struct hidpp_device *hidpp)
+{
+       struct k400_private_data *k400 = hidpp->private_data;
+       struct hidpp_touchpad_fw_items items = {};
+       int ret;
+       u8 feature_type;
+
+       if (!k400->feature_index) {
+               ret = hidpp_root_get_feature(hidpp,
+                       HIDPP_PAGE_TOUCHPAD_FW_ITEMS,
+                       &k400->feature_index, &feature_type);
+               if (ret)
+                       /* means that the device is not powered up */
+                       return ret;
+       }
+
+       ret = hidpp_touchpad_fw_items_set(hidpp, k400->feature_index, &items);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int k400_allocate(struct hid_device *hdev)
+{
+       struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+       struct k400_private_data *k400;
+
+       k400 = devm_kzalloc(&hdev->dev, sizeof(struct k400_private_data),
+                           GFP_KERNEL);
+       if (!k400)
+               return -ENOMEM;
+
+       hidpp->private_data = k400;
+
+       return 0;
+};
+
+static int k400_connect(struct hid_device *hdev, bool connected)
+{
+       struct hidpp_device *hidpp = hid_get_drvdata(hdev);
+
+       if (!connected)
+               return 0;
+
+       if (!disable_tap_to_click)
+               return 0;
+
+       return k400_disable_tap_to_click(hidpp);
+}
+
 /* -------------------------------------------------------------------------- */
 /* Generic HID++ devices                                                      */
 /* -------------------------------------------------------------------------- */
@@ -1160,13 +1285,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
                m560_populate_input(hidpp, input, origin_is_hid_core);
 }
 
-static void hidpp_input_configured(struct hid_device *hdev,
+static int hidpp_input_configured(struct hid_device *hdev,
                                struct hid_input *hidinput)
 {
        struct hidpp_device *hidpp = hid_get_drvdata(hdev);
        struct input_dev *input = hidinput->input;
 
        hidpp_populate_input(hidpp, input, true);
+
+       return 0;
 }
 
 static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
@@ -1203,7 +1330,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
        if (unlikely(hidpp_report_is_connect_event(report))) {
                atomic_set(&hidpp->connected,
                                !(report->rap.params[0] & (1 << 6)));
-               if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) &&
+               if ((hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) &&
                    (schedule_work(&hidpp->work) == 0))
                        dbg_hid("%s: connect event already queued\n", __func__);
                return 1;
@@ -1328,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
                ret = m560_send_config_command(hdev, connected);
                if (ret)
                        return;
+       } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+               ret = k400_connect(hdev, connected);
+               if (ret)
+                       return;
        }
 
        if (!connected || hidpp->delayed_input)
                return;
 
+       /* the device is already connected, we can ask for its name and
+        * protocol */
        if (!hidpp->protocol_major) {
                ret = !hidpp_is_connected(hidpp);
                if (ret) {
                        hid_err(hdev, "Can not get the protocol version.\n");
                        return;
                }
+               hid_info(hdev, "HID++ %u.%u device connected.\n",
+                        hidpp->protocol_major, hidpp->protocol_minor);
        }
 
-       /* the device is already connected, we can ask for its name and
-        * protocol */
-       hid_info(hdev, "HID++ %u.%u device connected.\n",
-                hidpp->protocol_major, hidpp->protocol_minor);
+       if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT))
+               /* if HID created the input nodes for us, we can stop now */
+               return;
 
        if (!hidpp->name || hidpp->name == hdev->name) {
                name = hidpp_get_device_name(hidpp);
@@ -1397,7 +1531,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
 
        if (disable_raw_mode) {
                hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP;
-               hidpp->quirks &= ~HIDPP_QUIRK_DELAYED_INIT;
+               hidpp->quirks &= ~HIDPP_QUIRK_CONNECT_EVENTS;
+               hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT;
        }
 
        if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
@@ -1408,6 +1543,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                ret = m560_allocate(hdev);
                if (ret)
                        goto allocate_fail;
+       } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
+               ret = k400_allocate(hdev);
+               if (ret)
+                       goto allocate_fail;
        }
 
        INIT_WORK(&hidpp->work, delayed_work_cb);
@@ -1448,7 +1587,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
        /* Block incoming packets */
        hid_device_io_stop(hdev);
 
-       if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
+       if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
                connect_mask &= ~HID_CONNECT_HIDINPUT;
 
        ret = hid_hw_start(hdev, connect_mask);
@@ -1457,7 +1596,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
                goto hid_hw_start_fail;
        }
 
-       if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) {
+       if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
                /* Allow incoming packets */
                hid_device_io_start(hdev);
 
@@ -1502,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = {
          HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
                USB_VENDOR_ID_LOGITECH, 0x402d),
          .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },
+       { /* Keyboard logitech K400 */
+         HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
+               USB_VENDOR_ID_LOGITECH, 0x4024),
+         .driver_data = HIDPP_QUIRK_CONNECT_EVENTS | HIDPP_QUIRK_CLASS_K400 },
 
        { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
                USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
index 29a74c1efcb85fa727536c4b72be844f9963cd70..d6fa496d0ca25c17035233315ba9f5d5ebddc4fd 100644 (file)
@@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
        return 0;
 }
 
-static void magicmouse_input_configured(struct hid_device *hdev,
+static int magicmouse_input_configured(struct hid_device *hdev,
                struct hid_input *hi)
 
 {
        struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+       int ret;
 
-       int ret = magicmouse_setup_input(msc->input, hdev);
+       ret = magicmouse_setup_input(msc->input, hdev);
        if (ret) {
                hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
                /* clean msc->input to notify probe() of the failure */
                msc->input = NULL;
+               return ret;
        }
+
+       return 0;
 }
 
 
index 9aa3515090a7252abc0459c8849bc9bea32d733e..77a2cf3e4afec25eee5d5d313f63caaf9939653f 100644 (file)
@@ -278,6 +278,8 @@ static const struct hid_device_id ms_devices[] = {
                .driver_data = MS_DUPLICATE_USAGES },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3),
                .driver_data = MS_HIDINPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2),
+               .driver_data = MS_HIDINPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
                .driver_data = MS_HIDINPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
index 426b2f1a34501c7516ab39dc631d3c2073591aac..3d664d01305e5ef32301fdcf53a4f3bbee61f027 100644 (file)
@@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = {
        .attrs = sysfs_attrs
 };
 
+static void mt_get_feature(struct hid_device *hdev, struct hid_report *report)
+{
+       struct mt_device *td = hid_get_drvdata(hdev);
+       int ret, size = hid_report_len(report);
+       u8 *buf;
+
+       /*
+        * Only fetch the feature report if initial reports are not already
+        * been retrieved. Currently this is only done for Windows 8 touch
+        * devices.
+        */
+       if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS))
+               return;
+       if (td->mtclass.name != MT_CLS_WIN_8)
+               return;
+
+       buf = hid_alloc_report_buf(report, GFP_KERNEL);
+       if (!buf)
+               return;
+
+       ret = hid_hw_raw_request(hdev, report->id, buf, size,
+                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
+       if (ret < 0) {
+               dev_warn(&hdev->dev, "failed to fetch feature %d\n",
+                        report->id);
+       } else {
+               ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf,
+                                          size, 0);
+               if (ret)
+                       dev_warn(&hdev->dev, "failed to report feature\n");
+       }
+
+       kfree(buf);
+}
+
 static void mt_feature_mapping(struct hid_device *hdev,
                struct hid_field *field, struct hid_usage *usage)
 {
@@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev,
 
                break;
        case HID_DG_CONTACTMAX:
+               mt_get_feature(hdev, field->report);
+
                td->maxcontact_report_id = field->report->id;
                td->maxcontacts = field->value[0];
                if (!td->maxcontacts &&
@@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev,
                        break;
                }
 
+               mt_get_feature(hdev, field->report);
                if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
                        td->is_buttonpad = true;
 
@@ -725,12 +763,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report)
                mt_sync_frame(td, report->field[0]->hidinput->input);
 }
 
-static void mt_touch_input_configured(struct hid_device *hdev,
+static int mt_touch_input_configured(struct hid_device *hdev,
                                        struct hid_input *hi)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
        struct mt_class *cls = &td->mtclass;
        struct input_dev *input = hi->input;
+       int ret;
 
        if (!td->maxcontacts)
                td->maxcontacts = MT_DEFAULT_MAXCONTACT;
@@ -752,9 +791,12 @@ static void mt_touch_input_configured(struct hid_device *hdev,
        if (td->is_buttonpad)
                __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 
-       input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+       ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags);
+       if (ret)
+               return ret;
 
        td->mt_flags = 0;
+       return 0;
 }
 
 static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -930,15 +972,19 @@ static void mt_post_parse(struct mt_device *td)
                cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
 }
 
-static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
        struct mt_device *td = hid_get_drvdata(hdev);
        char *name;
        const char *suffix = NULL;
        struct hid_field *field = hi->report->field[0];
+       int ret;
 
-       if (hi->report->id == td->mt_report_id)
-               mt_touch_input_configured(hdev, hi);
+       if (hi->report->id == td->mt_report_id) {
+               ret = mt_touch_input_configured(hdev, hi);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
@@ -968,6 +1014,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
                case HID_DG_TOUCHSCREEN:
                        /* we do not set suffix = "Touchscreen" */
                        break;
+               case HID_DG_TOUCHPAD:
+                       suffix = "Touchpad";
+                       break;
                case HID_GD_SYSTEM_CONTROL:
                        suffix = "System Control";
                        break;
@@ -989,6 +1038,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
                        hi->input->name = name;
                }
        }
+
+       return 0;
 }
 
 static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
@@ -1026,8 +1077,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
                 * reports. Fortunately, the Win8 spec says that all touches
                 * should be sent during each report, making the initialization
                 * of input reports unnecessary.
+                *
+                * In addition some touchpads do not behave well if we read
+                * all feature reports from them. Instead we prevent
+                * initial report fetching and then selectively fetch each
+                * report we are interested in.
                 */
-               hdev->quirks |= HID_QUIRK_NO_INIT_INPUT_REPORTS;
+               hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
 
        td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
        if (!td) {
index 600f2075512ff1895852212c67a0fbcb9764566c..756d1ef9bd991d9f77df5835f0cb1f44391493ed 100644 (file)
@@ -859,14 +859,14 @@ not_claimed_input:
        return 1;
 }
 
-static void ntrig_input_configured(struct hid_device *hid,
+static int ntrig_input_configured(struct hid_device *hid,
                struct hid_input *hidinput)
 
 {
        struct input_dev *input = hidinput->input;
 
        if (hidinput->report->maxfield < 1)
-               return;
+               return 0;
 
        switch (hidinput->report->field[0]->application) {
        case HID_DG_PEN:
@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid,
                                                        "N-Trig MultiTouch";
                break;
        }
+
+       return 0;
 }
 
 static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
index e3e98ccf137b54bae52fcd5cd0ded68b839742bf..3a207c0ac0e39678da16a01e0412a391d2a22cfc 100644 (file)
@@ -427,7 +427,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
                                        pm->midi_octave = 2;
                                dbg_hid("pcmidi mode: %d octave: %d\n",
                                        pm->midi_mode, pm->midi_octave);
-                           continue;
+                               continue;
                        } else
                                key = KEY_MESSENGER;
                        break;
@@ -695,7 +695,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
        if (err < 0) {
                pk_error("failed to register pc-midi sound card: error %d\n",
                         err);
-                        goto fail_register;
+               goto fail_register;
        }
 
        dbg_hid("pcmidi_snd_initialise finished ok\n");
index 2c148129beb2f0a746f4661660be47e79421274e..67cd059a8f46cdf7dab8d73cb0edb7bd5aff1333 100644 (file)
@@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev)
        return 0;
 }
 
-static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
 {
        struct rmi_data *data = hid_get_drvdata(hdev);
        struct input_dev *input = hi->input;
@@ -1185,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
        hid_dbg(hdev, "Opening low level driver\n");
        ret = hid_hw_open(hdev);
        if (ret)
-               return;
+               return ret;
 
        if (!(data->device_flags & RMI_DEVICE))
-               return;
+               return 0;
 
        /* Allow incoming hid reports */
        hid_device_io_start(hdev);
@@ -1228,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
        input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
        input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
 
-       input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+       ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+       if (ret < 0)
+               goto exit;
 
        if (data->button_count) {
                __set_bit(EV_KEY, input->evbit);
@@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
 exit:
        hid_device_io_stop(hdev);
        hid_hw_close(hdev);
+       return ret;
 }
 
 static int rmi_input_mapping(struct hid_device *hdev,
index a014f21275d8bfada33701b4bef5013f3b81eb2a..2f84b26f116706c131abda474ab855d1aff11cfa 100644 (file)
@@ -177,6 +177,8 @@ static int saitek_event(struct hid_device *hdev, struct hid_field *field,
 static const struct hid_device_id saitek_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000),
                .driver_data = SAITEK_FIX_PS1000 },
+       { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5),
+               .driver_data = SAITEK_RELEASE_MODE_RAT7 },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD),
                .driver_data = SAITEK_RELEASE_MODE_RAT7 },
        { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
index a76eb2a0a987b33da708dbbaf581ef914901ffbd..92870cdb52d946a7408463a5b249129befd5e91d 100644 (file)
@@ -593,6 +593,20 @@ static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                }
        }
 
+       /* Checks if the report descriptor of Thinkpad Helix 2 has a logical
+        * minimum for magnetic flux axis greater than the maximum */
+       if (hdev->product == USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA &&
+               *rsize == 2558 && rdesc[913] == 0x17 && rdesc[914] == 0x40 &&
+               rdesc[915] == 0x81 && rdesc[916] == 0x08 &&
+               rdesc[917] == 0x00 && rdesc[918] == 0x27 &&
+               rdesc[921] == 0x07 && rdesc[922] == 0x00) {
+               /* Sets negative logical minimum for mag x, y and z */
+               rdesc[914] = rdesc[935] = rdesc[956] = 0xc0;
+               rdesc[915] = rdesc[936] = rdesc[957] = 0x7e;
+               rdesc[916] = rdesc[937] = rdesc[958] = 0xf7;
+               rdesc[917] = rdesc[938] = rdesc[959] = 0xff;
+       }
+
        return rdesc;
 }
 
@@ -646,8 +660,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
                                                      GFP_KERNEL);
        if (sd->hid_sensor_hub_client_devs == NULL) {
                hid_err(hdev, "Failed to allocate memory for mfd cells\n");
-                       ret = -ENOMEM;
-                       goto err_stop_hw;
+               ret = -ENOMEM;
+               goto err_stop_hw;
        }
 
        for (i = 0; i < hdev->maxcollection; ++i) {
@@ -684,8 +698,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
                                              collection->usage);
                        if (name == NULL) {
                                hid_err(hdev, "Failed MFD device name\n");
-                                       ret = -ENOMEM;
-                                       goto err_stop_hw;
+                               ret = -ENOMEM;
+                               goto err_stop_hw;
                        }
                        sd->hid_sensor_hub_client_devs[
                                sd->hid_sensor_client_cnt].name = name;
@@ -777,6 +791,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
                        USB_DEVICE_ID_ITE_LENOVO_YOGA),
                        .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
+       { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
+                       USB_DEVICE_ID_ITE_LENOVO_YOGA2),
+                       .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
        { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
                     HID_ANY_ID) },
        { }
index 661f94f8ab8b0b0aafc9dace1073b08849e23784..774cd221056659f5bacd480b8b07744c1a5a138f 100644 (file)
@@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count,
        return 0;
 }
 
-static void sony_input_configured(struct hid_device *hdev,
+static int sony_input_configured(struct hid_device *hdev,
                                        struct hid_input *hidinput)
 {
        struct sony_sc *sc = hid_get_drvdata(hdev);
+       int ret;
 
        /*
         * The Dualshock 4 touchpad supports 2 touches and has a
         * resolution of 1920x942 (44.86 dots/mm).
         */
        if (sc->quirks & DUALSHOCK4_CONTROLLER) {
-               if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0)
+               ret = sony_register_touchpad(hidinput, 2, 1920, 942);
+               if (ret) {
                        hid_err(sc->hdev,
-                               "Unable to initialize multi-touch slots\n");
+                               "Unable to initialize multi-touch slots: %d\n",
+                               ret);
+                       return ret;
+               }
        }
+
+       return 0;
 }
 
 /*
index b905d501e752d607b6fc1731ad89ff3d23ce7cd0..85ac43517e3ffc3232461f54d43054cd36a39a29 100644 (file)
@@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        return 0;
 }
 
-static void uclogic_input_configured(struct hid_device *hdev,
+static int uclogic_input_configured(struct hid_device *hdev,
                struct hid_input *hi)
 {
        char *name;
@@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev,
 
        /* no report associated (HID_QUIRK_MULTI_INPUT not set) */
        if (!hi->report)
-               return;
+               return 0;
 
        field = hi->report->field[0];
 
@@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev,
                        hi->input->name = name;
                }
        }
+
+       return 0;
 }
 
 /**
index 2871f3c81a4cceb521f4c26aac4da75466f5db6f..10bd8e6e4c9c814cbceb863bbff4a87f3d3a283a 100644 (file)
@@ -1028,6 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client,
 
        snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
                 client->name, hid->vendor, hid->product);
+       strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
 
        ret = hid_add_device(hid);
        if (ret) {
index 1dff8f0015bac2bfd76c6946bdca8d0fdd00d73d..94bb137abe3281bfb023c7bc438ad8bcf0d716a4 100644 (file)
@@ -71,6 +71,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
@@ -91,6 +92,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
+       { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
index 9a4912c1828dad3109b9473305670c79fc20d022..abb7fdf05d921eb6a71cd38333cc8f29c8790588 100644 (file)
@@ -211,7 +211,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
         * Bamboo models do not support HID_DG_CONTACTMAX.
         * And, Bamboo Pen only descriptor contains touch.
         */
-       if (features->type != BAMBOO_PT) {
+       if (features->type > BAMBOO_PT) {
                /* ISDv4 touch devices at least supports one touch point */
                if (finger && !features->touch_max)
                        features->touch_max = 1;
@@ -222,7 +222,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
                features->x_max = field->logical_maximum;
                if (finger) {
                        features->x_phy = field->physical_maximum;
-                       if (features->type != BAMBOO_PT) {
+                       if ((features->type != BAMBOO_PT) &&
+                           (features->type != BAMBOO_TOUCH)) {
                                features->unit = field->unit;
                                features->unitExpo = field->unit_exponent;
                        }
@@ -232,7 +233,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
                features->y_max = field->logical_maximum;
                if (finger) {
                        features->y_phy = field->physical_maximum;
-                       if (features->type != BAMBOO_PT) {
+                       if ((features->type != BAMBOO_PT) &&
+                           (features->type != BAMBOO_TOUCH)) {
                                features->unit = field->unit;
                                features->unitExpo = field->unit_exponent;
                        }
@@ -420,7 +422,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
                        /* MT Tablet PC touch */
                        return wacom_set_device_mode(hdev, 3, 4, 4);
                }
-               else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) {
+               else if (features->type == WACOM_24HDT) {
                        return wacom_set_device_mode(hdev, 18, 3, 2);
                }
                else if (features->type == WACOM_27QHDT) {
@@ -430,7 +432,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
                        return wacom_set_device_mode(hdev, 2, 2, 2);
                }
        } else if (features->device_type & WACOM_DEVICETYPE_PEN) {
-               if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
+               if (features->type <= BAMBOO_PT) {
                        return wacom_set_device_mode(hdev, 2, 2, 2);
                }
        }
@@ -1547,15 +1549,16 @@ static void wacom_wireless_work(struct work_struct *work)
                wacom_wac1->features =
                        *((struct wacom_features *)id->driver_data);
                wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN;
-               if (wacom_wac1->features.type != INTUOSHT &&
-                   wacom_wac1->features.type != BAMBOO_PT)
-                       wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
                wacom_set_default_phy(&wacom_wac1->features);
                wacom_calculate_res(&wacom_wac1->features);
                snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen",
                         wacom_wac1->features.name);
-               snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
-                        wacom_wac1->features.name);
+               if (wacom_wac1->features.type < BAMBOO_PEN ||
+                   wacom_wac1->features.type > BAMBOO_PT) {
+                       snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
+                                wacom_wac1->features.name);
+                       wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
+               }
                wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max;
                wacom_wac1->shared->type = wacom_wac1->features.type;
                wacom_wac1->pid = wacom_wac->pid;
@@ -1566,7 +1569,8 @@ static void wacom_wireless_work(struct work_struct *work)
 
                /* Touch interface */
                if (wacom_wac1->features.touch_max ||
-                   wacom_wac1->features.type == INTUOSHT) {
+                   (wacom_wac1->features.type >= INTUOSHT &&
+                   wacom_wac1->features.type <= BAMBOO_PT)) {
                        wacom_wac2->features =
                                *((struct wacom_features *)id->driver_data);
                        wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
@@ -1575,20 +1579,22 @@ static void wacom_wireless_work(struct work_struct *work)
                        wacom_calculate_res(&wacom_wac2->features);
                        snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX,
                                 "%s (WL) Finger",wacom_wac2->features.name);
-                       snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
-                                "%s (WL) Pad",wacom_wac2->features.name);
                        if (wacom_wac1->features.touch_max)
                                wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH;
-                       if (wacom_wac1->features.type == INTUOSHT ||
-                           wacom_wac1->features.type == BAMBOO_PT)
+                       if (wacom_wac1->features.type >= INTUOSHT &&
+                           wacom_wac1->features.type <= BAMBOO_PT) {
+                               snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
+                                        "%s (WL) Pad",wacom_wac2->features.name);
                                wacom_wac2->features.device_type |= WACOM_DEVICETYPE_PAD;
+                       }
                        wacom_wac2->pid = wacom_wac->pid;
                        error = wacom_allocate_inputs(wacom2) ||
                                wacom_register_inputs(wacom2);
                        if (error)
                                goto fail;
 
-                       if (wacom_wac1->features.type == INTUOSHT &&
+                       if ((wacom_wac1->features.type == INTUOSHT ||
+                           wacom_wac1->features.type == INTUOSHT2) &&
                            wacom_wac1->features.touch_max)
                                wacom_wac->shared->touch_input = wacom_wac2->touch_input;
                }
@@ -1772,6 +1778,24 @@ static int wacom_probe(struct hid_device *hdev,
                features->device_type |= WACOM_DEVICETYPE_PEN;
        }
 
+       /* Note that if query fails it is not a hard failure */
+       wacom_query_tablet_data(hdev, features);
+
+       /* touch only Bamboo doesn't support pen */
+       if ((features->type == BAMBOO_TOUCH) &&
+           (features->device_type & WACOM_DEVICETYPE_PEN)) {
+               error = -ENODEV;
+               goto fail_shared_data;
+       }
+
+       /* pen only Bamboo neither support touch nor pad */
+       if ((features->type == BAMBOO_PEN) &&
+           ((features->device_type & WACOM_DEVICETYPE_TOUCH) ||
+           (features->device_type & WACOM_DEVICETYPE_PAD))) {
+               error = -ENODEV;
+               goto fail_shared_data;
+       }
+
        wacom_calculate_res(features);
 
        wacom_update_name(wacom);
@@ -1809,14 +1833,12 @@ static int wacom_probe(struct hid_device *hdev,
                goto fail_hw_start;
        }
 
-       /* Note that if query fails it is not a hard failure */
-       wacom_query_tablet_data(hdev, features);
-
        if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
                error = hid_hw_open(hdev);
 
-       if (wacom_wac->features.type == INTUOSHT && 
-           wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
+       if ((wacom_wac->features.type == INTUOSHT ||
+           wacom_wac->features.type == INTUOSHT2) &&
+           (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) {
                        wacom_wac->shared->touch_input = wacom_wac->touch_input;
        }
 
index 0215ab62bb93f1b3669ed02ba1087ab43ffa6456..8b29949507d1692f436b1db5045ca7ed4b8d54f3 100644 (file)
@@ -765,13 +765,15 @@ static void wacom_intuos_general(struct wacom_wac *wacom)
        /* general pen packet */
        if ((data[1] & 0xb8) == 0xa0) {
                t = (data[6] << 2) | ((data[7] >> 6) & 3);
-               if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) {
+               if (features->pressure_max == 2047) {
                        t = (t << 1) | (data[1] & 1);
                }
                input_report_abs(input, ABS_PRESSURE, t);
-               input_report_abs(input, ABS_TILT_X,
+               if (features->type != INTUOSHT2) {
+                   input_report_abs(input, ABS_TILT_X,
                                 (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64);
-               input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+                   input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64);
+               }
                input_report_key(input, BTN_STYLUS, data[1] & 2);
                input_report_key(input, BTN_STYLUS2, data[1] & 4);
                input_report_key(input, BTN_TOUCH, t > 10);
@@ -799,6 +801,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
            data[0] != WACOM_REPORT_INTUOSREAD &&
            data[0] != WACOM_REPORT_INTUOSWRITE &&
            data[0] != WACOM_REPORT_INTUOSPAD &&
+           data[0] != WACOM_REPORT_INTUOS_PEN &&
            data[0] != WACOM_REPORT_CINTIQ &&
            data[0] != WACOM_REPORT_CINTIQPAD &&
            data[0] != WACOM_REPORT_INTUOS5PAD) {
@@ -948,6 +951,27 @@ static int wacom_intuos_irq(struct wacom_wac *wacom)
                        } else {
                                input_report_abs(input, ABS_MISC, 0);
                        }
+
+               } else if (features->type == CINTIQ_COMPANION_2) {
+                       input_report_key(input, BTN_1, (data[1] & 0x02));
+                       input_report_key(input, BTN_2, (data[2] & 0x01));
+                       input_report_key(input, BTN_3, (data[2] & 0x02));
+                       input_report_key(input, BTN_4, (data[2] & 0x04));
+                       input_report_key(input, BTN_5, (data[2] & 0x08));
+                       input_report_key(input, BTN_6, (data[1] & 0x04));
+
+                       input_report_key(input, BTN_7, (data[2] & 0x10));  /* Right  */
+                       input_report_key(input, BTN_8, (data[2] & 0x20));  /* Up         */
+                       input_report_key(input, BTN_9, (data[2] & 0x40));  /* Left   */
+                       input_report_key(input, BTN_A, (data[2] & 0x80));  /* Down   */
+                       input_report_key(input, BTN_0, (data[1] & 0x01));  /* Center */
+
+                       if (data[2] | (data[1] & 0x07)) {
+                               input_report_abs(input, ABS_MISC, PAD_DEVICE_ID);
+                       } else {
+                               input_report_abs(input, ABS_MISC, 0);
+                       }
+
                } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) {
                        int i;
 
@@ -1628,6 +1652,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
                wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0);
                break;
        case HID_DG_CONTACTCOUNT:
+               wacom_wac->hid_data.cc_report = field->report->id;
                wacom_wac->hid_data.cc_index = field->index;
                wacom_wac->hid_data.cc_value_index = usage->usage_index;
                break;
@@ -1715,7 +1740,32 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
        struct wacom_wac *wacom_wac = &wacom->wacom_wac;
        struct hid_data* hid_data = &wacom_wac->hid_data;
 
-       if (hid_data->cc_index >= 0) {
+       if (hid_data->cc_report != 0 &&
+           hid_data->cc_report != report->id) {
+               int i;
+
+               hid_data->cc_report = report->id;
+               hid_data->cc_index = -1;
+               hid_data->cc_value_index = -1;
+
+               for (i = 0; i < report->maxfield; i++) {
+                       struct hid_field *field = report->field[i];
+                       int j;
+
+                       for (j = 0; j < field->maxusage; j++) {
+                               if (field->usage[j].hid == HID_DG_CONTACTCOUNT) {
+                                       hid_data->cc_index = i;
+                                       hid_data->cc_value_index = j;
+
+                                       /* break */
+                                       i = report->maxfield;
+                                       j = field->maxusage;
+                               }
+                       }
+               }
+       }
+       if (hid_data->cc_report != 0 &&
+           hid_data->cc_index >= 0) {
                struct hid_field *field = report->field[hid_data->cc_index];
                int value = field->value[hid_data->cc_value_index];
                if (value)
@@ -1896,7 +1946,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
                int y = (data[3] << 4) | (data[4] & 0x0f);
                int width, height;
 
-               if (features->type >= INTUOSPS && features->type <= INTUOSHT) {
+               if (features->type >= INTUOSPS && features->type <= INTUOSHT2) {
                        width  = data[5] * 100;
                        height = data[6] * 100;
                } else {
@@ -1924,7 +1974,7 @@ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
        struct input_dev *input = wacom->pad_input;
        struct wacom_features *features = &wacom->features;
 
-       if (features->type == INTUOSHT) {
+       if (features->type == INTUOSHT || features->type == INTUOSHT2) {
                input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0);
                input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0);
        } else {
@@ -1939,7 +1989,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
 {
        unsigned char *data = wacom->data;
        int count = data[1] & 0x07;
-       int i;
+       int  touch_changed = 0, i;
 
        if (data[0] != 0x02)
            return 0;
@@ -1949,15 +1999,16 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
                int offset = (8 * i) + 2;
                int msg_id = data[offset];
 
-               if (msg_id >= 2 && msg_id <= 17)
+               if (msg_id >= 2 && msg_id <= 17) {
                        wacom_bpt3_touch_msg(wacom, data + offset);
-               else if (msg_id == 128)
+                       touch_changed++;
+               } else if (msg_id == 128)
                        wacom_bpt3_button_msg(wacom, data + offset);
 
        }
 
-       /* only update the touch if we actually have a touchpad */
-       if (wacom->touch_registered) {
+       /* only update touch if we actually have a touchpad and touch data changed */
+       if (wacom->touch_registered && touch_changed) {
                input_mt_sync_frame(wacom->touch_input);
                wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom);
        }
@@ -2038,7 +2089,12 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
 
 static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
 {
-       if (len == WACOM_PKGLEN_BBTOUCH)
+       struct wacom_features *features = &wacom->features;
+
+       if ((features->type == INTUOSHT2) &&
+           (features->device_type & WACOM_DEVICETYPE_PEN))
+               return wacom_intuos_irq(wacom);
+       else if (len == WACOM_PKGLEN_BBTOUCH)
                return wacom_bpt_touch(wacom);
        else if (len == WACOM_PKGLEN_BBTOUCH3)
                return wacom_bpt3_touch(wacom);
@@ -2145,7 +2201,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
        if (connected) {
                int pid, battery, charging;
 
-               if ((wacom->shared->type == INTUOSHT) &&
+               if ((wacom->shared->type == INTUOSHT ||
+                   wacom->shared->type == INTUOSHT2) &&
                    wacom->shared->touch_input &&
                    wacom->shared->touch_max) {
                        input_report_switch(wacom->shared->touch_input,
@@ -2183,7 +2240,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
        if (data[0] != WACOM_REPORT_USB)
                return 0;
 
-       if (features->type == INTUOSHT &&
+       if ((features->type == INTUOSHT ||
+           features->type == INTUOSHT2) &&
            wacom_wac->shared->touch_input &&
            features->touch_max) {
                input_report_switch(wacom_wac->shared->touch_input,
@@ -2264,6 +2322,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        case WACOM_27QHD:
        case DTK:
        case CINTIQ_HYBRID:
+       case CINTIQ_COMPANION_2:
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
@@ -2300,7 +2359,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                break;
 
        case BAMBOO_PT:
+       case BAMBOO_PEN:
+       case BAMBOO_TOUCH:
        case INTUOSHT:
+       case INTUOSHT2:
                if (wacom_wac->data[0] == WACOM_REPORT_USB)
                        sync = wacom_status_irq(wacom_wac, len);
                else
@@ -2337,22 +2399,31 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
        }
 }
 
-static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
+static void wacom_setup_basic_pro_pen(struct wacom_wac *wacom_wac)
 {
        struct input_dev *input_dev = wacom_wac->pen_input;
 
        input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
 
-       __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
        __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-       __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
-       __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
-       __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
        __set_bit(BTN_STYLUS, input_dev->keybit);
        __set_bit(BTN_STYLUS2, input_dev->keybit);
 
        input_set_abs_params(input_dev, ABS_DISTANCE,
                             0, wacom_wac->features.distance_max, 0, 0);
+}
+
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
+{
+       struct input_dev *input_dev = wacom_wac->pen_input;
+
+       wacom_setup_basic_pro_pen(wacom_wac);
+
+       __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+       __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
+       __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
+       __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
+
        input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
        input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0);
        input_abs_set_res(input_dev, ABS_TILT_X, 57);
@@ -2387,9 +2458,8 @@ void wacom_setup_device_quirks(struct wacom *wacom)
 
        /* The pen and pad share the same interface on most devices */
        if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 ||
-           features->type == DTUS || features->type == WACOM_MO ||
-           (features->type >= INTUOS3S && features->type <= WACOM_13HD && 
-            features->type != INTUOSHT)) {
+           features->type == DTUS ||
+           (features->type >= INTUOS3S && features->type <= WACOM_MO)) {
                if (features->device_type & WACOM_DEVICETYPE_PEN)
                        features->device_type |= WACOM_DEVICETYPE_PAD;
        }
@@ -2406,12 +2476,12 @@ void wacom_setup_device_quirks(struct wacom *wacom)
         * interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the
         * tablet values.
         */
-       if ((features->type >= INTUOS5S && features->type <= INTUOSHT) ||
-               (features->type == BAMBOO_PT)) {
+       if ((features->type >= INTUOS5S && features->type <= INTUOSPL) ||
+               (features->type >= INTUOSHT && features->type <= BAMBOO_PT)) {
                if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
                        if (features->touch_max)
                                features->device_type |= WACOM_DEVICETYPE_TOUCH;
-                       if (features->type == BAMBOO_PT || features->type == INTUOSHT)
+                       if (features->type >= INTUOSHT || features->type <= BAMBOO_PT)
                                features->device_type |= WACOM_DEVICETYPE_PAD;
 
                        features->x_max = 4096;
@@ -2520,6 +2590,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
        case CINTIQ:
        case WACOM_13HD:
        case CINTIQ_HYBRID:
+       case CINTIQ_COMPANION_2:
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_abs_set_res(input_dev, ABS_Z, 287);
                __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
@@ -2598,16 +2669,22 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
 
        case INTUOSHT:
        case BAMBOO_PT:
-               __clear_bit(ABS_MISC, input_dev->absbit);
-
+       case BAMBOO_PEN:
+       case INTUOSHT2:
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
-               __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
-               __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-               __set_bit(BTN_STYLUS, input_dev->keybit);
-               __set_bit(BTN_STYLUS2, input_dev->keybit);
-               input_set_abs_params(input_dev, ABS_DISTANCE, 0,
+
+               if (features->type == INTUOSHT2) {
+                       wacom_setup_basic_pro_pen(wacom_wac);
+               } else {
+                       __clear_bit(ABS_MISC, input_dev->absbit);
+                       __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+                       __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+                       __set_bit(BTN_STYLUS, input_dev->keybit);
+                       __set_bit(BTN_STYLUS2, input_dev->keybit);
+                       input_set_abs_params(input_dev, ABS_DISTANCE, 0,
                                      features->distance_max,
                                      0, 0);
+               }
                break;
        case BAMBOO_PAD:
                __clear_bit(ABS_MISC, input_dev->absbit);
@@ -2688,11 +2765,13 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
                break;
 
        case INTUOSHT:
+       case INTUOSHT2:
                input_dev->evbit[0] |= BIT_MASK(EV_SW);
                __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
                /* fall through */
 
        case BAMBOO_PT:
+       case BAMBOO_TOUCH:
                if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) {
                        input_set_abs_params(input_dev,
                                     ABS_MT_TOUCH_MAJOR,
@@ -2752,6 +2831,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
        switch (features->type) {
 
        case CINTIQ_HYBRID:
+       case CINTIQ_COMPANION_2:
        case DTK:
        case DTUS:
        case GRAPHIRE_BT:
@@ -2845,6 +2925,8 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev,
 
        case INTUOSHT:
        case BAMBOO_PT:
+       case BAMBOO_TOUCH:
+       case INTUOSHT2:
                __clear_bit(ABS_MISC, input_dev->absbit);
 
                __set_bit(BTN_LEFT, input_dev->keybit);
@@ -3235,11 +3317,10 @@ static const struct wacom_features wacom_features_0x47 =
        { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31,
          INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x84 =
-       { "Wacom Wireless Receiver", 0, 0, 0, 0,
-         WIRELESS, 0, 0, .touch_max = 16 };
+       { "Wacom Wireless Receiver", .type = WIRELESS, .touch_max = 16 };
 static const struct wacom_features wacom_features_0xD0 =
        { "Wacom Bamboo 2FG", 14720, 9200, 1023, 31,
-         BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
+         BAMBOO_TOUCH, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
 static const struct wacom_features wacom_features_0xD1 =
        { "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31,
          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -3251,10 +3332,10 @@ static const struct wacom_features wacom_features_0xD3 =
          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
 static const struct wacom_features wacom_features_0xD4 =
        { "Wacom Bamboo Pen", 14720, 9200, 1023, 31,
-         BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD5 =
        { "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31,
-         BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD6 =
        { "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31,
          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 };
@@ -3281,7 +3362,7 @@ static const struct wacom_features wacom_features_0xDF =
          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 };
 static const struct wacom_features wacom_features_0x300 =
        { "Wacom Bamboo One S", 14720, 9225, 1023, 31,
-         BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+         BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x301 =
        { "Wacom Bamboo One M", 21648, 13530, 1023, 31,
          BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -3324,14 +3405,38 @@ static const struct wacom_features wacom_features_0x318 =
 static const struct wacom_features wacom_features_0x319 =
        { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */
          .type = BAMBOO_PAD, 35, 48, .touch_max = 4 };
+static const struct wacom_features wacom_features_0x325 =
+       { "Wacom ISDv5 325", 59552, 33848, 2047, 63,
+         CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11,
+         WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET,
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 };
+static const struct wacom_features wacom_features_0x326 = /* Touch */
+       { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM,
+         .oPid = 0x325 };
 static const struct wacom_features wacom_features_0x323 =
        { "Wacom Intuos P M", 21600, 13500, 1023, 31,
          INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
          .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 static const struct wacom_features wacom_features_0x331 =
-       { "Wacom Express Key Remote", 0, 0, 0, 0,
-         REMOTE, 0, 0, 18, .check_for_hid_type = true,
+       { "Wacom Express Key Remote", .type = REMOTE,
+         .numbered_buttons = 18, .check_for_hid_type = true,
          .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33B =
+       { "Wacom Intuos S 2", 15200, 9500, 2047, 63,
+         INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33C =
+       { "Wacom Intuos PT S 2", 15200, 9500, 2047, 63,
+         INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33D =
+       { "Wacom Intuos P M 2", 21600, 13500, 2047, 63,
+         INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
+static const struct wacom_features wacom_features_0x33E =
+       { "Wacom Intuos PT M 2", 21600, 13500, 2047, 63,
+         INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16,
+         .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE };
 
 static const struct wacom_features wacom_features_HID_ANY_ID =
        { "Wacom HID", .type = HID_GENERIC };
@@ -3483,6 +3588,8 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x318) },
        { USB_DEVICE_WACOM(0x319) },
        { USB_DEVICE_WACOM(0x323) },
+       { USB_DEVICE_WACOM(0x325) },
+       { USB_DEVICE_WACOM(0x326) },
        { USB_DEVICE_WACOM(0x32A) },
        { USB_DEVICE_WACOM(0x32B) },
        { USB_DEVICE_WACOM(0x32C) },
@@ -3491,6 +3598,10 @@ const struct hid_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x333) },
        { USB_DEVICE_WACOM(0x335) },
        { USB_DEVICE_WACOM(0x336) },
+       { USB_DEVICE_WACOM(0x33B) },
+       { USB_DEVICE_WACOM(0x33C) },
+       { USB_DEVICE_WACOM(0x33D) },
+       { USB_DEVICE_WACOM(0x33E) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x4004) },
        { USB_DEVICE_WACOM(0x5000) },
index 1e270d401e181e45802cb869d30998d1017ff735..877c24a5df94ad5056983ca95c71bbe79588903f 100644 (file)
@@ -68,6 +68,7 @@
 #define WACOM_REPORT_BPAD_PEN          3
 #define WACOM_REPORT_BPAD_TOUCH                16
 #define WACOM_REPORT_DEVICE_LIST       16
+#define WACOM_REPORT_INTUOS_PEN                16
 #define WACOM_REPORT_REMOTE            17
 
 /* device quirks */
@@ -117,22 +118,26 @@ enum {
        INTUOSPS,
        INTUOSPM,
        INTUOSPL,
-       INTUOSHT,
        WACOM_21UX2,
        WACOM_22HD,
        DTK,
        WACOM_24HD,
        WACOM_27QHD,
        CINTIQ_HYBRID,
+       CINTIQ_COMPANION_2,
        CINTIQ,
        WACOM_BEE,
        WACOM_13HD,
        WACOM_MO,
-       WIRELESS,
+       BAMBOO_PEN,
+       INTUOSHT,
+       INTUOSHT2,
+       BAMBOO_TOUCH,
        BAMBOO_PT,
        WACOM_24HDT,
        WACOM_27QHDT,
        BAMBOO_PAD,
+       WIRELESS,
        REMOTE,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
@@ -198,6 +203,7 @@ struct hid_data {
        int width;
        int height;
        int id;
+       int cc_report;
        int cc_index;
        int cc_value_index;
        int num_expected;
index f17980de26629fbf65365047a0cfe8ce6034b53e..251a1d382e2325a17e0acb169d6e111589cf7444 100644 (file)
@@ -698,8 +698,8 @@ struct hid_driver {
        int (*input_mapped)(struct hid_device *hdev,
                        struct hid_input *hidinput, struct hid_field *field,
                        struct hid_usage *usage, unsigned long **bit, int *max);
-       void (*input_configured)(struct hid_device *hdev,
-                                struct hid_input *hidinput);
+       int (*input_configured)(struct hid_device *hdev,
+                               struct hid_input *hidinput);
        void (*feature_mapping)(struct hid_device *hdev,
                        struct hid_field *field,
                        struct hid_usage *usage);