Commit 6f1da317 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID updates from Jiri Kosina:
 "Highlights:

   - Intel Skylake Win8 precision touchpads support fixes/improvements
     from Mika Westerberg

   - Lenovo Yoga 2 quirk from Ritesh Raj Sarraf

   - potential uninitialized buffer access fix in HID core from Richard
     Purdie

   - Wacom Intuos and Wacom Cintiq 2 support improvements from Jason
     Gerecke and Ping Cheng

   - initiation of sysfs deprecation process for most of the roccat
     drivers, from the roccat support maintiner Stefan Achatz

   - quite a few device ID / quirk additions and small fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (30 commits)
  HID: logitech: Add support for G29
  HID: logitech: Simplify wheel detection scheme
  HID: wacom: Call 'wacom_query_tablet_data' only after 'hid_hw_start'
  HID: wacom: Fix ABS_MISC reporting for Cintiq Companion 2
  HID: wacom: Remove useless conditions from 'wacom_query_tablet_data'
  HID: wacom: fix Intuos wireless report id issue
  HID: fix some indenting issues
  HID: wacom: Expect 'touch_max' touches if HID_DG_CONTACTCOUNT not present
  HID: wacom: Tie cached HID_DG_CONTACTCOUNT indices to report ID
  HID: roccat: Fixed resubmit: Deprecating most Roccat sysfs attributes
  HID: wacom: Report full pressure range for Intuos, Cintiq 13HD Touch
  HID: wacom: Add support for Cintiq Companion 2
  HID: multitouch: Fetch feature reports on demand for Win8 devices
  HID: sensor-hub: Add quirk for Lenovo Yoga 2 with ITE Chips
  HID: usbhid: Fix for the WiiU adapter from Mayflash
  HID: corsair: boolify struct k90_led.removed
  HID: corsair: Add Corsair Vengeance K90 driver
  HID: hid-input: allow input_configured callback return errors
  HID: multitouch: Add suffix for HID_DG_TOUCHPAD
  HID: i2c-hid: Fill in physical device providing HID functionality
  ...
parents 99aaa9c6 d64e19db
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>
...@@ -45,4 +106,40 @@ Description: The mouse can store 5 profiles which can be switched by the ...@@ -45,4 +106,40 @@ Description: The mouse can store 5 profiles which can be switched by the
The returned data is 43 bytes in size. The returned data is 43 bytes in size.
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
\ No newline at end of file
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
...@@ -678,9 +688,8 @@ config HID_SAITEK ...@@ -678,9 +688,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
......
...@@ -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) &&
...@@ -1611,7 +1612,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) ...@@ -1611,7 +1612,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
"Multi-Axis Controller" "Multi-Axis Controller"
}; };
const char *type, *bus; const char *type, *bus;
char buf[64]; char buf[64] = "";
unsigned int i; unsigned int i;
int len; int len;
int ret; int ret;
...@@ -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;
} }
......
...@@ -27,7 +27,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -27,7 +27,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n");
rdesc[47] = 0x00; rdesc[47] = 0x00;
} }
return rdesc; return rdesc;
} }
static const struct hid_device_id elecom_devices[] = { static const struct hid_device_id elecom_devices[] = {
......
...@@ -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
...@@ -288,6 +291,7 @@ ...@@ -288,6 +291,7 @@
#define USB_DEVICE_ID_DMI_ENC 0x5fab #define USB_DEVICE_ID_DMI_ENC 0x5fab
#define USB_VENDOR_ID_DRAGONRISE 0x0079 #define USB_VENDOR_ID_DRAGONRISE 0x0079
#define USB_DEVICE_ID_DRAGONRISE_WIIU 0x1800
#define USB_VENDOR_ID_DWAV 0x0eef #define USB_VENDOR_ID_DWAV 0x0eef
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
...@@ -510,6 +514,7 @@ ...@@ -510,6 +514,7 @@
#define USB_VENDOR_ID_ITE 0x048d #define USB_VENDOR_ID_ITE 0x048d
#define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386 #define USB_DEVICE_ID_ITE_LENOVO_YOGA 0x8386
#define USB_DEVICE_ID_ITE_LENOVO_YOGA2 0x8350
#define USB_VENDOR_ID_JABRA 0x0b0e #define USB_VENDOR_ID_JABRA 0x0b0e
#define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412
...@@ -646,6 +651,7 @@ ...@@ -646,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
...@@ -679,6 +685,7 @@ ...@@ -679,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
......
...@@ -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_g27_ident_info, &lg4ff_dfgt_ident_info,
&lg4ff_g25_ident_info, &lg4ff_g27_ident_info,
&lg4ff_dfp_ident_info} &lg4ff_g25_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; break;
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;
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 */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
...@@ -1205,7 +1330,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, ...@@ -1205,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;
...@@ -1330,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ...@@ -1330,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;
} }
hid_info(hdev, "HID++ %u.%u device connected.\n",
hidpp->protocol_major, hidpp->protocol_minor);
} }
/* the device is already connected, we can ask for its name and if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT))
* protocol */ /* if HID created the input nodes for us, we can stop now */
hid_info(hdev, "HID++ %u.%u device connected.\n", return;
hidpp->protocol_major, hidpp->protocol_minor);
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);
...@@ -1399,7 +1531,8 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1399,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) {
...@@ -1410,6 +1543,10 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1410,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);
...@@ -1450,7 +1587,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1450,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);
...@@ -1459,7 +1596,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1459,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);
...@@ -1504,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = { ...@@ -1504,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)},
......
...@@ -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;
...@@ -976,6 +1014,9 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) ...@@ -976,6 +1014,9 @@ static int 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;
...@@ -1036,8 +1077,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -1036,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) {
......
...@@ -427,7 +427,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) ...@@ -427,7 +427,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data)
pm->midi_octave = 2; pm->midi_octave = 2;
dbg_hid("pcmidi mode: %d octave: %d\n", dbg_hid("pcmidi mode: %d octave: %d\n",
pm->midi_mode, pm->midi_octave); pm->midi_mode, pm->midi_octave);
continue; continue;
} else } else
key = KEY_MESSENGER; key = KEY_MESSENGER;
break; break;
...@@ -695,7 +695,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) ...@@ -695,7 +695,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm)
if (err < 0) { if (err < 0) {
pk_error("failed to register pc-midi sound card: error %d\n", pk_error("failed to register pc-midi sound card: error %d\n",
err); err);
goto fail_register; goto fail_register;
} }
dbg_hid("pcmidi_snd_initialise finished ok\n"); dbg_hid("pcmidi_snd_initialise finished ok\n");
......
...@@ -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),
......
...@@ -593,6 +593,20 @@ static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc, ...@@ -593,6 +593,20 @@ static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc,
} }
} }
/* Checks if the report descriptor of Thinkpad Helix 2 has a logical
* minimum for magnetic flux axis greater than the maximum */
if (hdev->product == USB_DEVICE_ID_TEXAS_INSTRUMENTS_LENOVO_YOGA &&
*rsize == 2558 && rdesc[913] == 0x17 && rdesc[914] == 0x40 &&
rdesc[915] == 0x81 && rdesc[916] == 0x08 &&
rdesc[917] == 0x00 && rdesc[918] == 0x27 &&
rdesc[921] == 0x07 && rdesc[922] == 0x00) {
/* Sets negative logical minimum for mag x, y and z */
rdesc[914] = rdesc[935] = rdesc[956] = 0xc0;
rdesc[915] = rdesc[936] = rdesc[957] = 0x7e;
rdesc[916] = rdesc[937] = rdesc[958] = 0xf7;
rdesc[917] = rdesc[938] = rdesc[959] = 0xff;
}
return rdesc; return rdesc;
} }
...@@ -646,8 +660,8 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -646,8 +660,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
GFP_KERNEL); GFP_KERNEL);
if (sd->hid_sensor_hub_client_devs == NULL) { if (sd->hid_sensor_hub_client_devs == NULL) {
hid_err(hdev, "Failed to allocate memory for mfd cells\n"); hid_err(hdev, "Failed to allocate memory for mfd cells\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_stop_hw; goto err_stop_hw;
} }
for (i = 0; i < hdev->maxcollection; ++i) { for (i = 0; i < hdev->maxcollection; ++i) {
...@@ -684,8 +698,8 @@ static int sensor_hub_probe(struct hid_device *hdev, ...@@ -684,8 +698,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
collection->usage); collection->usage);
if (name == NULL) { if (name == NULL) {
hid_err(hdev, "Failed MFD device name\n"); hid_err(hdev, "Failed MFD device name\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err_stop_hw; goto err_stop_hw;
} }
sd->hid_sensor_hub_client_devs[ sd->hid_sensor_hub_client_devs[
sd->hid_sensor_client_cnt].name = name; sd->hid_sensor_client_cnt].name = name;
...@@ -777,6 +791,9 @@ static const struct hid_device_id sensor_hub_devices[] = { ...@@ -777,6 +791,9 @@ static const struct hid_device_id sensor_hub_devices[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA), USB_DEVICE_ID_ITE_LENOVO_YOGA),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, .driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE,
USB_DEVICE_ID_ITE_LENOVO_YOGA2),
.driver_data = HID_SENSOR_HUB_ENUM_QUIRK},
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID,
HID_ANY_ID) }, HID_ANY_ID) },
{ } { }
......
...@@ -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) {
......
...@@ -71,6 +71,7 @@ static const struct hid_blacklist { ...@@ -71,6 +71,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
...@@ -91,6 +92,7 @@ static const struct hid_blacklist { ...@@ -91,6 +92,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_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);
snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", if (wacom_wac1->features.type < BAMBOO_PEN ||
wacom_wac1->features.name); wacom_wac1->features.type > BAMBOO_PT) {
snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
wacom_wac1->features.name);
wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
}
wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; wacom_wac1->shared->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,
...@@ -198,6 +203,7 @@ struct hid_data { ...@@ -198,6 +203,7 @@ struct hid_data {
int width; int width;
int height; int height;
int id; int id;
int cc_report;
int cc_index; int cc_index;
int cc_value_index; int cc_value_index;
int num_expected; int num_expected;
......
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