Commit d64e19db authored by Jiri Kosina's avatar Jiri Kosina

Merge branches 'for-4.3/upstream-fixes', 'for-4.4/corsair',...

Merge branches 'for-4.3/upstream-fixes', 'for-4.4/corsair', 'for-4.4/dragonrise', 'for-4.4/i2c-hid', 'for-4.4/logitech', 'for-4.4/microsoft', 'for-4.4/multitouch', 'for-4.4/roccat-sysfs-deprecation', 'for-4.4/upstream' and 'for-4.4/wacom' into for-linus
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 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 Date: October 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -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. Please read binary attribute info which contains firmware version.
Users: http://roccat.sourceforge.net 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 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 Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -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. Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net 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 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 Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
...@@ -46,3 +107,39 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -46,3 +107,39 @@ Description: The mouse can store 5 profiles which can be switched by the
This file is readonly. This file is readonly.
Write control to select profile and read profile_settings instead. Write control to select profile and read profile_settings instead.
Users: http://roccat.sourceforge.net 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
...@@ -8,6 +8,17 @@ Description: The integer value of this attribute ranges from 1-4. ...@@ -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. Has never been used. If bookkeeping is done, it's done in userland tools.
Users: http://roccat.sourceforge.net 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 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 Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -40,6 +51,29 @@ Description: When read, this file returns the raw integer version number of the
Obsoleted by binary sysfs attribute "info". Obsoleted by binary sysfs attribute "info".
Users: http://roccat.sourceforge.net 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 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 Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -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. Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net 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 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 Date: January 2011
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
......
...@@ -37,6 +37,29 @@ Description: When read, this file returns the raw integer version number of the ...@@ -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. Please use binary attribute "info" which provides this information.
Users: http://roccat.sourceforge.net 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 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 Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -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. Write control to select profile and read profile_buttons instead.
Users: http://roccat.sourceforge.net 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 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 Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> 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 ...@@ -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. Write control to select profile and read profile_settings instead.
Users: http://roccat.sourceforge.net 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 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 Date: August 2010
Contact: Stefan Achatz <erazor_de@users.sourceforge.net> Contact: Stefan Achatz <erazor_de@users.sourceforge.net>
......
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.
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
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
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
...@@ -171,6 +171,16 @@ config HID_CHICONY ...@@ -171,6 +171,16 @@ config HID_CHICONY
---help--- ---help---
Support for Chicony Tactical pad. 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 config HID_PRODIKEYS
tristate "Prodikeys PC-MIDI Keyboard support" tristate "Prodikeys PC-MIDI Keyboard support"
depends on HID && SND depends on HID && SND
...@@ -672,9 +682,8 @@ config HID_SAITEK ...@@ -672,9 +682,8 @@ config HID_SAITEK
Supported devices: Supported devices:
- PS1000 Dual Analog Pad - PS1000 Dual Analog Pad
- R.A.T.9 Gaming Mouse - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice
- R.A.T.7 Gaming Mouse - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice
- M.M.O.7 Gaming Mouse
config HID_SAMSUNG config HID_SAMSUNG
tristate "Samsung InfraRed remote control or keyboards" tristate "Samsung InfraRed remote control or keyboards"
......
...@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o ...@@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
obj-$(CONFIG_HID_CHERRY) += hid-cherry.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.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_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o
......
...@@ -256,7 +256,7 @@ static int appleir_raw_event(struct hid_device *hid, struct hid_report *report, ...@@ -256,7 +256,7 @@ static int appleir_raw_event(struct hid_device *hid, struct hid_report *report,
return 0; 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 hid_input *hidinput)
{ {
struct input_dev *input_dev = hidinput->input; struct input_dev *input_dev = hidinput->input;
...@@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid, ...@@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid,
for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++)
set_bit(appleir->keymap[i], input_dev->keybit); set_bit(appleir->keymap[i], input_dev->keybit);
clear_bit(KEY_RESERVED, input_dev->keybit); clear_bit(KEY_RESERVED, input_dev->keybit);
return 0;
} }
static int appleir_input_mapping(struct hid_device *hid, static int appleir_input_mapping(struct hid_device *hid,
......
...@@ -23,7 +23,8 @@ static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -23,7 +23,8 @@ static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc,
if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { 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"); dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n");
rdesc[53] = 0x65; rdesc[53] = 0x65;
} return rdesc; }
return rdesc;
} }
static const struct hid_device_id aureal_devices[] = { static const struct hid_device_id aureal_devices[] = {
......
...@@ -725,6 +725,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) ...@@ -725,6 +725,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
if (hid->vendor == USB_VENDOR_ID_MICROSOFT && 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 ||
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_PRO_3_JP ||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
hid->product == USB_DEVICE_ID_MS_POWER_COVER) && hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
...@@ -1678,6 +1679,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) ...@@ -1678,6 +1679,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
case BUS_BLUETOOTH: case BUS_BLUETOOTH:
bus = "BLUETOOTH"; bus = "BLUETOOTH";
break; break;
case BUS_I2C:
bus = "I2C";
break;
default: default:
bus = "<UNKNOWN>"; bus = "<UNKNOWN>";
} }
...@@ -1828,6 +1832,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -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_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { 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_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_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, { 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) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
...@@ -1896,6 +1901,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1896,6 +1901,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
...@@ -1928,6 +1934,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1928,6 +1934,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_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_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) },
{ 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_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_TYPE_COVER_3) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) },
...@@ -1981,6 +1988,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1981,6 +1988,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_OLD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, { 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_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) }, { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
#endif #endif
{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
......
This diff is collapsed.
...@@ -234,6 +234,58 @@ static __u8 pid0011_rdesc_fixed[] = { ...@@ -234,6 +234,58 @@ static __u8 pid0011_rdesc_fixed[] = {
0xC0 /* End Collection */ 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, static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
unsigned int *rsize) unsigned int *rsize)
{ {
...@@ -244,6 +296,12 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -244,6 +296,12 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
*rsize = sizeof(pid0011_rdesc_fixed); *rsize = sizeof(pid0011_rdesc_fixed);
} }
break; break;
case 0x0006:
if (*rsize == sizeof(pid0006_rdesc_fixed)) {
rdesc = pid0006_rdesc_fixed;
*rsize = sizeof(pid0006_rdesc_fixed);
}
break;
} }
return rdesc; return rdesc;
} }
......
...@@ -37,7 +37,7 @@ static bool use_fw_quirk = true; ...@@ -37,7 +37,7 @@ static bool use_fw_quirk = true;
module_param(use_fw_quirk, bool, S_IRUGO); module_param(use_fw_quirk, bool, S_IRUGO);
MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); 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 hid_input *hidinput)
{ {
struct input_dev *input = hidinput->input; struct input_dev *input = hidinput->input;
...@@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev, ...@@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev,
set_bit(BTN_TOUCH, input->keybit); set_bit(BTN_TOUCH, input->keybit);
set_bit(ABS_PRESSURE, input->absbit); set_bit(ABS_PRESSURE, input->absbit);
input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); 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) static void elo_process_data(struct input_dev *input, const u8 *data, int size)
......
...@@ -251,6 +251,9 @@ ...@@ -251,6 +251,9 @@
#define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500
#define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff #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_VENDOR_ID_CREATIVELABS 0x041e
#define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801
...@@ -648,6 +651,7 @@ ...@@ -648,6 +651,7 @@
#define USB_VENDOR_ID_MADCATZ 0x0738 #define USB_VENDOR_ID_MADCATZ 0x0738
#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
#define USB_DEVICE_ID_MADCATZ_RAT5 0x1705
#define USB_DEVICE_ID_MADCATZ_RAT9 0x1709 #define USB_DEVICE_ID_MADCATZ_RAT9 0x1709
#define USB_VENDOR_ID_MCC 0x09db #define USB_VENDOR_ID_MCC 0x09db
...@@ -681,6 +685,7 @@ ...@@ -681,6 +685,7 @@
#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #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_2 0x07a9
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc #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_PRO_3_JP 0x07dd
#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da #define USB_DEVICE_ID_MS_POWER_COVER 0x07da
......
...@@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
* UGCI) cram a lot of unrelated inputs into the * UGCI) cram a lot of unrelated inputs into the
* same interface. */ * same interface. */
hidinput->report = report; hidinput->report = report;
if (drv->input_configured) if (drv->input_configured &&
drv->input_configured(hid, hidinput); drv->input_configured(hid, hidinput))
goto out_cleanup;
if (input_register_device(hidinput->input)) if (input_register_device(hidinput->input))
goto out_cleanup; goto out_cleanup;
hidinput = NULL; hidinput = NULL;
...@@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) ...@@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
} }
if (hidinput) { if (hidinput) {
if (drv->input_configured) if (drv->input_configured &&
drv->input_configured(hid, hidinput); drv->input_configured(hid, hidinput))
goto out_cleanup;
if (input_register_device(hidinput->input)) if (input_register_device(hidinput->input))
goto out_cleanup; goto out_cleanup;
} }
......
...@@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev) ...@@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev)
hid_hw_stop(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) struct hid_input *hi)
{ {
switch (hdev->product) { switch (hdev->product) {
...@@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev, ...@@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev,
} }
break; break;
} }
return 0;
} }
......
...@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, ...@@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi,
usage->code == ABS_Y || usage->code == ABS_Z || usage->code == ABS_Y || usage->code == ABS_Z ||
usage->code == ABS_RZ)) { usage->code == ABS_RZ)) {
switch (hdev->product) { switch (hdev->product) {
case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
case USB_DEVICE_ID_LOGITECH_WHEEL: case USB_DEVICE_ID_LOGITECH_WHEEL:
case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
...@@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field, ...@@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
{ {
struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
unsigned int connect_mask = HID_CONNECT_DEFAULT; unsigned int connect_mask = HID_CONNECT_DEFAULT;
struct lg_drv_data *drv_data; struct lg_drv_data *drv_data;
int ret; int ret;
/* Only work with the 1st interface (G29 presents multiple) */
if (iface_num != 0) {
dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
return -ENODEV;
}
drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
if (!drv_data) { if (!drv_data) {
hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
......
...@@ -45,7 +45,8 @@ ...@@ -45,7 +45,8 @@
#define LG4FF_MODE_G25_IDX 3 #define LG4FF_MODE_G25_IDX 3
#define LG4FF_MODE_DFGT_IDX 4 #define LG4FF_MODE_DFGT_IDX 4
#define LG4FF_MODE_G27_IDX 5 #define LG4FF_MODE_G27_IDX 5
#define LG4FF_MODE_MAX_IDX 6 #define LG4FF_MODE_G29_IDX 6
#define LG4FF_MODE_MAX_IDX 7
#define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX) #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX)
#define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX) #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX)
...@@ -53,6 +54,7 @@ ...@@ -53,6 +54,7 @@
#define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX) #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX)
#define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX) #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX)
#define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX) #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX)
#define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX)
#define LG4FF_DFEX_TAG "DF-EX" #define LG4FF_DFEX_TAG "DF-EX"
#define LG4FF_DFEX_NAME "Driving Force / Formula EX" #define LG4FF_DFEX_NAME "Driving Force / Formula EX"
...@@ -62,6 +64,8 @@ ...@@ -62,6 +64,8 @@
#define LG4FF_G25_NAME "G25 Racing Wheel" #define LG4FF_G25_NAME "G25 Racing Wheel"
#define LG4FF_G27_TAG "G27" #define LG4FF_G27_TAG "G27"
#define LG4FF_G27_NAME "G27 Racing Wheel" #define LG4FF_G27_NAME "G27 Racing Wheel"
#define LG4FF_G29_TAG "G29"
#define LG4FF_G29_NAME "G29 Racing Wheel"
#define LG4FF_DFGT_TAG "DFGT" #define LG4FF_DFGT_TAG "DFGT"
#define LG4FF_DFGT_NAME "Driving Force GT" #define LG4FF_DFGT_NAME "Driving Force GT"
...@@ -114,16 +118,12 @@ struct lg4ff_compat_mode_switch { ...@@ -114,16 +118,12 @@ struct lg4ff_compat_mode_switch {
}; };
struct lg4ff_wheel_ident_info { struct lg4ff_wheel_ident_info {
const u32 modes;
const u16 mask; const u16 mask;
const u16 result; const u16 result;
const u16 real_product_id; const u16 real_product_id;
}; };
struct lg4ff_wheel_ident_checklist {
const u32 count;
const struct lg4ff_wheel_ident_info *models[];
};
struct lg4ff_multimode_wheel { struct lg4ff_multimode_wheel {
const u16 product_id; const u16 product_id;
const u32 alternate_modes; const u32 alternate_modes;
...@@ -144,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = { ...@@ -144,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = {
{USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_G29_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25},
{USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL},
{USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}
}; };
...@@ -161,6 +162,9 @@ static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = { ...@@ -161,6 +162,9 @@ static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = {
{USB_DEVICE_ID_LOGITECH_G27_WHEEL, {USB_DEVICE_ID_LOGITECH_G27_WHEEL,
LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
LG4FF_G27_TAG, LG4FF_G27_NAME}, LG4FF_G27_TAG, LG4FF_G27_NAME},
{USB_DEVICE_ID_LOGITECH_G29_WHEEL,
LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
LG4FF_G29_TAG, LG4FF_G29_NAME},
}; };
static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
...@@ -169,41 +173,61 @@ static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { ...@@ -169,41 +173,61 @@ static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = {
[LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME}, [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME},
[LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME}, [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME},
[LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME}, [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME},
[LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME} [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME},
[LG4FF_MODE_G29_IDX] = {USB_DEVICE_ID_LOGITECH_G29_WHEEL, LG4FF_G29_TAG, LG4FF_G29_NAME},
}; };
/* Multimode wheel identificators */ /* Multimode wheel identificators */
static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = { static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = {
LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xf000, 0xf000,
0x1000, 0x1000,
USB_DEVICE_ID_LOGITECH_DFP_WHEEL USB_DEVICE_ID_LOGITECH_DFP_WHEEL
}; };
static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = { static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = {
LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00, 0xff00,
0x1200, 0x1200,
USB_DEVICE_ID_LOGITECH_G25_WHEEL USB_DEVICE_ID_LOGITECH_G25_WHEEL
}; };
static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = { static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = {
LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xfff0, 0xfff0,
0x1230, 0x1230,
USB_DEVICE_ID_LOGITECH_G27_WHEEL USB_DEVICE_ID_LOGITECH_G27_WHEEL
}; };
static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = { static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = {
LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00, 0xff00,
0x1300, 0x1300,
USB_DEVICE_ID_LOGITECH_DFGT_WHEEL USB_DEVICE_ID_LOGITECH_DFGT_WHEEL
}; };
static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info = {
LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xfff8,
0x1350,
USB_DEVICE_ID_LOGITECH_G29_WHEEL
};
static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info2 = {
LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX,
0xff00,
0x8900,
USB_DEVICE_ID_LOGITECH_G29_WHEEL
};
/* Multimode wheel identification checklists */ /* Multimode wheel identification checklists */
static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = { static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = {
4, &lg4ff_g29_ident_info,
{&lg4ff_dfgt_ident_info, &lg4ff_g29_ident_info2,
&lg4ff_dfgt_ident_info,
&lg4ff_g27_ident_info, &lg4ff_g27_ident_info,
&lg4ff_g25_ident_info, &lg4ff_g25_ident_info,
&lg4ff_dfp_ident_info} &lg4ff_dfp_ident_info
}; };
/* Compatibility mode switching commands */ /* Compatibility mode switching commands */
...@@ -238,6 +262,12 @@ static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = { ...@@ -238,6 +262,12 @@ static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = {
0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */ 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */
}; };
static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g29 = {
2,
{0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */
0xf8, 0x09, 0x05, 0x01, 0x01, 0x00, 0x00} /* Switch mode to G29 with detach */
};
/* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */ /* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */
static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = { static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = {
1, 1,
...@@ -651,6 +681,23 @@ static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(cons ...@@ -651,6 +681,23 @@ static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(cons
return NULL; return NULL;
} }
break; break;
case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
switch (target_product_id) {
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
return &lg4ff_mode_switch_ext09_dfp;
case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
return &lg4ff_mode_switch_ext09_dfgt;
case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
return &lg4ff_mode_switch_ext09_g25;
case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
return &lg4ff_mode_switch_ext09_g27;
case USB_DEVICE_ID_LOGITECH_G29_WHEEL:
return &lg4ff_mode_switch_ext09_g29;
/* G29 can only be switched to DF-EX, DFP, DFGT, G25, G27 or its native mode */
default:
return NULL;
}
break;
case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
switch (target_product_id) { switch (target_product_id) {
case USB_DEVICE_ID_LOGITECH_WHEEL: case USB_DEVICE_ID_LOGITECH_WHEEL:
...@@ -1037,41 +1084,28 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde ...@@ -1037,41 +1084,28 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde
static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice) static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice)
{ {
const struct lg4ff_wheel_ident_checklist *checklist; u32 current_mode;
int i, from_idx, to_idx; int i;
switch (reported_product_id) { /* identify current mode from USB PID */
case USB_DEVICE_ID_LOGITECH_WHEEL: for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) {
case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: dbg_hid("Testing whether PID is %X\n", lg4ff_alternate_modes[i].product_id);
checklist = &lg4ff_main_checklist; if (reported_product_id == lg4ff_alternate_modes[i].product_id)
from_idx = 0;
to_idx = checklist->count - 1;
break;
case USB_DEVICE_ID_LOGITECH_G25_WHEEL:
checklist = &lg4ff_main_checklist;
from_idx = 0;
to_idx = checklist->count - 2; /* End identity check at G25 */
break; break;
case USB_DEVICE_ID_LOGITECH_G27_WHEEL:
checklist = &lg4ff_main_checklist;
from_idx = 1; /* Start identity check at G27 */
to_idx = checklist->count - 3; /* End identity check at G27 */
break;
case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL:
checklist = &lg4ff_main_checklist;
from_idx = 0;
to_idx = checklist->count - 4; /* End identity check at DFGT */
break;
default:
return 0;
} }
for (i = from_idx; i <= to_idx; i++) { if (i == ARRAY_SIZE(lg4ff_alternate_modes))
const u16 mask = checklist->models[i]->mask; return 0;
const u16 result = checklist->models[i]->result;
const u16 real_product_id = checklist->models[i]->real_product_id; current_mode = BIT(i);
for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) {
const u16 mask = lg4ff_main_checklist[i]->mask;
const u16 result = lg4ff_main_checklist[i]->result;
const u16 real_product_id = lg4ff_main_checklist[i]->real_product_id;
if ((bcdDevice & mask) == result) { if ((current_mode & lg4ff_main_checklist[i]->modes) && \
(bcdDevice & mask) == result) {
dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id); dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id);
return real_product_id; return real_product_id;
} }
...@@ -1246,12 +1280,13 @@ int lg4ff_init(struct hid_device *hid) ...@@ -1246,12 +1280,13 @@ int lg4ff_init(struct hid_device *hid)
entry->wdata.set_range(hid, entry->wdata.range); entry->wdata.set_range(hid, entry->wdata.range);
#ifdef CONFIG_LEDS_CLASS #ifdef CONFIG_LEDS_CLASS
/* register led subsystem - G27 only */ /* register led subsystem - G27/G29 only */
entry->wdata.led_state = 0; entry->wdata.led_state = 0;
for (j = 0; j < 5; j++) for (j = 0; j < 5; j++)
entry->wdata.led[j] = NULL; entry->wdata.led[j] = NULL;
if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) { if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL ||
lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G29_WHEEL) {
struct led_classdev *led; struct led_classdev *led;
size_t name_sz; size_t name_sz;
char *name; char *name;
......
...@@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644); ...@@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644);
MODULE_PARM_DESC(disable_raw_mode, MODULE_PARM_DESC(disable_raw_mode,
"Disable Raw mode reporting for touchpads and keep firmware gestures."); "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_SHORT 0x10
#define REPORT_ID_HIDPP_LONG 0x11 #define REPORT_ID_HIDPP_LONG 0x11
...@@ -41,10 +46,15 @@ MODULE_PARM_DESC(disable_raw_mode, ...@@ -41,10 +46,15 @@ MODULE_PARM_DESC(disable_raw_mode,
#define HIDPP_QUIRK_CLASS_WTP BIT(0) #define HIDPP_QUIRK_CLASS_WTP BIT(0)
#define HIDPP_QUIRK_CLASS_M560 BIT(1) #define HIDPP_QUIRK_CLASS_M560 BIT(1)
#define HIDPP_QUIRK_CLASS_K400 BIT(2)
/* bits 2..20 are reserved for classes */ /* 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_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 * 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) ...@@ -552,6 +562,52 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp)
return name; 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 */ /* 0x6100: TouchPadRawXY */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
...@@ -1132,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -1132,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return -1; 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 */ /* Generic HID++ devices */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
...@@ -1160,13 +1285,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, ...@@ -1160,13 +1285,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,
m560_populate_input(hidpp, input, origin_is_hid_core); 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 hid_input *hidinput)
{ {
struct hidpp_device *hidpp = hid_get_drvdata(hdev); struct hidpp_device *hidpp = hid_get_drvdata(hdev);
struct input_dev *input = hidinput->input; struct input_dev *input = hidinput->input;
hidpp_populate_input(hidpp, input, true); hidpp_populate_input(hidpp, input, true);
return 0;
} }
static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, 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, ...@@ -1203,7 +1330,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
if (unlikely(hidpp_report_is_connect_event(report))) { if (unlikely(hidpp_report_is_connect_event(report))) {
atomic_set(&hidpp->connected, atomic_set(&hidpp->connected,
!(report->rap.params[0] & (1 << 6))); !(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)) (schedule_work(&hidpp->work) == 0))
dbg_hid("%s: connect event already queued\n", __func__); dbg_hid("%s: connect event already queued\n", __func__);
return 1; return 1;
...@@ -1328,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ...@@ -1328,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
ret = m560_send_config_command(hdev, connected); ret = m560_send_config_command(hdev, connected);
if (ret) if (ret)
return; return;
} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
ret = k400_connect(hdev, connected);
if (ret)
return;
} }
if (!connected || hidpp->delayed_input) if (!connected || hidpp->delayed_input)
return; return;
/* the device is already connected, we can ask for its name and
* protocol */
if (!hidpp->protocol_major) { if (!hidpp->protocol_major) {
ret = !hidpp_is_connected(hidpp); ret = !hidpp_is_connected(hidpp);
if (ret) { if (ret) {
hid_err(hdev, "Can not get the protocol version.\n"); hid_err(hdev, "Can not get the protocol version.\n");
return; return;
} }
}
/* the device is already connected, we can ask for its name and
* protocol */
hid_info(hdev, "HID++ %u.%u device connected.\n", hid_info(hdev, "HID++ %u.%u device connected.\n",
hidpp->protocol_major, hidpp->protocol_minor); 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) { if (!hidpp->name || hidpp->name == hdev->name) {
name = hidpp_get_device_name(hidpp); name = hidpp_get_device_name(hidpp);
...@@ -1397,7 +1531,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1397,7 +1531,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (disable_raw_mode) { if (disable_raw_mode) {
hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; 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) { 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) ...@@ -1408,6 +1543,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
ret = m560_allocate(hdev); ret = m560_allocate(hdev);
if (ret) if (ret)
goto allocate_fail; 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); 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) ...@@ -1448,7 +1587,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
/* Block incoming packets */ /* Block incoming packets */
hid_device_io_stop(hdev); hid_device_io_stop(hdev);
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)
connect_mask &= ~HID_CONNECT_HIDINPUT; connect_mask &= ~HID_CONNECT_HIDINPUT;
ret = hid_hw_start(hdev, connect_mask); 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) ...@@ -1457,7 +1596,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto hid_hw_start_fail; goto hid_hw_start_fail;
} }
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) { if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) {
/* Allow incoming packets */ /* Allow incoming packets */
hid_device_io_start(hdev); hid_device_io_start(hdev);
...@@ -1502,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -1502,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = {
HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
USB_VENDOR_ID_LOGITECH, 0x402d), USB_VENDOR_ID_LOGITECH, 0x402d),
.driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, .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, { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE,
USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},
......
...@@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev, ...@@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
return 0; 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 hid_input *hi)
{ {
struct magicmouse_sc *msc = hid_get_drvdata(hdev); 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) { if (ret) {
hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
/* clean msc->input to notify probe() of the failure */ /* clean msc->input to notify probe() of the failure */
msc->input = NULL; msc->input = NULL;
return ret;
} }
return 0;
} }
......
...@@ -278,6 +278,8 @@ static const struct hid_device_id ms_devices[] = { ...@@ -278,6 +278,8 @@ static const struct hid_device_id ms_devices[] = {
.driver_data = MS_DUPLICATE_USAGES }, .driver_data = MS_DUPLICATE_USAGES },
{ 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),
.driver_data = MS_HIDINPUT }, .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), { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
.driver_data = MS_HIDINPUT }, .driver_data = MS_HIDINPUT },
{ 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_TYPE_COVER_3),
......
...@@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = { ...@@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = {
.attrs = sysfs_attrs .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, static void mt_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage) struct hid_field *field, struct hid_usage *usage)
{ {
...@@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev, ...@@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev,
break; break;
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
mt_get_feature(hdev, field->report);
td->maxcontact_report_id = field->report->id; td->maxcontact_report_id = field->report->id;
td->maxcontacts = field->value[0]; td->maxcontacts = field->value[0];
if (!td->maxcontacts && if (!td->maxcontacts &&
...@@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev, ...@@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev,
break; break;
} }
mt_get_feature(hdev, field->report);
if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD) if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
td->is_buttonpad = true; td->is_buttonpad = true;
...@@ -725,12 +763,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) ...@@ -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); 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 hid_input *hi)
{ {
struct mt_device *td = hid_get_drvdata(hdev); struct mt_device *td = hid_get_drvdata(hdev);
struct mt_class *cls = &td->mtclass; struct mt_class *cls = &td->mtclass;
struct input_dev *input = hi->input; struct input_dev *input = hi->input;
int ret;
if (!td->maxcontacts) if (!td->maxcontacts)
td->maxcontacts = MT_DEFAULT_MAXCONTACT; td->maxcontacts = MT_DEFAULT_MAXCONTACT;
...@@ -752,9 +791,12 @@ static void mt_touch_input_configured(struct hid_device *hdev, ...@@ -752,9 +791,12 @@ static void mt_touch_input_configured(struct hid_device *hdev,
if (td->is_buttonpad) if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit); __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; td->mt_flags = 0;
return 0;
} }
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, 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) ...@@ -930,15 +972,19 @@ static void mt_post_parse(struct mt_device *td)
cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; 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); struct mt_device *td = hid_get_drvdata(hdev);
char *name; char *name;
const char *suffix = NULL; const char *suffix = NULL;
struct hid_field *field = hi->report->field[0]; struct hid_field *field = hi->report->field[0];
int ret;
if (hi->report->id == td->mt_report_id) if (hi->report->id == td->mt_report_id) {
mt_touch_input_configured(hdev, hi); ret = mt_touch_input_configured(hdev, hi);
if (ret)
return ret;
}
/* /*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" * 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) ...@@ -968,6 +1014,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
case HID_DG_TOUCHSCREEN: case HID_DG_TOUCHSCREEN:
/* we do not set suffix = "Touchscreen" */ /* we do not set suffix = "Touchscreen" */
break; break;
case HID_DG_TOUCHPAD:
suffix = "Touchpad";
break;
case HID_GD_SYSTEM_CONTROL: case HID_GD_SYSTEM_CONTROL:
suffix = "System Control"; suffix = "System Control";
break; break;
...@@ -989,6 +1038,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -989,6 +1038,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
hi->input->name = name; hi->input->name = name;
} }
} }
return 0;
} }
static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 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) ...@@ -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 * reports. Fortunately, the Win8 spec says that all touches
* should be sent during each report, making the initialization * should be sent during each report, making the initialization
* of input reports unnecessary. * 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); td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL);
if (!td) { if (!td) {
......
...@@ -859,14 +859,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, ...@@ -859,14 +859,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field,
return 1; 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 hid_input *hidinput)
{ {
struct input_dev *input = hidinput->input; struct input_dev *input = hidinput->input;
if (hidinput->report->maxfield < 1) if (hidinput->report->maxfield < 1)
return; return 0;
switch (hidinput->report->field[0]->application) { switch (hidinput->report->field[0]->application) {
case HID_DG_PEN: case HID_DG_PEN:
...@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid, ...@@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid,
"N-Trig MultiTouch"; "N-Trig MultiTouch";
break; break;
} }
return 0;
} }
static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id)
......
...@@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev) ...@@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev)
return 0; 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 rmi_data *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input; struct input_dev *input = hi->input;
...@@ -1185,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -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"); hid_dbg(hdev, "Opening low level driver\n");
ret = hid_hw_open(hdev); ret = hid_hw_open(hdev);
if (ret) if (ret)
return; return ret;
if (!(data->device_flags & RMI_DEVICE)) if (!(data->device_flags & RMI_DEVICE))
return; return 0;
/* Allow incoming hid reports */ /* Allow incoming hid reports */
hid_device_io_start(hdev); hid_device_io_start(hdev);
...@@ -1228,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -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_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 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) { if (data->button_count) {
__set_bit(EV_KEY, input->evbit); __set_bit(EV_KEY, input->evbit);
...@@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
exit: exit:
hid_device_io_stop(hdev); hid_device_io_stop(hdev);
hid_hw_close(hdev); hid_hw_close(hdev);
return ret;
} }
static int rmi_input_mapping(struct hid_device *hdev, static int rmi_input_mapping(struct hid_device *hdev,
......
...@@ -177,6 +177,8 @@ static int saitek_event(struct hid_device *hdev, struct hid_field *field, ...@@ -177,6 +177,8 @@ static int saitek_event(struct hid_device *hdev, struct hid_field *field,
static const struct hid_device_id saitek_devices[] = { static const struct hid_device_id saitek_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000),
.driver_data = SAITEK_FIX_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), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD),
.driver_data = SAITEK_RELEASE_MODE_RAT7 }, .driver_data = SAITEK_RELEASE_MODE_RAT7 },
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7),
......
...@@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count, ...@@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count,
return 0; 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 hid_input *hidinput)
{ {
struct sony_sc *sc = hid_get_drvdata(hdev); struct sony_sc *sc = hid_get_drvdata(hdev);
int ret;
/* /*
* The Dualshock 4 touchpad supports 2 touches and has a * The Dualshock 4 touchpad supports 2 touches and has a
* resolution of 1920x942 (44.86 dots/mm). * resolution of 1920x942 (44.86 dots/mm).
*/ */
if (sc->quirks & DUALSHOCK4_CONTROLLER) { 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, hid_err(sc->hdev,
"Unable to initialize multi-touch slots\n"); "Unable to initialize multi-touch slots: %d\n",
ret);
return ret;
} }
}
return 0;
} }
/* /*
......
...@@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, ...@@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi,
return 0; return 0;
} }
static void uclogic_input_configured(struct hid_device *hdev, static int uclogic_input_configured(struct hid_device *hdev,
struct hid_input *hi) struct hid_input *hi)
{ {
char *name; char *name;
...@@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev, ...@@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev,
/* no report associated (HID_QUIRK_MULTI_INPUT not set) */ /* no report associated (HID_QUIRK_MULTI_INPUT not set) */
if (!hi->report) if (!hi->report)
return; return 0;
field = hi->report->field[0]; field = hi->report->field[0];
...@@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev, ...@@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev,
hi->input->name = name; hi->input->name = name;
} }
} }
return 0;
} }
/** /**
......
...@@ -1028,6 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client, ...@@ -1028,6 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client,
snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX",
client->name, hid->vendor, hid->product); client->name, hid->vendor, hid->product);
strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys));
ret = hid_add_device(hid); ret = hid_add_device(hid);
if (ret) { if (ret) {
......
...@@ -92,6 +92,7 @@ static const struct hid_blacklist { ...@@ -92,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_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_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, 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_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_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
......
...@@ -211,7 +211,7 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -211,7 +211,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
* Bamboo models do not support HID_DG_CONTACTMAX. * Bamboo models do not support HID_DG_CONTACTMAX.
* And, Bamboo Pen only descriptor contains touch. * 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 */ /* ISDv4 touch devices at least supports one touch point */
if (finger && !features->touch_max) if (finger && !features->touch_max)
features->touch_max = 1; features->touch_max = 1;
...@@ -222,7 +222,8 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -222,7 +222,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
features->x_max = field->logical_maximum; features->x_max = field->logical_maximum;
if (finger) { if (finger) {
features->x_phy = field->physical_maximum; 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->unit = field->unit;
features->unitExpo = field->unit_exponent; features->unitExpo = field->unit_exponent;
} }
...@@ -232,7 +233,8 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -232,7 +233,8 @@ static void wacom_usage_mapping(struct hid_device *hdev,
features->y_max = field->logical_maximum; features->y_max = field->logical_maximum;
if (finger) { if (finger) {
features->y_phy = field->physical_maximum; 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->unit = field->unit;
features->unitExpo = field->unit_exponent; features->unitExpo = field->unit_exponent;
} }
...@@ -420,7 +422,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, ...@@ -420,7 +422,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
/* MT Tablet PC touch */ /* MT Tablet PC touch */
return wacom_set_device_mode(hdev, 3, 4, 4); 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); return wacom_set_device_mode(hdev, 18, 3, 2);
} }
else if (features->type == WACOM_27QHDT) { else if (features->type == WACOM_27QHDT) {
...@@ -430,7 +432,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, ...@@ -430,7 +432,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev,
return wacom_set_device_mode(hdev, 2, 2, 2); return wacom_set_device_mode(hdev, 2, 2, 2);
} }
} else if (features->device_type & WACOM_DEVICETYPE_PEN) { } 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); return wacom_set_device_mode(hdev, 2, 2, 2);
} }
} }
...@@ -1547,15 +1549,16 @@ static void wacom_wireless_work(struct work_struct *work) ...@@ -1547,15 +1549,16 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_wac1->features = wacom_wac1->features =
*((struct wacom_features *)id->driver_data); *((struct wacom_features *)id->driver_data);
wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN; 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_set_default_phy(&wacom_wac1->features);
wacom_calculate_res(&wacom_wac1->features); wacom_calculate_res(&wacom_wac1->features);
snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen", snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name); 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", snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
wacom_wac1->features.name); 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->touch_max = wacom_wac1->features.touch_max;
wacom_wac1->shared->type = wacom_wac1->features.type; wacom_wac1->shared->type = wacom_wac1->features.type;
wacom_wac1->pid = wacom_wac->pid; wacom_wac1->pid = wacom_wac->pid;
...@@ -1566,7 +1569,8 @@ static void wacom_wireless_work(struct work_struct *work) ...@@ -1566,7 +1569,8 @@ static void wacom_wireless_work(struct work_struct *work)
/* Touch interface */ /* Touch interface */
if (wacom_wac1->features.touch_max || 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 = wacom_wac2->features =
*((struct wacom_features *)id->driver_data); *((struct wacom_features *)id->driver_data);
wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
...@@ -1575,20 +1579,22 @@ static void wacom_wireless_work(struct work_struct *work) ...@@ -1575,20 +1579,22 @@ static void wacom_wireless_work(struct work_struct *work)
wacom_calculate_res(&wacom_wac2->features); wacom_calculate_res(&wacom_wac2->features);
snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX, snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX,
"%s (WL) Finger",wacom_wac2->features.name); "%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) if (wacom_wac1->features.touch_max)
wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH;
if (wacom_wac1->features.type == INTUOSHT || if (wacom_wac1->features.type >= INTUOSHT &&
wacom_wac1->features.type == BAMBOO_PT) 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->features.device_type |= WACOM_DEVICETYPE_PAD;
}
wacom_wac2->pid = wacom_wac->pid; wacom_wac2->pid = wacom_wac->pid;
error = wacom_allocate_inputs(wacom2) || error = wacom_allocate_inputs(wacom2) ||
wacom_register_inputs(wacom2); wacom_register_inputs(wacom2);
if (error) if (error)
goto fail; 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_wac1->features.touch_max)
wacom_wac->shared->touch_input = wacom_wac2->touch_input; wacom_wac->shared->touch_input = wacom_wac2->touch_input;
} }
...@@ -1812,11 +1818,27 @@ static int wacom_probe(struct hid_device *hdev, ...@@ -1812,11 +1818,27 @@ static int wacom_probe(struct hid_device *hdev,
/* Note that if query fails it is not a hard failure */ /* Note that if query fails it is not a hard failure */
wacom_query_tablet_data(hdev, features); 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_hw_start;
}
/* 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_hw_start;
}
if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR)
error = hid_hw_open(hdev); error = hid_hw_open(hdev);
if (wacom_wac->features.type == INTUOSHT && if ((wacom_wac->features.type == INTUOSHT ||
wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { wacom_wac->features.type == INTUOSHT2) &&
(wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) {
wacom_wac->shared->touch_input = wacom_wac->touch_input; wacom_wac->shared->touch_input = wacom_wac->touch_input;
} }
......
This diff is collapsed.
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#define WACOM_REPORT_BPAD_PEN 3 #define WACOM_REPORT_BPAD_PEN 3
#define WACOM_REPORT_BPAD_TOUCH 16 #define WACOM_REPORT_BPAD_TOUCH 16
#define WACOM_REPORT_DEVICE_LIST 16 #define WACOM_REPORT_DEVICE_LIST 16
#define WACOM_REPORT_INTUOS_PEN 16
#define WACOM_REPORT_REMOTE 17 #define WACOM_REPORT_REMOTE 17
/* device quirks */ /* device quirks */
...@@ -117,22 +118,26 @@ enum { ...@@ -117,22 +118,26 @@ enum {
INTUOSPS, INTUOSPS,
INTUOSPM, INTUOSPM,
INTUOSPL, INTUOSPL,
INTUOSHT,
WACOM_21UX2, WACOM_21UX2,
WACOM_22HD, WACOM_22HD,
DTK, DTK,
WACOM_24HD, WACOM_24HD,
WACOM_27QHD, WACOM_27QHD,
CINTIQ_HYBRID, CINTIQ_HYBRID,
CINTIQ_COMPANION_2,
CINTIQ, CINTIQ,
WACOM_BEE, WACOM_BEE,
WACOM_13HD, WACOM_13HD,
WACOM_MO, WACOM_MO,
WIRELESS, BAMBOO_PEN,
INTUOSHT,
INTUOSHT2,
BAMBOO_TOUCH,
BAMBOO_PT, BAMBOO_PT,
WACOM_24HDT, WACOM_24HDT,
WACOM_27QHDT, WACOM_27QHDT,
BAMBOO_PAD, BAMBOO_PAD,
WIRELESS,
REMOTE, REMOTE,
TABLETPC, /* add new TPC below */ TABLETPC, /* add new TPC below */
TABLETPCE, TABLETPCE,
......
...@@ -698,7 +698,7 @@ struct hid_driver { ...@@ -698,7 +698,7 @@ struct hid_driver {
int (*input_mapped)(struct hid_device *hdev, int (*input_mapped)(struct hid_device *hdev,
struct hid_input *hidinput, struct hid_field *field, struct hid_input *hidinput, struct hid_field *field,
struct hid_usage *usage, unsigned long **bit, int *max); struct hid_usage *usage, unsigned long **bit, int *max);
void (*input_configured)(struct hid_device *hdev, int (*input_configured)(struct hid_device *hdev,
struct hid_input *hidinput); struct hid_input *hidinput);
void (*feature_mapping)(struct hid_device *hdev, void (*feature_mapping)(struct hid_device *hdev,
struct hid_field *field, struct hid_field *field,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment