diff options
44 files changed, 1509 insertions, 349 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-arvo index 55e281b0071a..55e281b0071a 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-arvo | |||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-isku index c601d0f2ac46..c601d0f2ac46 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-isku +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-isku | |||
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus index 833fd59926a7..545e69f43229 100644 --- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-koneplus | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile | ||
| 2 | Date: October 2010 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: The integer value of this attribute ranges from 0-4. | ||
| 5 | When read, this attribute returns the number of the actual | ||
| 6 | profile. This value is persistent, so its equivalent to the | ||
| 7 | profile that's active when the mouse is powered on next time. | ||
| 8 | When written, this file sets the number of the startup profile | ||
| 9 | and the mouse activates this profile immediately. | ||
| 10 | Users: http://roccat.sourceforge.net | ||
| 11 | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile | 12 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile |
| 2 | Date: October 2010 | 13 | Date: October 2010 |
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 14 | 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 | Please read binary attribute info which contains firmware version. | 33 | Please read binary attribute info which contains firmware version. |
| 23 | Users: http://roccat.sourceforge.net | 34 | Users: http://roccat.sourceforge.net |
| 24 | 35 | ||
| 36 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info | ||
| 37 | Date: November 2012 | ||
| 38 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 39 | Description: When read, this file returns general data like firmware version. | ||
| 40 | When written, the device can be reset. | ||
| 41 | The data is 8 bytes long. | ||
| 42 | Users: http://roccat.sourceforge.net | ||
| 43 | |||
| 44 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro | ||
| 45 | Date: October 2010 | ||
| 46 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 47 | Description: The mouse can store a macro with max 500 key/button strokes | ||
| 48 | internally. | ||
| 49 | When written, this file lets one set the sequence for a specific | ||
| 50 | button for a specific profile. Button and profile numbers are | ||
| 51 | included in written data. The data has to be 2082 bytes long. | ||
| 52 | This file is writeonly. | ||
| 53 | Users: http://roccat.sourceforge.net | ||
| 54 | |||
| 55 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons | ||
| 56 | Date: August 2010 | ||
| 57 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 58 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 59 | press of a button. A profile is split in settings and buttons. | ||
| 60 | profile_buttons holds information about button layout. | ||
| 61 | When written, this file lets one write the respective profile | ||
| 62 | buttons back to the mouse. The data has to be 77 bytes long. | ||
| 63 | The mouse will reject invalid data. | ||
| 64 | Which profile to write is determined by the profile number | ||
| 65 | contained in the data. | ||
| 66 | Before reading this file, control has to be written to select | ||
| 67 | which profile to read. | ||
| 68 | Users: http://roccat.sourceforge.net | ||
| 69 | |||
| 25 | 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 | 70 | 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 |
| 26 | Date: August 2010 | 71 | Date: August 2010 |
| 27 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 72 | 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 | Write control to select profile and read profile_buttons instead. | 79 | Write control to select profile and read profile_buttons instead. |
| 35 | Users: http://roccat.sourceforge.net | 80 | Users: http://roccat.sourceforge.net |
| 36 | 81 | ||
| 82 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings | ||
| 83 | Date: October 2010 | ||
| 84 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 85 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 86 | press of a button. A profile is split in settings and buttons. | ||
| 87 | profile_settings holds information like resolution, sensitivity | ||
| 88 | and light effects. | ||
| 89 | When written, this file lets one write the respective profile | ||
| 90 | settings back to the mouse. The data has to be 43 bytes long. | ||
| 91 | The mouse will reject invalid data. | ||
| 92 | Which profile to write is determined by the profile number | ||
| 93 | contained in the data. | ||
| 94 | Before reading this file, control has to be written to select | ||
| 95 | which profile to read. | ||
| 96 | Users: http://roccat.sourceforge.net | ||
| 97 | |||
| 37 | 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 | 98 | 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 |
| 38 | Date: August 2010 | 99 | Date: August 2010 |
| 39 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 100 | 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 | The returned data is 43 bytes in size. | 106 | The returned data is 43 bytes in size. |
| 46 | This file is readonly. | 107 | This file is readonly. |
| 47 | Write control to select profile and read profile_settings instead. | 108 | Write control to select profile and read profile_settings instead. |
| 48 | Users: http://roccat.sourceforge.net \ No newline at end of file | 109 | Users: http://roccat.sourceforge.net |
| 110 | |||
| 111 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor | ||
| 112 | Date: October 2010 | ||
| 113 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 114 | Description: The mouse has a tracking- and a distance-control-unit. These | ||
| 115 | can be activated/deactivated and the lift-off distance can be | ||
| 116 | set. The data has to be 6 bytes long. | ||
| 117 | This file is writeonly. | ||
| 118 | Users: http://roccat.sourceforge.net | ||
| 119 | |||
| 120 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk | ||
| 121 | Date: May 2011 | ||
| 122 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 123 | Description: Used to active some easy* functions of the mouse from outside. | ||
| 124 | The data has to be 16 bytes long. | ||
| 125 | This file is writeonly. | ||
| 126 | Users: http://roccat.sourceforge.net | ||
| 127 | |||
| 128 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu | ||
| 129 | Date: October 2010 | ||
| 130 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 131 | Description: When written a calibration process for the tracking control unit | ||
| 132 | can be initiated/cancelled. Also lets one read/write sensor | ||
| 133 | registers. | ||
| 134 | The data has to be 4 bytes long. | ||
| 135 | Users: http://roccat.sourceforge.net | ||
| 136 | |||
| 137 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image | ||
| 138 | Date: October 2010 | ||
| 139 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 140 | Description: When read the mouse returns a 30x30 pixel image of the | ||
| 141 | sampled underground. This works only in the course of a | ||
| 142 | calibration process initiated with tcu. | ||
| 143 | The returned data is 1028 bytes in size. | ||
| 144 | This file is readonly. | ||
| 145 | Users: http://roccat.sourceforge.net | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-konepure index 41a9b7fbfc79..41a9b7fbfc79 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-konepure +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-konepure | |||
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus index 4a98e02b6c6a..ab01631e1e0f 100644 --- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-kovaplus | |||
| @@ -8,6 +8,17 @@ Description: The integer value of this attribute ranges from 1-4. | |||
| 8 | Has never been used. If bookkeeping is done, it's done in userland tools. | 8 | Has never been used. If bookkeeping is done, it's done in userland tools. |
| 9 | Users: http://roccat.sourceforge.net | 9 | Users: http://roccat.sourceforge.net |
| 10 | 10 | ||
| 11 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile | ||
| 12 | Date: January 2011 | ||
| 13 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 14 | Description: The integer value of this attribute ranges from 0-4. | ||
| 15 | When read, this attribute returns the number of the active | ||
| 16 | profile. | ||
| 17 | When written, the mouse activates this profile immediately. | ||
| 18 | The profile that's active when powered down is the same that's | ||
| 19 | active when the mouse is powered on. | ||
| 20 | Users: http://roccat.sourceforge.net | ||
| 21 | |||
| 11 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x | 22 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x |
| 12 | Date: January 2011 | 23 | Date: January 2011 |
| 13 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 24 | 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 | Obsoleted by binary sysfs attribute "info". | 51 | Obsoleted by binary sysfs attribute "info". |
| 41 | Users: http://roccat.sourceforge.net | 52 | Users: http://roccat.sourceforge.net |
| 42 | 53 | ||
| 54 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info | ||
| 55 | Date: November 2012 | ||
| 56 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 57 | Description: When read, this file returns general data like firmware version. | ||
| 58 | When written, the device can be reset. | ||
| 59 | The data is 6 bytes long. | ||
| 60 | Users: http://roccat.sourceforge.net | ||
| 61 | |||
| 62 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons | ||
| 63 | Date: January 2011 | ||
| 64 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 65 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 66 | press of a button. A profile is split in settings and buttons. | ||
| 67 | profile_buttons holds information about button layout. | ||
| 68 | When written, this file lets one write the respective profile | ||
| 69 | buttons back to the mouse. The data has to be 23 bytes long. | ||
| 70 | The mouse will reject invalid data. | ||
| 71 | Which profile to write is determined by the profile number | ||
| 72 | contained in the data. | ||
| 73 | Before reading this file, control has to be written to select | ||
| 74 | which profile to read. | ||
| 75 | Users: http://roccat.sourceforge.net | ||
| 76 | |||
| 43 | 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 | 77 | 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 |
| 44 | Date: January 2011 | 78 | Date: January 2011 |
| 45 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 79 | 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 | Write control to select profile and read profile_buttons instead. | 86 | Write control to select profile and read profile_buttons instead. |
| 53 | Users: http://roccat.sourceforge.net | 87 | Users: http://roccat.sourceforge.net |
| 54 | 88 | ||
| 89 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings | ||
| 90 | Date: January 2011 | ||
| 91 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 92 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 93 | press of a button. A profile is split in settings and buttons. | ||
| 94 | profile_settings holds information like resolution, sensitivity | ||
| 95 | and light effects. | ||
| 96 | When written, this file lets one write the respective profile | ||
| 97 | settings back to the mouse. The data has to be 16 bytes long. | ||
| 98 | The mouse will reject invalid data. | ||
| 99 | Which profile to write is determined by the profile number | ||
| 100 | contained in the data. | ||
| 101 | Before reading this file, control has to be written to select | ||
| 102 | which profile to read. | ||
| 103 | Users: http://roccat.sourceforge.net | ||
| 104 | |||
| 55 | 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 | 105 | 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 |
| 56 | Date: January 2011 | 106 | Date: January 2011 |
| 57 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 107 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> |
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-lua index 31c6c4c8ba2b..31c6c4c8ba2b 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-lua +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-lua | |||
diff --git a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra index 87ac87e9556d..16020b31ae64 100644 --- a/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-pyra | |||
| @@ -37,6 +37,29 @@ Description: When read, this file returns the raw integer version number of the | |||
| 37 | Please use binary attribute "info" which provides this information. | 37 | Please use binary attribute "info" which provides this information. |
| 38 | Users: http://roccat.sourceforge.net | 38 | Users: http://roccat.sourceforge.net |
| 39 | 39 | ||
| 40 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info | ||
| 41 | Date: November 2012 | ||
| 42 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 43 | Description: When read, this file returns general data like firmware version. | ||
| 44 | When written, the device can be reset. | ||
| 45 | The data is 6 bytes long. | ||
| 46 | Users: http://roccat.sourceforge.net | ||
| 47 | |||
| 48 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons | ||
| 49 | Date: August 2010 | ||
| 50 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 51 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 52 | press of a button. A profile is split in settings and buttons. | ||
| 53 | profile_buttons holds information about button layout. | ||
| 54 | When written, this file lets one write the respective profile | ||
| 55 | buttons back to the mouse. The data has to be 19 bytes long. | ||
| 56 | The mouse will reject invalid data. | ||
| 57 | Which profile to write is determined by the profile number | ||
| 58 | contained in the data. | ||
| 59 | Before reading this file, control has to be written to select | ||
| 60 | which profile to read. | ||
| 61 | Users: http://roccat.sourceforge.net | ||
| 62 | |||
| 40 | 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 | 63 | 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 |
| 41 | Date: August 2010 | 64 | Date: August 2010 |
| 42 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 65 | 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 | Write control to select profile and read profile_buttons instead. | 72 | Write control to select profile and read profile_buttons instead. |
| 50 | Users: http://roccat.sourceforge.net | 73 | Users: http://roccat.sourceforge.net |
| 51 | 74 | ||
| 75 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings | ||
| 76 | Date: August 2010 | ||
| 77 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 78 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 79 | press of a button. A profile is split in settings and buttons. | ||
| 80 | profile_settings holds information like resolution, sensitivity | ||
| 81 | and light effects. | ||
| 82 | When written, this file lets one write the respective profile | ||
| 83 | settings back to the mouse. The data has to be 13 bytes long. | ||
| 84 | The mouse will reject invalid data. | ||
| 85 | Which profile to write is determined by the profile number | ||
| 86 | contained in the data. | ||
| 87 | Before reading this file, control has to be written to select | ||
| 88 | which profile to read. | ||
| 89 | Users: http://roccat.sourceforge.net | ||
| 90 | |||
| 52 | 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 | 91 | 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 |
| 53 | Date: August 2010 | 92 | Date: August 2010 |
| 54 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 93 | 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 | Write control to select profile and read profile_settings instead. | 101 | Write control to select profile and read profile_settings instead. |
| 63 | Users: http://roccat.sourceforge.net | 102 | Users: http://roccat.sourceforge.net |
| 64 | 103 | ||
| 104 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings | ||
| 105 | Date: August 2010 | ||
| 106 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 107 | Description: When read, this file returns the settings stored in the mouse. | ||
| 108 | The size of the data is 3 bytes and holds information on the | ||
| 109 | startup_profile. | ||
| 110 | When written, this file lets write settings back to the mouse. | ||
| 111 | The data has to be 3 bytes long. The mouse will reject invalid | ||
| 112 | data. | ||
| 113 | Users: http://roccat.sourceforge.net | ||
| 114 | |||
| 65 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile | 115 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile |
| 66 | Date: August 2010 | 116 | Date: August 2010 |
| 67 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | 117 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> |
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-ryos index 1d6a8cf9dc0a..1d6a8cf9dc0a 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-ryos +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-ryos | |||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu index f1e02a98bd9d..f1e02a98bd9d 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-savu +++ b/Documentation/ABI/obsolete/sysfs-driver-hid-roccat-savu | |||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-corsair b/Documentation/ABI/testing/sysfs-driver-hid-corsair new file mode 100644 index 000000000000..b8827f0f12c4 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-driver-hid-corsair | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | What: /sys/bus/drivers/corsair/<dev>/macro_mode | ||
| 2 | Date: August 2015 | ||
| 3 | KernelVersion: 4.2 | ||
| 4 | Contact: Clement Vuchener <clement.vuchener@gmail.com> | ||
| 5 | Description: Get/set the current playback mode. "SW" for software mode | ||
| 6 | where G-keys triggers their regular key codes. "HW" for | ||
| 7 | hardware playback mode where the G-keys play their macro | ||
| 8 | from the on-board memory. | ||
| 9 | |||
| 10 | |||
| 11 | What: /sys/bus/drivers/corsair/<dev>/current_profile | ||
| 12 | Date: August 2015 | ||
| 13 | KernelVersion: 4.2 | ||
| 14 | Contact: Clement Vuchener <clement.vuchener@gmail.com> | ||
| 15 | Description: Get/set the current selected profile. Values are from 1 to 3. | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus deleted file mode 100644 index 7bd776f9c3c7..000000000000 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus +++ /dev/null | |||
| @@ -1,96 +0,0 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/actual_profile | ||
| 2 | Date: October 2010 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: The integer value of this attribute ranges from 0-4. | ||
| 5 | When read, this attribute returns the number of the actual | ||
| 6 | profile. This value is persistent, so its equivalent to the | ||
| 7 | profile that's active when the mouse is powered on next time. | ||
| 8 | When written, this file sets the number of the startup profile | ||
| 9 | and the mouse activates this profile immediately. | ||
| 10 | Users: http://roccat.sourceforge.net | ||
| 11 | |||
| 12 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/info | ||
| 13 | Date: November 2012 | ||
| 14 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 15 | Description: When read, this file returns general data like firmware version. | ||
| 16 | When written, the device can be reset. | ||
| 17 | The data is 8 bytes long. | ||
| 18 | Users: http://roccat.sourceforge.net | ||
| 19 | |||
| 20 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro | ||
| 21 | Date: October 2010 | ||
| 22 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 23 | Description: The mouse can store a macro with max 500 key/button strokes | ||
| 24 | internally. | ||
| 25 | When written, this file lets one set the sequence for a specific | ||
| 26 | button for a specific profile. Button and profile numbers are | ||
| 27 | included in written data. The data has to be 2082 bytes long. | ||
| 28 | This file is writeonly. | ||
| 29 | Users: http://roccat.sourceforge.net | ||
| 30 | |||
| 31 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons | ||
| 32 | Date: August 2010 | ||
| 33 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 34 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 35 | press of a button. A profile is split in settings and buttons. | ||
| 36 | profile_buttons holds information about button layout. | ||
| 37 | When written, this file lets one write the respective profile | ||
| 38 | buttons back to the mouse. The data has to be 77 bytes long. | ||
| 39 | The mouse will reject invalid data. | ||
| 40 | Which profile to write is determined by the profile number | ||
| 41 | contained in the data. | ||
| 42 | Before reading this file, control has to be written to select | ||
| 43 | which profile to read. | ||
| 44 | Users: http://roccat.sourceforge.net | ||
| 45 | |||
| 46 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings | ||
| 47 | Date: October 2010 | ||
| 48 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 49 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 50 | press of a button. A profile is split in settings and buttons. | ||
| 51 | profile_settings holds information like resolution, sensitivity | ||
| 52 | and light effects. | ||
| 53 | When written, this file lets one write the respective profile | ||
| 54 | settings back to the mouse. The data has to be 43 bytes long. | ||
| 55 | The mouse will reject invalid data. | ||
| 56 | Which profile to write is determined by the profile number | ||
| 57 | contained in the data. | ||
| 58 | Before reading this file, control has to be written to select | ||
| 59 | which profile to read. | ||
| 60 | Users: http://roccat.sourceforge.net | ||
| 61 | |||
| 62 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor | ||
| 63 | Date: October 2010 | ||
| 64 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 65 | Description: The mouse has a tracking- and a distance-control-unit. These | ||
| 66 | can be activated/deactivated and the lift-off distance can be | ||
| 67 | set. The data has to be 6 bytes long. | ||
| 68 | This file is writeonly. | ||
| 69 | Users: http://roccat.sourceforge.net | ||
| 70 | |||
| 71 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/talk | ||
| 72 | Date: May 2011 | ||
| 73 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 74 | Description: Used to active some easy* functions of the mouse from outside. | ||
| 75 | The data has to be 16 bytes long. | ||
| 76 | This file is writeonly. | ||
| 77 | Users: http://roccat.sourceforge.net | ||
| 78 | |||
| 79 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu | ||
| 80 | Date: October 2010 | ||
| 81 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 82 | Description: When written a calibration process for the tracking control unit | ||
| 83 | can be initiated/cancelled. Also lets one read/write sensor | ||
| 84 | registers. | ||
| 85 | The data has to be 4 bytes long. | ||
| 86 | Users: http://roccat.sourceforge.net | ||
| 87 | |||
| 88 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image | ||
| 89 | Date: October 2010 | ||
| 90 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 91 | Description: When read the mouse returns a 30x30 pixel image of the | ||
| 92 | sampled underground. This works only in the course of a | ||
| 93 | calibration process initiated with tcu. | ||
| 94 | The returned data is 1028 bytes in size. | ||
| 95 | This file is readonly. | ||
| 96 | Users: http://roccat.sourceforge.net | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus b/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus deleted file mode 100644 index a10404f15a54..000000000000 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile | ||
| 2 | Date: January 2011 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: The integer value of this attribute ranges from 0-4. | ||
| 5 | When read, this attribute returns the number of the active | ||
| 6 | profile. | ||
| 7 | When written, the mouse activates this profile immediately. | ||
| 8 | The profile that's active when powered down is the same that's | ||
| 9 | active when the mouse is powered on. | ||
| 10 | Users: http://roccat.sourceforge.net | ||
| 11 | |||
| 12 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/info | ||
| 13 | Date: November 2012 | ||
| 14 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 15 | Description: When read, this file returns general data like firmware version. | ||
| 16 | When written, the device can be reset. | ||
| 17 | The data is 6 bytes long. | ||
| 18 | Users: http://roccat.sourceforge.net | ||
| 19 | |||
| 20 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons | ||
| 21 | Date: January 2011 | ||
| 22 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 23 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 24 | press of a button. A profile is split in settings and buttons. | ||
| 25 | profile_buttons holds information about button layout. | ||
| 26 | When written, this file lets one write the respective profile | ||
| 27 | buttons back to the mouse. The data has to be 23 bytes long. | ||
| 28 | The mouse will reject invalid data. | ||
| 29 | Which profile to write is determined by the profile number | ||
| 30 | contained in the data. | ||
| 31 | Before reading this file, control has to be written to select | ||
| 32 | which profile to read. | ||
| 33 | Users: http://roccat.sourceforge.net | ||
| 34 | |||
| 35 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings | ||
| 36 | Date: January 2011 | ||
| 37 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 38 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 39 | press of a button. A profile is split in settings and buttons. | ||
| 40 | profile_settings holds information like resolution, sensitivity | ||
| 41 | and light effects. | ||
| 42 | When written, this file lets one write the respective profile | ||
| 43 | settings back to the mouse. The data has to be 16 bytes long. | ||
| 44 | The mouse will reject invalid data. | ||
| 45 | Which profile to write is determined by the profile number | ||
| 46 | contained in the data. | ||
| 47 | Before reading this file, control has to be written to select | ||
| 48 | which profile to read. | ||
| 49 | Users: http://roccat.sourceforge.net | ||
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra b/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra deleted file mode 100644 index 9fa9de30d14b..000000000000 --- a/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/info | ||
| 2 | Date: November 2012 | ||
| 3 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 4 | Description: When read, this file returns general data like firmware version. | ||
| 5 | When written, the device can be reset. | ||
| 6 | The data is 6 bytes long. | ||
| 7 | Users: http://roccat.sourceforge.net | ||
| 8 | |||
| 9 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings | ||
| 10 | Date: August 2010 | ||
| 11 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 12 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 13 | press of a button. A profile is split in settings and buttons. | ||
| 14 | profile_settings holds information like resolution, sensitivity | ||
| 15 | and light effects. | ||
| 16 | When written, this file lets one write the respective profile | ||
| 17 | settings back to the mouse. The data has to be 13 bytes long. | ||
| 18 | The mouse will reject invalid data. | ||
| 19 | Which profile to write is determined by the profile number | ||
| 20 | contained in the data. | ||
| 21 | Before reading this file, control has to be written to select | ||
| 22 | which profile to read. | ||
| 23 | Users: http://roccat.sourceforge.net | ||
| 24 | |||
| 25 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons | ||
| 26 | Date: August 2010 | ||
| 27 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 28 | Description: The mouse can store 5 profiles which can be switched by the | ||
| 29 | press of a button. A profile is split in settings and buttons. | ||
| 30 | profile_buttons holds information about button layout. | ||
| 31 | When written, this file lets one write the respective profile | ||
| 32 | buttons back to the mouse. The data has to be 19 bytes long. | ||
| 33 | The mouse will reject invalid data. | ||
| 34 | Which profile to write is determined by the profile number | ||
| 35 | contained in the data. | ||
| 36 | Before reading this file, control has to be written to select | ||
| 37 | which profile to read. | ||
| 38 | Users: http://roccat.sourceforge.net | ||
| 39 | |||
| 40 | What: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings | ||
| 41 | Date: August 2010 | ||
| 42 | Contact: Stefan Achatz <erazor_de@users.sourceforge.net> | ||
| 43 | Description: When read, this file returns the settings stored in the mouse. | ||
| 44 | The size of the data is 3 bytes and holds information on the | ||
| 45 | startup_profile. | ||
| 46 | When written, this file lets write settings back to the mouse. | ||
| 47 | The data has to be 3 bytes long. The mouse will reject invalid | ||
| 48 | data. | ||
| 49 | Users: http://roccat.sourceforge.net | ||
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ab51ae3c39d..4135055d7203 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
| @@ -171,6 +171,16 @@ config HID_CHICONY | |||
| 171 | ---help--- | 171 | ---help--- |
| 172 | Support for Chicony Tactical pad. | 172 | Support for Chicony Tactical pad. |
| 173 | 173 | ||
| 174 | config HID_CORSAIR | ||
| 175 | tristate "Corsair devices" | ||
| 176 | depends on HID && USB && LEDS_CLASS | ||
| 177 | ---help--- | ||
| 178 | Support for Corsair devices that are not fully compliant with the | ||
| 179 | HID standard. | ||
| 180 | |||
| 181 | Supported devices: | ||
| 182 | - Vengeance K90 | ||
| 183 | |||
| 174 | config HID_PRODIKEYS | 184 | config HID_PRODIKEYS |
| 175 | tristate "Prodikeys PC-MIDI Keyboard support" | 185 | tristate "Prodikeys PC-MIDI Keyboard support" |
| 176 | depends on HID && SND | 186 | depends on HID && SND |
| @@ -672,9 +682,8 @@ config HID_SAITEK | |||
| 672 | 682 | ||
| 673 | Supported devices: | 683 | Supported devices: |
| 674 | - PS1000 Dual Analog Pad | 684 | - PS1000 Dual Analog Pad |
| 675 | - R.A.T.9 Gaming Mouse | 685 | - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice |
| 676 | - R.A.T.7 Gaming Mouse | 686 | - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice |
| 677 | - M.M.O.7 Gaming Mouse | ||
| 678 | 687 | ||
| 679 | config HID_SAMSUNG | 688 | config HID_SAMSUNG |
| 680 | tristate "Samsung InfraRed remote control or keyboards" | 689 | tristate "Samsung InfraRed remote control or keyboards" |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index e6441bc7dae4..edaa0f264bde 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
| @@ -29,6 +29,7 @@ obj-$(CONFIG_HID_BELKIN) += hid-belkin.o | |||
| 29 | obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o | 29 | obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o |
| 30 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o | 30 | obj-$(CONFIG_HID_CHERRY) += hid-cherry.o |
| 31 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o | 31 | obj-$(CONFIG_HID_CHICONY) += hid-chicony.o |
| 32 | obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o | ||
| 32 | obj-$(CONFIG_HID_CP2112) += hid-cp2112.o | 33 | obj-$(CONFIG_HID_CP2112) += hid-cp2112.o |
| 33 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o | 34 | obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o |
| 34 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o | 35 | obj-$(CONFIG_HID_DRAGONRISE) += hid-dr.o |
diff --git a/drivers/hid/hid-appleir.c b/drivers/hid/hid-appleir.c index 0e6a42d37eb6..07cbc70f00e7 100644 --- a/drivers/hid/hid-appleir.c +++ b/drivers/hid/hid-appleir.c | |||
| @@ -256,7 +256,7 @@ out: | |||
| 256 | return 0; | 256 | return 0; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static void appleir_input_configured(struct hid_device *hid, | 259 | static int appleir_input_configured(struct hid_device *hid, |
| 260 | struct hid_input *hidinput) | 260 | struct hid_input *hidinput) |
| 261 | { | 261 | { |
| 262 | struct input_dev *input_dev = hidinput->input; | 262 | struct input_dev *input_dev = hidinput->input; |
| @@ -275,6 +275,8 @@ static void appleir_input_configured(struct hid_device *hid, | |||
| 275 | for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) | 275 | for (i = 0; i < ARRAY_SIZE(appleir_key_table); i++) |
| 276 | set_bit(appleir->keymap[i], input_dev->keybit); | 276 | set_bit(appleir->keymap[i], input_dev->keybit); |
| 277 | clear_bit(KEY_RESERVED, input_dev->keybit); | 277 | clear_bit(KEY_RESERVED, input_dev->keybit); |
| 278 | |||
| 279 | return 0; | ||
| 278 | } | 280 | } |
| 279 | 281 | ||
| 280 | static int appleir_input_mapping(struct hid_device *hid, | 282 | static int appleir_input_mapping(struct hid_device *hid, |
diff --git a/drivers/hid/hid-aureal.c b/drivers/hid/hid-aureal.c index 340ba9d394a0..3280aff28e90 100644 --- a/drivers/hid/hid-aureal.c +++ b/drivers/hid/hid-aureal.c | |||
| @@ -23,7 +23,8 @@ static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 23 | if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { | 23 | if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { |
| 24 | dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n"); | 24 | dev_info(&hdev->dev, "fixing Aureal Cy se W-01RN USB_V3.1 report descriptor.\n"); |
| 25 | rdesc[53] = 0x65; | 25 | rdesc[53] = 0x65; |
| 26 | } return rdesc; | 26 | } |
| 27 | return rdesc; | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | static const struct hid_device_id aureal_devices[] = { | 30 | static const struct hid_device_id aureal_devices[] = { |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4130685fca7c..0bd972b7614c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -725,6 +725,7 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) | |||
| 725 | 725 | ||
| 726 | if (hid->vendor == USB_VENDOR_ID_MICROSOFT && | 726 | if (hid->vendor == USB_VENDOR_ID_MICROSOFT && |
| 727 | (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 || | 727 | (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 || |
| 728 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 || | ||
| 728 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP || | 729 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP || |
| 729 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || | 730 | hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || |
| 730 | hid->product == USB_DEVICE_ID_MS_POWER_COVER) && | 731 | hid->product == USB_DEVICE_ID_MS_POWER_COVER) && |
| @@ -1678,6 +1679,9 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) | |||
| 1678 | case BUS_BLUETOOTH: | 1679 | case BUS_BLUETOOTH: |
| 1679 | bus = "BLUETOOTH"; | 1680 | bus = "BLUETOOTH"; |
| 1680 | break; | 1681 | break; |
| 1682 | case BUS_I2C: | ||
| 1683 | bus = "I2C"; | ||
| 1684 | break; | ||
| 1681 | default: | 1685 | default: |
| 1682 | bus = "<UNKNOWN>"; | 1686 | bus = "<UNKNOWN>"; |
| 1683 | } | 1687 | } |
| @@ -1828,6 +1832,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
| 1828 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, | 1832 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, |
| 1829 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, | 1833 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, |
| 1830 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) }, | 1834 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) }, |
| 1835 | { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90) }, | ||
| 1831 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, | 1836 | { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, |
| 1832 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, | 1837 | { HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) }, |
| 1833 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1838 | { 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 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, | 1901 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD) }, |
| 1897 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, | 1902 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD) }, |
| 1898 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, | 1903 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2) }, |
| 1904 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G29_WHEEL) }, | ||
| 1899 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, | 1905 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_F3D) }, |
| 1900 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, | 1906 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ) }, |
| 1901 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) }, | 1907 | { 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 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, | 1934 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, |
| 1929 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, | 1935 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, |
| 1930 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, | 1936 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, |
| 1937 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, | ||
| 1931 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, | 1938 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, |
| 1932 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, | 1939 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, |
| 1933 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, | 1940 | { 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 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) }, | 1988 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) }, |
| 1982 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, | 1989 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, |
| 1983 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, | 1990 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, |
| 1991 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) }, | ||
| 1984 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, | 1992 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, |
| 1985 | #endif | 1993 | #endif |
| 1986 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, | 1994 | { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, |
diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c new file mode 100644 index 000000000000..bcefb9ebb026 --- /dev/null +++ b/drivers/hid/hid-corsair.c | |||
| @@ -0,0 +1,673 @@ | |||
| 1 | /* | ||
| 2 | * HID driver for Corsair devices | ||
| 3 | * | ||
| 4 | * Supported devices: | ||
| 5 | * - Vengeance K90 Keyboard | ||
| 6 | * | ||
| 7 | * Copyright (c) 2015 Clement Vuchener | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License as published by the Free | ||
| 13 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 14 | * any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/hid.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/usb.h> | ||
| 20 | #include <linux/leds.h> | ||
| 21 | |||
| 22 | #include "hid-ids.h" | ||
| 23 | |||
| 24 | #define CORSAIR_USE_K90_MACRO (1<<0) | ||
| 25 | #define CORSAIR_USE_K90_BACKLIGHT (1<<1) | ||
| 26 | |||
| 27 | struct k90_led { | ||
| 28 | struct led_classdev cdev; | ||
| 29 | int brightness; | ||
| 30 | struct work_struct work; | ||
| 31 | bool removed; | ||
| 32 | }; | ||
| 33 | |||
| 34 | struct k90_drvdata { | ||
| 35 | struct k90_led record_led; | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct corsair_drvdata { | ||
| 39 | unsigned long quirks; | ||
| 40 | struct k90_drvdata *k90; | ||
| 41 | struct k90_led *backlight; | ||
| 42 | }; | ||
| 43 | |||
| 44 | #define K90_GKEY_COUNT 18 | ||
| 45 | |||
| 46 | static int corsair_usage_to_gkey(unsigned int usage) | ||
| 47 | { | ||
| 48 | /* G1 (0xd0) to G16 (0xdf) */ | ||
| 49 | if (usage >= 0xd0 && usage <= 0xdf) | ||
| 50 | return usage - 0xd0 + 1; | ||
| 51 | /* G17 (0xe8) to G18 (0xe9) */ | ||
| 52 | if (usage >= 0xe8 && usage <= 0xe9) | ||
| 53 | return usage - 0xe8 + 17; | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static unsigned short corsair_gkey_map[K90_GKEY_COUNT] = { | ||
| 58 | BTN_TRIGGER_HAPPY1, | ||
| 59 | BTN_TRIGGER_HAPPY2, | ||
| 60 | BTN_TRIGGER_HAPPY3, | ||
| 61 | BTN_TRIGGER_HAPPY4, | ||
| 62 | BTN_TRIGGER_HAPPY5, | ||
| 63 | BTN_TRIGGER_HAPPY6, | ||
| 64 | BTN_TRIGGER_HAPPY7, | ||
| 65 | BTN_TRIGGER_HAPPY8, | ||
| 66 | BTN_TRIGGER_HAPPY9, | ||
| 67 | BTN_TRIGGER_HAPPY10, | ||
| 68 | BTN_TRIGGER_HAPPY11, | ||
| 69 | BTN_TRIGGER_HAPPY12, | ||
| 70 | BTN_TRIGGER_HAPPY13, | ||
| 71 | BTN_TRIGGER_HAPPY14, | ||
| 72 | BTN_TRIGGER_HAPPY15, | ||
| 73 | BTN_TRIGGER_HAPPY16, | ||
| 74 | BTN_TRIGGER_HAPPY17, | ||
| 75 | BTN_TRIGGER_HAPPY18, | ||
| 76 | }; | ||
| 77 | |||
| 78 | module_param_array_named(gkey_codes, corsair_gkey_map, ushort, NULL, S_IRUGO); | ||
| 79 | MODULE_PARM_DESC(gkey_codes, "Key codes for the G-keys"); | ||
| 80 | |||
| 81 | static unsigned short corsair_record_keycodes[2] = { | ||
| 82 | BTN_TRIGGER_HAPPY19, | ||
| 83 | BTN_TRIGGER_HAPPY20 | ||
| 84 | }; | ||
| 85 | |||
| 86 | module_param_array_named(recordkey_codes, corsair_record_keycodes, ushort, | ||
| 87 | NULL, S_IRUGO); | ||
| 88 | MODULE_PARM_DESC(recordkey_codes, "Key codes for the MR (start and stop record) button"); | ||
| 89 | |||
| 90 | static unsigned short corsair_profile_keycodes[3] = { | ||
| 91 | BTN_TRIGGER_HAPPY21, | ||
| 92 | BTN_TRIGGER_HAPPY22, | ||
| 93 | BTN_TRIGGER_HAPPY23 | ||
| 94 | }; | ||
| 95 | |||
| 96 | module_param_array_named(profilekey_codes, corsair_profile_keycodes, ushort, | ||
| 97 | NULL, S_IRUGO); | ||
| 98 | MODULE_PARM_DESC(profilekey_codes, "Key codes for the profile buttons"); | ||
| 99 | |||
| 100 | #define CORSAIR_USAGE_SPECIAL_MIN 0xf0 | ||
| 101 | #define CORSAIR_USAGE_SPECIAL_MAX 0xff | ||
| 102 | |||
| 103 | #define CORSAIR_USAGE_MACRO_RECORD_START 0xf6 | ||
| 104 | #define CORSAIR_USAGE_MACRO_RECORD_STOP 0xf7 | ||
| 105 | |||
| 106 | #define CORSAIR_USAGE_PROFILE 0xf1 | ||
| 107 | #define CORSAIR_USAGE_M1 0xf1 | ||
| 108 | #define CORSAIR_USAGE_M2 0xf2 | ||
| 109 | #define CORSAIR_USAGE_M3 0xf3 | ||
| 110 | #define CORSAIR_USAGE_PROFILE_MAX 0xf3 | ||
| 111 | |||
| 112 | #define CORSAIR_USAGE_META_OFF 0xf4 | ||
| 113 | #define CORSAIR_USAGE_META_ON 0xf5 | ||
| 114 | |||
| 115 | #define CORSAIR_USAGE_LIGHT 0xfa | ||
| 116 | #define CORSAIR_USAGE_LIGHT_OFF 0xfa | ||
| 117 | #define CORSAIR_USAGE_LIGHT_DIM 0xfb | ||
| 118 | #define CORSAIR_USAGE_LIGHT_MEDIUM 0xfc | ||
| 119 | #define CORSAIR_USAGE_LIGHT_BRIGHT 0xfd | ||
| 120 | #define CORSAIR_USAGE_LIGHT_MAX 0xfd | ||
| 121 | |||
| 122 | /* USB control protocol */ | ||
| 123 | |||
| 124 | #define K90_REQUEST_BRIGHTNESS 49 | ||
| 125 | #define K90_REQUEST_MACRO_MODE 2 | ||
| 126 | #define K90_REQUEST_STATUS 4 | ||
| 127 | #define K90_REQUEST_GET_MODE 5 | ||
| 128 | #define K90_REQUEST_PROFILE 20 | ||
| 129 | |||
| 130 | #define K90_MACRO_MODE_SW 0x0030 | ||
| 131 | #define K90_MACRO_MODE_HW 0x0001 | ||
| 132 | |||
| 133 | #define K90_MACRO_LED_ON 0x0020 | ||
| 134 | #define K90_MACRO_LED_OFF 0x0040 | ||
| 135 | |||
| 136 | /* | ||
| 137 | * LED class devices | ||
| 138 | */ | ||
| 139 | |||
| 140 | #define K90_BACKLIGHT_LED_SUFFIX "::backlight" | ||
| 141 | #define K90_RECORD_LED_SUFFIX "::record" | ||
| 142 | |||
| 143 | static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev) | ||
| 144 | { | ||
| 145 | int ret; | ||
| 146 | struct k90_led *led = container_of(led_cdev, struct k90_led, cdev); | ||
| 147 | struct device *dev = led->cdev.dev->parent; | ||
| 148 | struct usb_interface *usbif = to_usb_interface(dev->parent); | ||
| 149 | struct usb_device *usbdev = interface_to_usbdev(usbif); | ||
| 150 | int brightness; | ||
| 151 | char data[8]; | ||
| 152 | |||
| 153 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), | ||
| 154 | K90_REQUEST_STATUS, | ||
| 155 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
| 156 | USB_RECIP_DEVICE, 0, 0, data, 8, | ||
| 157 | USB_CTRL_SET_TIMEOUT); | ||
| 158 | if (ret < 0) { | ||
| 159 | dev_warn(dev, "Failed to get K90 initial state (error %d).\n", | ||
| 160 | ret); | ||
| 161 | return -EIO; | ||
| 162 | } | ||
| 163 | brightness = data[4]; | ||
| 164 | if (brightness < 0 || brightness > 3) { | ||
| 165 | dev_warn(dev, | ||
| 166 | "Read invalid backlight brightness: %02hhx.\n", | ||
| 167 | data[4]); | ||
| 168 | return -EIO; | ||
| 169 | } | ||
| 170 | return brightness; | ||
| 171 | } | ||
| 172 | |||
| 173 | static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev) | ||
| 174 | { | ||
| 175 | struct k90_led *led = container_of(led_cdev, struct k90_led, cdev); | ||
| 176 | |||
| 177 | return led->brightness; | ||
| 178 | } | ||
| 179 | |||
| 180 | static void k90_brightness_set(struct led_classdev *led_cdev, | ||
| 181 | enum led_brightness brightness) | ||
| 182 | { | ||
| 183 | struct k90_led *led = container_of(led_cdev, struct k90_led, cdev); | ||
| 184 | |||
| 185 | led->brightness = brightness; | ||
| 186 | schedule_work(&led->work); | ||
| 187 | } | ||
| 188 | |||
| 189 | static void k90_backlight_work(struct work_struct *work) | ||
| 190 | { | ||
| 191 | int ret; | ||
| 192 | struct k90_led *led = container_of(work, struct k90_led, work); | ||
| 193 | struct device *dev; | ||
| 194 | struct usb_interface *usbif; | ||
| 195 | struct usb_device *usbdev; | ||
| 196 | |||
| 197 | if (led->removed) | ||
| 198 | return; | ||
| 199 | |||
| 200 | dev = led->cdev.dev->parent; | ||
| 201 | usbif = to_usb_interface(dev->parent); | ||
| 202 | usbdev = interface_to_usbdev(usbif); | ||
| 203 | |||
| 204 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | ||
| 205 | K90_REQUEST_BRIGHTNESS, | ||
| 206 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
| 207 | USB_RECIP_DEVICE, led->brightness, 0, | ||
| 208 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 209 | if (ret != 0) | ||
| 210 | dev_warn(dev, "Failed to set backlight brightness (error: %d).\n", | ||
| 211 | ret); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void k90_record_led_work(struct work_struct *work) | ||
| 215 | { | ||
| 216 | int ret; | ||
| 217 | struct k90_led *led = container_of(work, struct k90_led, work); | ||
| 218 | struct device *dev; | ||
| 219 | struct usb_interface *usbif; | ||
| 220 | struct usb_device *usbdev; | ||
| 221 | int value; | ||
| 222 | |||
| 223 | if (led->removed) | ||
| 224 | return; | ||
| 225 | |||
| 226 | dev = led->cdev.dev->parent; | ||
| 227 | usbif = to_usb_interface(dev->parent); | ||
| 228 | usbdev = interface_to_usbdev(usbif); | ||
| 229 | |||
| 230 | if (led->brightness > 0) | ||
| 231 | value = K90_MACRO_LED_ON; | ||
| 232 | else | ||
| 233 | value = K90_MACRO_LED_OFF; | ||
| 234 | |||
| 235 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | ||
| 236 | K90_REQUEST_MACRO_MODE, | ||
| 237 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
| 238 | USB_RECIP_DEVICE, value, 0, NULL, 0, | ||
| 239 | USB_CTRL_SET_TIMEOUT); | ||
| 240 | if (ret != 0) | ||
| 241 | dev_warn(dev, "Failed to set record LED state (error: %d).\n", | ||
| 242 | ret); | ||
| 243 | } | ||
| 244 | |||
| 245 | /* | ||
| 246 | * Keyboard attributes | ||
| 247 | */ | ||
| 248 | |||
| 249 | static ssize_t k90_show_macro_mode(struct device *dev, | ||
| 250 | struct device_attribute *attr, char *buf) | ||
| 251 | { | ||
| 252 | int ret; | ||
| 253 | struct usb_interface *usbif = to_usb_interface(dev->parent); | ||
| 254 | struct usb_device *usbdev = interface_to_usbdev(usbif); | ||
| 255 | const char *macro_mode; | ||
| 256 | char data[8]; | ||
| 257 | |||
| 258 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), | ||
| 259 | K90_REQUEST_GET_MODE, | ||
| 260 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
| 261 | USB_RECIP_DEVICE, 0, 0, data, 2, | ||
| 262 | USB_CTRL_SET_TIMEOUT); | ||
| 263 | if (ret < 0) { | ||
| 264 | dev_warn(dev, "Failed to get K90 initial mode (error %d).\n", | ||
| 265 | ret); | ||
| 266 | return -EIO; | ||
| 267 | } | ||
| 268 | |||
| 269 | switch (data[0]) { | ||
| 270 | case K90_MACRO_MODE_HW: | ||
| 271 | macro_mode = "HW"; | ||
| 272 | break; | ||
| 273 | |||
| 274 | case K90_MACRO_MODE_SW: | ||
| 275 | macro_mode = "SW"; | ||
| 276 | break; | ||
| 277 | default: | ||
| 278 | dev_warn(dev, "K90 in unknown mode: %02hhx.\n", | ||
| 279 | data[0]); | ||
| 280 | return -EIO; | ||
| 281 | } | ||
| 282 | |||
| 283 | return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode); | ||
| 284 | } | ||
| 285 | |||
| 286 | static ssize_t k90_store_macro_mode(struct device *dev, | ||
| 287 | struct device_attribute *attr, | ||
| 288 | const char *buf, size_t count) | ||
| 289 | { | ||
| 290 | int ret; | ||
| 291 | struct usb_interface *usbif = to_usb_interface(dev->parent); | ||
| 292 | struct usb_device *usbdev = interface_to_usbdev(usbif); | ||
| 293 | __u16 value; | ||
| 294 | |||
| 295 | if (strncmp(buf, "SW", 2) == 0) | ||
| 296 | value = K90_MACRO_MODE_SW; | ||
| 297 | else if (strncmp(buf, "HW", 2) == 0) | ||
| 298 | value = K90_MACRO_MODE_HW; | ||
| 299 | else | ||
| 300 | return -EINVAL; | ||
| 301 | |||
| 302 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | ||
| 303 | K90_REQUEST_MACRO_MODE, | ||
| 304 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
| 305 | USB_RECIP_DEVICE, value, 0, NULL, 0, | ||
| 306 | USB_CTRL_SET_TIMEOUT); | ||
| 307 | if (ret != 0) { | ||
| 308 | dev_warn(dev, "Failed to set macro mode.\n"); | ||
| 309 | return ret; | ||
| 310 | } | ||
| 311 | |||
| 312 | return count; | ||
| 313 | } | ||
| 314 | |||
| 315 | static ssize_t k90_show_current_profile(struct device *dev, | ||
| 316 | struct device_attribute *attr, | ||
| 317 | char *buf) | ||
| 318 | { | ||
| 319 | int ret; | ||
| 320 | struct usb_interface *usbif = to_usb_interface(dev->parent); | ||
| 321 | struct usb_device *usbdev = interface_to_usbdev(usbif); | ||
| 322 | int current_profile; | ||
| 323 | char data[8]; | ||
| 324 | |||
| 325 | ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), | ||
| 326 | K90_REQUEST_STATUS, | ||
| 327 | USB_DIR_IN | USB_TYPE_VENDOR | | ||
| 328 | USB_RECIP_DEVICE, 0, 0, data, 8, | ||
| 329 | USB_CTRL_SET_TIMEOUT); | ||
| 330 | if (ret < 0) { | ||
| 331 | dev_warn(dev, "Failed to get K90 initial state (error %d).\n", | ||
| 332 | ret); | ||
| 333 | return -EIO; | ||
| 334 | } | ||
| 335 | current_profile = data[7]; | ||
| 336 | if (current_profile < 1 || current_profile > 3) { | ||
| 337 | dev_warn(dev, "Read invalid current profile: %02hhx.\n", | ||
| 338 | data[7]); | ||
| 339 | return -EIO; | ||
| 340 | } | ||
| 341 | |||
| 342 | return snprintf(buf, PAGE_SIZE, "%d\n", current_profile); | ||
| 343 | } | ||
| 344 | |||
| 345 | static ssize_t k90_store_current_profile(struct device *dev, | ||
| 346 | struct device_attribute *attr, | ||
| 347 | const char *buf, size_t count) | ||
| 348 | { | ||
| 349 | int ret; | ||
| 350 | struct usb_interface *usbif = to_usb_interface(dev->parent); | ||
| 351 | struct usb_device *usbdev = interface_to_usbdev(usbif); | ||
| 352 | int profile; | ||
| 353 | |||
| 354 | if (kstrtoint(buf, 10, &profile)) | ||
| 355 | return -EINVAL; | ||
| 356 | if (profile < 1 || profile > 3) | ||
| 357 | return -EINVAL; | ||
| 358 | |||
| 359 | ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), | ||
| 360 | K90_REQUEST_PROFILE, | ||
| 361 | USB_DIR_OUT | USB_TYPE_VENDOR | | ||
| 362 | USB_RECIP_DEVICE, profile, 0, NULL, 0, | ||
| 363 | USB_CTRL_SET_TIMEOUT); | ||
| 364 | if (ret != 0) { | ||
| 365 | dev_warn(dev, "Failed to change current profile (error %d).\n", | ||
| 366 | ret); | ||
| 367 | return ret; | ||
| 368 | } | ||
| 369 | |||
| 370 | return count; | ||
| 371 | } | ||
| 372 | |||
| 373 | static DEVICE_ATTR(macro_mode, 0644, k90_show_macro_mode, k90_store_macro_mode); | ||
| 374 | static DEVICE_ATTR(current_profile, 0644, k90_show_current_profile, | ||
| 375 | k90_store_current_profile); | ||
| 376 | |||
| 377 | static struct attribute *k90_attrs[] = { | ||
| 378 | &dev_attr_macro_mode.attr, | ||
| 379 | &dev_attr_current_profile.attr, | ||
| 380 | NULL | ||
| 381 | }; | ||
| 382 | |||
| 383 | static const struct attribute_group k90_attr_group = { | ||
| 384 | .attrs = k90_attrs, | ||
| 385 | }; | ||
| 386 | |||
| 387 | /* | ||
| 388 | * Driver functions | ||
| 389 | */ | ||
| 390 | |||
| 391 | static int k90_init_backlight(struct hid_device *dev) | ||
| 392 | { | ||
| 393 | int ret; | ||
| 394 | struct corsair_drvdata *drvdata = hid_get_drvdata(dev); | ||
| 395 | size_t name_sz; | ||
| 396 | char *name; | ||
| 397 | |||
| 398 | drvdata->backlight = kzalloc(sizeof(struct k90_led), GFP_KERNEL); | ||
| 399 | if (!drvdata->backlight) { | ||
| 400 | ret = -ENOMEM; | ||
| 401 | goto fail_backlight_alloc; | ||
| 402 | } | ||
| 403 | |||
| 404 | name_sz = | ||
| 405 | strlen(dev_name(&dev->dev)) + sizeof(K90_BACKLIGHT_LED_SUFFIX); | ||
| 406 | name = kzalloc(name_sz, GFP_KERNEL); | ||
| 407 | if (!name) { | ||
| 408 | ret = -ENOMEM; | ||
| 409 | goto fail_name_alloc; | ||
| 410 | } | ||
| 411 | snprintf(name, name_sz, "%s" K90_BACKLIGHT_LED_SUFFIX, | ||
| 412 | dev_name(&dev->dev)); | ||
| 413 | drvdata->backlight->removed = false; | ||
| 414 | drvdata->backlight->cdev.name = name; | ||
| 415 | drvdata->backlight->cdev.max_brightness = 3; | ||
| 416 | drvdata->backlight->cdev.brightness_set = k90_brightness_set; | ||
| 417 | drvdata->backlight->cdev.brightness_get = k90_backlight_get; | ||
| 418 | INIT_WORK(&drvdata->backlight->work, k90_backlight_work); | ||
| 419 | ret = led_classdev_register(&dev->dev, &drvdata->backlight->cdev); | ||
| 420 | if (ret != 0) | ||
| 421 | goto fail_register_cdev; | ||
| 422 | |||
| 423 | return 0; | ||
| 424 | |||
| 425 | fail_register_cdev: | ||
| 426 | kfree(drvdata->backlight->cdev.name); | ||
| 427 | fail_name_alloc: | ||
| 428 | kfree(drvdata->backlight); | ||
| 429 | drvdata->backlight = NULL; | ||
| 430 | fail_backlight_alloc: | ||
| 431 | return ret; | ||
| 432 | } | ||
| 433 | |||
| 434 | static int k90_init_macro_functions(struct hid_device *dev) | ||
| 435 | { | ||
| 436 | int ret; | ||
| 437 | struct corsair_drvdata *drvdata = hid_get_drvdata(dev); | ||
| 438 | struct k90_drvdata *k90; | ||
| 439 | size_t name_sz; | ||
| 440 | char *name; | ||
| 441 | |||
| 442 | k90 = kzalloc(sizeof(struct k90_drvdata), GFP_KERNEL); | ||
| 443 | if (!k90) { | ||
| 444 | ret = -ENOMEM; | ||
| 445 | goto fail_drvdata; | ||
| 446 | } | ||
| 447 | drvdata->k90 = k90; | ||
| 448 | |||
| 449 | /* Init LED device for record LED */ | ||
| 450 | name_sz = strlen(dev_name(&dev->dev)) + sizeof(K90_RECORD_LED_SUFFIX); | ||
| 451 | name = kzalloc(name_sz, GFP_KERNEL); | ||
| 452 | if (!name) { | ||
| 453 | ret = -ENOMEM; | ||
| 454 | goto fail_record_led_alloc; | ||
| 455 | } | ||
| 456 | snprintf(name, name_sz, "%s" K90_RECORD_LED_SUFFIX, | ||
| 457 | dev_name(&dev->dev)); | ||
| 458 | k90->record_led.removed = false; | ||
| 459 | k90->record_led.cdev.name = name; | ||
| 460 | k90->record_led.cdev.max_brightness = 1; | ||
| 461 | k90->record_led.cdev.brightness_set = k90_brightness_set; | ||
| 462 | k90->record_led.cdev.brightness_get = k90_record_led_get; | ||
| 463 | INIT_WORK(&k90->record_led.work, k90_record_led_work); | ||
| 464 | k90->record_led.brightness = 0; | ||
| 465 | ret = led_classdev_register(&dev->dev, &k90->record_led.cdev); | ||
| 466 | if (ret != 0) | ||
| 467 | goto fail_record_led; | ||
| 468 | |||
| 469 | /* Init attributes */ | ||
| 470 | ret = sysfs_create_group(&dev->dev.kobj, &k90_attr_group); | ||
| 471 | if (ret != 0) | ||
| 472 | goto fail_sysfs; | ||
| 473 | |||
| 474 | return 0; | ||
| 475 | |||
| 476 | fail_sysfs: | ||
| 477 | k90->record_led.removed = true; | ||
| 478 | led_classdev_unregister(&k90->record_led.cdev); | ||
| 479 | cancel_work_sync(&k90->record_led.work); | ||
| 480 | fail_record_led: | ||
| 481 | kfree(k90->record_led.cdev.name); | ||
| 482 | fail_record_led_alloc: | ||
| 483 | kfree(k90); | ||
| 484 | fail_drvdata: | ||
| 485 | drvdata->k90 = NULL; | ||
| 486 | return ret; | ||
| 487 | } | ||
| 488 | |||
| 489 | static void k90_cleanup_backlight(struct hid_device *dev) | ||
| 490 | { | ||
| 491 | struct corsair_drvdata *drvdata = hid_get_drvdata(dev); | ||
| 492 | |||
| 493 | if (drvdata->backlight) { | ||
| 494 | drvdata->backlight->removed = true; | ||
| 495 | led_classdev_unregister(&drvdata->backlight->cdev); | ||
| 496 | cancel_work_sync(&drvdata->backlight->work); | ||
| 497 | kfree(drvdata->backlight->cdev.name); | ||
| 498 | kfree(drvdata->backlight); | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | static void k90_cleanup_macro_functions(struct hid_device *dev) | ||
| 503 | { | ||
| 504 | struct corsair_drvdata *drvdata = hid_get_drvdata(dev); | ||
| 505 | struct k90_drvdata *k90 = drvdata->k90; | ||
| 506 | |||
| 507 | if (k90) { | ||
| 508 | sysfs_remove_group(&dev->dev.kobj, &k90_attr_group); | ||
| 509 | |||
| 510 | k90->record_led.removed = true; | ||
| 511 | led_classdev_unregister(&k90->record_led.cdev); | ||
| 512 | cancel_work_sync(&k90->record_led.work); | ||
| 513 | kfree(k90->record_led.cdev.name); | ||
| 514 | |||
| 515 | kfree(k90); | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id) | ||
| 520 | { | ||
| 521 | int ret; | ||
| 522 | unsigned long quirks = id->driver_data; | ||
| 523 | struct corsair_drvdata *drvdata; | ||
| 524 | struct usb_interface *usbif = to_usb_interface(dev->dev.parent); | ||
| 525 | |||
| 526 | drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), | ||
| 527 | GFP_KERNEL); | ||
| 528 | if (drvdata == NULL) | ||
| 529 | return -ENOMEM; | ||
| 530 | drvdata->quirks = quirks; | ||
| 531 | hid_set_drvdata(dev, drvdata); | ||
| 532 | |||
| 533 | ret = hid_parse(dev); | ||
| 534 | if (ret != 0) { | ||
| 535 | hid_err(dev, "parse failed\n"); | ||
| 536 | return ret; | ||
| 537 | } | ||
| 538 | ret = hid_hw_start(dev, HID_CONNECT_DEFAULT); | ||
| 539 | if (ret != 0) { | ||
| 540 | hid_err(dev, "hw start failed\n"); | ||
| 541 | return ret; | ||
| 542 | } | ||
| 543 | |||
| 544 | if (usbif->cur_altsetting->desc.bInterfaceNumber == 0) { | ||
| 545 | if (quirks & CORSAIR_USE_K90_MACRO) { | ||
| 546 | ret = k90_init_macro_functions(dev); | ||
| 547 | if (ret != 0) | ||
| 548 | hid_warn(dev, "Failed to initialize K90 macro functions.\n"); | ||
| 549 | } | ||
| 550 | if (quirks & CORSAIR_USE_K90_BACKLIGHT) { | ||
| 551 | ret = k90_init_backlight(dev); | ||
| 552 | if (ret != 0) | ||
| 553 | hid_warn(dev, "Failed to initialize K90 backlight.\n"); | ||
| 554 | } | ||
| 555 | } | ||
| 556 | |||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | |||
| 560 | static void corsair_remove(struct hid_device *dev) | ||
| 561 | { | ||
| 562 | k90_cleanup_macro_functions(dev); | ||
| 563 | k90_cleanup_backlight(dev); | ||
| 564 | |||
| 565 | hid_hw_stop(dev); | ||
| 566 | } | ||
| 567 | |||
| 568 | static int corsair_event(struct hid_device *dev, struct hid_field *field, | ||
| 569 | struct hid_usage *usage, __s32 value) | ||
| 570 | { | ||
| 571 | struct corsair_drvdata *drvdata = hid_get_drvdata(dev); | ||
| 572 | |||
| 573 | if (!drvdata->k90) | ||
| 574 | return 0; | ||
| 575 | |||
| 576 | switch (usage->hid & HID_USAGE) { | ||
| 577 | case CORSAIR_USAGE_MACRO_RECORD_START: | ||
| 578 | drvdata->k90->record_led.brightness = 1; | ||
| 579 | break; | ||
| 580 | case CORSAIR_USAGE_MACRO_RECORD_STOP: | ||
| 581 | drvdata->k90->record_led.brightness = 0; | ||
| 582 | break; | ||
| 583 | default: | ||
| 584 | break; | ||
| 585 | } | ||
| 586 | |||
| 587 | return 0; | ||
| 588 | } | ||
| 589 | |||
| 590 | static int corsair_input_mapping(struct hid_device *dev, | ||
| 591 | struct hid_input *input, | ||
| 592 | struct hid_field *field, | ||
| 593 | struct hid_usage *usage, unsigned long **bit, | ||
| 594 | int *max) | ||
| 595 | { | ||
| 596 | int gkey; | ||
| 597 | |||
| 598 | gkey = corsair_usage_to_gkey(usage->hid & HID_USAGE); | ||
| 599 | if (gkey != 0) { | ||
| 600 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 601 | corsair_gkey_map[gkey - 1]); | ||
| 602 | return 1; | ||
| 603 | } | ||
| 604 | if ((usage->hid & HID_USAGE) >= CORSAIR_USAGE_SPECIAL_MIN && | ||
| 605 | (usage->hid & HID_USAGE) <= CORSAIR_USAGE_SPECIAL_MAX) { | ||
| 606 | switch (usage->hid & HID_USAGE) { | ||
| 607 | case CORSAIR_USAGE_MACRO_RECORD_START: | ||
| 608 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 609 | corsair_record_keycodes[0]); | ||
| 610 | return 1; | ||
| 611 | |||
| 612 | case CORSAIR_USAGE_MACRO_RECORD_STOP: | ||
| 613 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 614 | corsair_record_keycodes[1]); | ||
| 615 | return 1; | ||
| 616 | |||
| 617 | case CORSAIR_USAGE_M1: | ||
| 618 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 619 | corsair_profile_keycodes[0]); | ||
| 620 | return 1; | ||
| 621 | |||
| 622 | case CORSAIR_USAGE_M2: | ||
| 623 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 624 | corsair_profile_keycodes[1]); | ||
| 625 | return 1; | ||
| 626 | |||
| 627 | case CORSAIR_USAGE_M3: | ||
| 628 | hid_map_usage_clear(input, usage, bit, max, EV_KEY, | ||
| 629 | corsair_profile_keycodes[2]); | ||
| 630 | return 1; | ||
| 631 | |||
| 632 | default: | ||
| 633 | return -1; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | |||
| 637 | return 0; | ||
| 638 | } | ||
| 639 | |||
| 640 | static const struct hid_device_id corsair_devices[] = { | ||
| 641 | { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K90), | ||
| 642 | .driver_data = CORSAIR_USE_K90_MACRO | | ||
| 643 | CORSAIR_USE_K90_BACKLIGHT }, | ||
| 644 | {} | ||
| 645 | }; | ||
| 646 | |||
| 647 | MODULE_DEVICE_TABLE(hid, corsair_devices); | ||
| 648 | |||
| 649 | static struct hid_driver corsair_driver = { | ||
| 650 | .name = "corsair", | ||
| 651 | .id_table = corsair_devices, | ||
| 652 | .probe = corsair_probe, | ||
| 653 | .event = corsair_event, | ||
| 654 | .remove = corsair_remove, | ||
| 655 | .input_mapping = corsair_input_mapping, | ||
| 656 | }; | ||
| 657 | |||
| 658 | static int __init corsair_init(void) | ||
| 659 | { | ||
| 660 | return hid_register_driver(&corsair_driver); | ||
| 661 | } | ||
| 662 | |||
| 663 | static void corsair_exit(void) | ||
| 664 | { | ||
| 665 | hid_unregister_driver(&corsair_driver); | ||
| 666 | } | ||
| 667 | |||
| 668 | module_init(corsair_init); | ||
| 669 | module_exit(corsair_exit); | ||
| 670 | |||
| 671 | MODULE_LICENSE("GPL"); | ||
| 672 | MODULE_AUTHOR("Clement Vuchener"); | ||
| 673 | MODULE_DESCRIPTION("HID driver for Corsair devices"); | ||
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index ce0644424f58..1d78ba3b799e 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c | |||
| @@ -234,6 +234,58 @@ static __u8 pid0011_rdesc_fixed[] = { | |||
| 234 | 0xC0 /* End Collection */ | 234 | 0xC0 /* End Collection */ |
| 235 | }; | 235 | }; |
| 236 | 236 | ||
| 237 | static __u8 pid0006_rdesc_fixed[] = { | ||
| 238 | 0x05, 0x01, /* Usage Page (Generic Desktop) */ | ||
| 239 | 0x09, 0x04, /* Usage (Joystick) */ | ||
| 240 | 0xA1, 0x01, /* Collection (Application) */ | ||
| 241 | 0xA1, 0x02, /* Collection (Logical) */ | ||
| 242 | 0x75, 0x08, /* Report Size (8) */ | ||
| 243 | 0x95, 0x05, /* Report Count (5) */ | ||
| 244 | 0x15, 0x00, /* Logical Minimum (0) */ | ||
| 245 | 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ | ||
| 246 | 0x35, 0x00, /* Physical Minimum (0) */ | ||
| 247 | 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ | ||
| 248 | 0x09, 0x30, /* Usage (X) */ | ||
| 249 | 0x09, 0x33, /* Usage (Ry) */ | ||
| 250 | 0x09, 0x32, /* Usage (Z) */ | ||
| 251 | 0x09, 0x31, /* Usage (Y) */ | ||
| 252 | 0x09, 0x34, /* Usage (Ry) */ | ||
| 253 | 0x81, 0x02, /* Input (Variable) */ | ||
| 254 | 0x75, 0x04, /* Report Size (4) */ | ||
| 255 | 0x95, 0x01, /* Report Count (1) */ | ||
| 256 | 0x25, 0x07, /* Logical Maximum (7) */ | ||
| 257 | 0x46, 0x3B, 0x01, /* Physical Maximum (315) */ | ||
| 258 | 0x65, 0x14, /* Unit (Centimeter) */ | ||
| 259 | 0x09, 0x39, /* Usage (Hat switch) */ | ||
| 260 | 0x81, 0x42, /* Input (Variable) */ | ||
| 261 | 0x65, 0x00, /* Unit (None) */ | ||
| 262 | 0x75, 0x01, /* Report Size (1) */ | ||
| 263 | 0x95, 0x0C, /* Report Count (12) */ | ||
| 264 | 0x25, 0x01, /* Logical Maximum (1) */ | ||
| 265 | 0x45, 0x01, /* Physical Maximum (1) */ | ||
| 266 | 0x05, 0x09, /* Usage Page (Button) */ | ||
| 267 | 0x19, 0x01, /* Usage Minimum (0x01) */ | ||
| 268 | 0x29, 0x0C, /* Usage Maximum (0x0C) */ | ||
| 269 | 0x81, 0x02, /* Input (Variable) */ | ||
| 270 | 0x06, 0x00, 0xFF, /* Usage Page (Vendor Defined) */ | ||
| 271 | 0x75, 0x01, /* Report Size (1) */ | ||
| 272 | 0x95, 0x08, /* Report Count (8) */ | ||
| 273 | 0x25, 0x01, /* Logical Maximum (1) */ | ||
| 274 | 0x45, 0x01, /* Physical Maximum (1) */ | ||
| 275 | 0x09, 0x01, /* Usage (0x01) */ | ||
| 276 | 0x81, 0x02, /* Input (Variable) */ | ||
| 277 | 0xC0, /* End Collection */ | ||
| 278 | 0xA1, 0x02, /* Collection (Logical) */ | ||
| 279 | 0x75, 0x08, /* Report Size (8) */ | ||
| 280 | 0x95, 0x07, /* Report Count (7) */ | ||
| 281 | 0x46, 0xFF, 0x00, /* Physical Maximum (255) */ | ||
| 282 | 0x26, 0xFF, 0x00, /* Logical Maximum (255) */ | ||
| 283 | 0x09, 0x02, /* Usage (0x02) */ | ||
| 284 | 0x91, 0x02, /* Output (Variable) */ | ||
| 285 | 0xC0, /* End Collection */ | ||
| 286 | 0xC0 /* End Collection */ | ||
| 287 | }; | ||
| 288 | |||
| 237 | static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 289 | static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 238 | unsigned int *rsize) | 290 | unsigned int *rsize) |
| 239 | { | 291 | { |
| @@ -244,6 +296,12 @@ static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 244 | *rsize = sizeof(pid0011_rdesc_fixed); | 296 | *rsize = sizeof(pid0011_rdesc_fixed); |
| 245 | } | 297 | } |
| 246 | break; | 298 | break; |
| 299 | case 0x0006: | ||
| 300 | if (*rsize == sizeof(pid0006_rdesc_fixed)) { | ||
| 301 | rdesc = pid0006_rdesc_fixed; | ||
| 302 | *rsize = sizeof(pid0006_rdesc_fixed); | ||
| 303 | } | ||
| 304 | break; | ||
| 247 | } | 305 | } |
| 248 | return rdesc; | 306 | return rdesc; |
| 249 | } | 307 | } |
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index d0bd13b62dc2..6e3848a8d8dd 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c | |||
| @@ -27,7 +27,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
| 27 | hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); | 27 | hid_info(hdev, "Fixing up Elecom BM084 report descriptor\n"); |
| 28 | rdesc[47] = 0x00; | 28 | rdesc[47] = 0x00; |
| 29 | } | 29 | } |
| 30 | return rdesc; | 30 | return rdesc; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | static const struct hid_device_id elecom_devices[] = { | 33 | static const struct hid_device_id elecom_devices[] = { |
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c index 4e49462870ab..aad8c162a825 100644 --- a/drivers/hid/hid-elo.c +++ b/drivers/hid/hid-elo.c | |||
| @@ -37,7 +37,7 @@ static bool use_fw_quirk = true; | |||
| 37 | module_param(use_fw_quirk, bool, S_IRUGO); | 37 | module_param(use_fw_quirk, bool, S_IRUGO); |
| 38 | MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); | 38 | MODULE_PARM_DESC(use_fw_quirk, "Do periodic pokes for broken M firmwares (default = true)"); |
| 39 | 39 | ||
| 40 | static void elo_input_configured(struct hid_device *hdev, | 40 | static int elo_input_configured(struct hid_device *hdev, |
| 41 | struct hid_input *hidinput) | 41 | struct hid_input *hidinput) |
| 42 | { | 42 | { |
| 43 | struct input_dev *input = hidinput->input; | 43 | struct input_dev *input = hidinput->input; |
| @@ -45,6 +45,8 @@ static void elo_input_configured(struct hid_device *hdev, | |||
| 45 | set_bit(BTN_TOUCH, input->keybit); | 45 | set_bit(BTN_TOUCH, input->keybit); |
| 46 | set_bit(ABS_PRESSURE, input->absbit); | 46 | set_bit(ABS_PRESSURE, input->absbit); |
| 47 | input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); | 47 | input_set_abs_params(input, ABS_PRESSURE, 0, 256, 0, 0); |
| 48 | |||
| 49 | return 0; | ||
| 48 | } | 50 | } |
| 49 | 51 | ||
| 50 | static void elo_process_data(struct input_dev *input, const u8 *data, int size) | 52 | static void elo_process_data(struct input_dev *input, const u8 *data, int size) |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b797adda2bc..ac1feea51be3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -251,6 +251,9 @@ | |||
| 251 | #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 | 251 | #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST 0x1500 |
| 252 | #define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff | 252 | #define USB_DEVICE_ID_CODEMERCS_IOW_LAST 0x15ff |
| 253 | 253 | ||
| 254 | #define USB_VENDOR_ID_CORSAIR 0x1b1c | ||
| 255 | #define USB_DEVICE_ID_CORSAIR_K90 0x1b02 | ||
| 256 | |||
| 254 | #define USB_VENDOR_ID_CREATIVELABS 0x041e | 257 | #define USB_VENDOR_ID_CREATIVELABS 0x041e |
| 255 | #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 | 258 | #define USB_DEVICE_ID_PRODIKEYS_PCMIDI 0x2801 |
| 256 | 259 | ||
| @@ -648,6 +651,7 @@ | |||
| 648 | 651 | ||
| 649 | #define USB_VENDOR_ID_MADCATZ 0x0738 | 652 | #define USB_VENDOR_ID_MADCATZ 0x0738 |
| 650 | #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 | 653 | #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 |
| 654 | #define USB_DEVICE_ID_MADCATZ_RAT5 0x1705 | ||
| 651 | #define USB_DEVICE_ID_MADCATZ_RAT9 0x1709 | 655 | #define USB_DEVICE_ID_MADCATZ_RAT9 0x1709 |
| 652 | 656 | ||
| 653 | #define USB_VENDOR_ID_MCC 0x09db | 657 | #define USB_VENDOR_ID_MCC 0x09db |
| @@ -681,6 +685,7 @@ | |||
| 681 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 | 685 | #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 |
| 682 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 | 686 | #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 |
| 683 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc | 687 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc |
| 688 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2 | ||
| 684 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd | 689 | #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd |
| 685 | #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de | 690 | #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de |
| 686 | #define USB_DEVICE_ID_MS_POWER_COVER 0x07da | 691 | #define USB_DEVICE_ID_MS_POWER_COVER 0x07da |
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 53aeaf6252c7..2ba6bf69b7d0 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
| @@ -1510,8 +1510,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1510 | * UGCI) cram a lot of unrelated inputs into the | 1510 | * UGCI) cram a lot of unrelated inputs into the |
| 1511 | * same interface. */ | 1511 | * same interface. */ |
| 1512 | hidinput->report = report; | 1512 | hidinput->report = report; |
| 1513 | if (drv->input_configured) | 1513 | if (drv->input_configured && |
| 1514 | drv->input_configured(hid, hidinput); | 1514 | drv->input_configured(hid, hidinput)) |
| 1515 | goto out_cleanup; | ||
| 1515 | if (input_register_device(hidinput->input)) | 1516 | if (input_register_device(hidinput->input)) |
| 1516 | goto out_cleanup; | 1517 | goto out_cleanup; |
| 1517 | hidinput = NULL; | 1518 | hidinput = NULL; |
| @@ -1532,8 +1533,9 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
| 1532 | } | 1533 | } |
| 1533 | 1534 | ||
| 1534 | if (hidinput) { | 1535 | if (hidinput) { |
| 1535 | if (drv->input_configured) | 1536 | if (drv->input_configured && |
| 1536 | drv->input_configured(hid, hidinput); | 1537 | drv->input_configured(hid, hidinput)) |
| 1538 | goto out_cleanup; | ||
| 1537 | if (input_register_device(hidinput->input)) | 1539 | if (input_register_device(hidinput->input)) |
| 1538 | goto out_cleanup; | 1540 | goto out_cleanup; |
| 1539 | } | 1541 | } |
diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index e4bc6cb6d7fa..8979f1fd5208 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c | |||
| @@ -848,7 +848,7 @@ static void lenovo_remove(struct hid_device *hdev) | |||
| 848 | hid_hw_stop(hdev); | 848 | hid_hw_stop(hdev); |
| 849 | } | 849 | } |
| 850 | 850 | ||
| 851 | static void lenovo_input_configured(struct hid_device *hdev, | 851 | static int lenovo_input_configured(struct hid_device *hdev, |
| 852 | struct hid_input *hi) | 852 | struct hid_input *hi) |
| 853 | { | 853 | { |
| 854 | switch (hdev->product) { | 854 | switch (hdev->product) { |
| @@ -863,6 +863,8 @@ static void lenovo_input_configured(struct hid_device *hdev, | |||
| 863 | } | 863 | } |
| 864 | break; | 864 | break; |
| 865 | } | 865 | } |
| 866 | |||
| 867 | return 0; | ||
| 866 | } | 868 | } |
| 867 | 869 | ||
| 868 | 870 | ||
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 5332fb7d072a..c20ac76c0a8c 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
| @@ -620,6 +620,7 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 620 | usage->code == ABS_Y || usage->code == ABS_Z || | 620 | usage->code == ABS_Y || usage->code == ABS_Z || |
| 621 | usage->code == ABS_RZ)) { | 621 | usage->code == ABS_RZ)) { |
| 622 | switch (hdev->product) { | 622 | switch (hdev->product) { |
| 623 | case USB_DEVICE_ID_LOGITECH_G29_WHEEL: | ||
| 623 | case USB_DEVICE_ID_LOGITECH_WHEEL: | 624 | case USB_DEVICE_ID_LOGITECH_WHEEL: |
| 624 | case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: | 625 | case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: |
| 625 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: | 626 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: |
| @@ -658,10 +659,18 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field, | |||
| 658 | 659 | ||
| 659 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | 660 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 660 | { | 661 | { |
| 662 | struct usb_interface *iface = to_usb_interface(hdev->dev.parent); | ||
| 663 | __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; | ||
| 661 | unsigned int connect_mask = HID_CONNECT_DEFAULT; | 664 | unsigned int connect_mask = HID_CONNECT_DEFAULT; |
| 662 | struct lg_drv_data *drv_data; | 665 | struct lg_drv_data *drv_data; |
| 663 | int ret; | 666 | int ret; |
| 664 | 667 | ||
| 668 | /* Only work with the 1st interface (G29 presents multiple) */ | ||
| 669 | if (iface_num != 0) { | ||
| 670 | dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num); | ||
| 671 | return -ENODEV; | ||
| 672 | } | ||
| 673 | |||
| 665 | drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); | 674 | drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); |
| 666 | if (!drv_data) { | 675 | if (!drv_data) { |
| 667 | hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); | 676 | hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); |
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 02cec83caac3..fbddcb37ae98 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c | |||
| @@ -45,7 +45,8 @@ | |||
| 45 | #define LG4FF_MODE_G25_IDX 3 | 45 | #define LG4FF_MODE_G25_IDX 3 |
| 46 | #define LG4FF_MODE_DFGT_IDX 4 | 46 | #define LG4FF_MODE_DFGT_IDX 4 |
| 47 | #define LG4FF_MODE_G27_IDX 5 | 47 | #define LG4FF_MODE_G27_IDX 5 |
| 48 | #define LG4FF_MODE_MAX_IDX 6 | 48 | #define LG4FF_MODE_G29_IDX 6 |
| 49 | #define LG4FF_MODE_MAX_IDX 7 | ||
| 49 | 50 | ||
| 50 | #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX) | 51 | #define LG4FF_MODE_NATIVE BIT(LG4FF_MODE_NATIVE_IDX) |
| 51 | #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX) | 52 | #define LG4FF_MODE_DFEX BIT(LG4FF_MODE_DFEX_IDX) |
| @@ -53,6 +54,7 @@ | |||
| 53 | #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX) | 54 | #define LG4FF_MODE_G25 BIT(LG4FF_MODE_G25_IDX) |
| 54 | #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX) | 55 | #define LG4FF_MODE_DFGT BIT(LG4FF_MODE_DFGT_IDX) |
| 55 | #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX) | 56 | #define LG4FF_MODE_G27 BIT(LG4FF_MODE_G27_IDX) |
| 57 | #define LG4FF_MODE_G29 BIT(LG4FF_MODE_G29_IDX) | ||
| 56 | 58 | ||
| 57 | #define LG4FF_DFEX_TAG "DF-EX" | 59 | #define LG4FF_DFEX_TAG "DF-EX" |
| 58 | #define LG4FF_DFEX_NAME "Driving Force / Formula EX" | 60 | #define LG4FF_DFEX_NAME "Driving Force / Formula EX" |
| @@ -62,6 +64,8 @@ | |||
| 62 | #define LG4FF_G25_NAME "G25 Racing Wheel" | 64 | #define LG4FF_G25_NAME "G25 Racing Wheel" |
| 63 | #define LG4FF_G27_TAG "G27" | 65 | #define LG4FF_G27_TAG "G27" |
| 64 | #define LG4FF_G27_NAME "G27 Racing Wheel" | 66 | #define LG4FF_G27_NAME "G27 Racing Wheel" |
| 67 | #define LG4FF_G29_TAG "G29" | ||
| 68 | #define LG4FF_G29_NAME "G29 Racing Wheel" | ||
| 65 | #define LG4FF_DFGT_TAG "DFGT" | 69 | #define LG4FF_DFGT_TAG "DFGT" |
| 66 | #define LG4FF_DFGT_NAME "Driving Force GT" | 70 | #define LG4FF_DFGT_NAME "Driving Force GT" |
| 67 | 71 | ||
| @@ -114,16 +118,12 @@ struct lg4ff_compat_mode_switch { | |||
| 114 | }; | 118 | }; |
| 115 | 119 | ||
| 116 | struct lg4ff_wheel_ident_info { | 120 | struct lg4ff_wheel_ident_info { |
| 121 | const u32 modes; | ||
| 117 | const u16 mask; | 122 | const u16 mask; |
| 118 | const u16 result; | 123 | const u16 result; |
| 119 | const u16 real_product_id; | 124 | const u16 real_product_id; |
| 120 | }; | 125 | }; |
| 121 | 126 | ||
| 122 | struct lg4ff_wheel_ident_checklist { | ||
| 123 | const u32 count; | ||
| 124 | const struct lg4ff_wheel_ident_info *models[]; | ||
| 125 | }; | ||
| 126 | |||
| 127 | struct lg4ff_multimode_wheel { | 127 | struct lg4ff_multimode_wheel { |
| 128 | const u16 product_id; | 128 | const u16 product_id; |
| 129 | const u32 alternate_modes; | 129 | const u32 alternate_modes; |
| @@ -144,6 +144,7 @@ static const struct lg4ff_wheel lg4ff_devices[] = { | |||
| 144 | {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, | 144 | {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, |
| 145 | {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, | 145 | {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, |
| 146 | {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, | 146 | {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, |
| 147 | {USB_DEVICE_ID_LOGITECH_G29_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, | ||
| 147 | {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, | 148 | {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, |
| 148 | {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} | 149 | {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} |
| 149 | }; | 150 | }; |
| @@ -161,6 +162,9 @@ static const struct lg4ff_multimode_wheel lg4ff_multimode_wheels[] = { | |||
| 161 | {USB_DEVICE_ID_LOGITECH_G27_WHEEL, | 162 | {USB_DEVICE_ID_LOGITECH_G27_WHEEL, |
| 162 | LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | 163 | LG4FF_MODE_NATIVE | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, |
| 163 | LG4FF_G27_TAG, LG4FF_G27_NAME}, | 164 | LG4FF_G27_TAG, LG4FF_G27_NAME}, |
| 165 | {USB_DEVICE_ID_LOGITECH_G29_WHEEL, | ||
| 166 | LG4FF_MODE_NATIVE | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 167 | LG4FF_G29_TAG, LG4FF_G29_NAME}, | ||
| 164 | }; | 168 | }; |
| 165 | 169 | ||
| 166 | static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { | 170 | static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { |
| @@ -169,41 +173,61 @@ static const struct lg4ff_alternate_mode lg4ff_alternate_modes[] = { | |||
| 169 | [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME}, | 173 | [LG4FF_MODE_DFP_IDX] = {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, LG4FF_DFP_TAG, LG4FF_DFP_NAME}, |
| 170 | [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME}, | 174 | [LG4FF_MODE_G25_IDX] = {USB_DEVICE_ID_LOGITECH_G25_WHEEL, LG4FF_G25_TAG, LG4FF_G25_NAME}, |
| 171 | [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME}, | 175 | [LG4FF_MODE_DFGT_IDX] = {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, LG4FF_DFGT_TAG, LG4FF_DFGT_NAME}, |
| 172 | [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME} | 176 | [LG4FF_MODE_G27_IDX] = {USB_DEVICE_ID_LOGITECH_G27_WHEEL, LG4FF_G27_TAG, LG4FF_G27_NAME}, |
| 177 | [LG4FF_MODE_G29_IDX] = {USB_DEVICE_ID_LOGITECH_G29_WHEEL, LG4FF_G29_TAG, LG4FF_G29_NAME}, | ||
| 173 | }; | 178 | }; |
| 174 | 179 | ||
| 175 | /* Multimode wheel identificators */ | 180 | /* Multimode wheel identificators */ |
| 176 | static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = { | 181 | static const struct lg4ff_wheel_ident_info lg4ff_dfp_ident_info = { |
| 182 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 177 | 0xf000, | 183 | 0xf000, |
| 178 | 0x1000, | 184 | 0x1000, |
| 179 | USB_DEVICE_ID_LOGITECH_DFP_WHEEL | 185 | USB_DEVICE_ID_LOGITECH_DFP_WHEEL |
| 180 | }; | 186 | }; |
| 181 | 187 | ||
| 182 | static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = { | 188 | static const struct lg4ff_wheel_ident_info lg4ff_g25_ident_info = { |
| 189 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 183 | 0xff00, | 190 | 0xff00, |
| 184 | 0x1200, | 191 | 0x1200, |
| 185 | USB_DEVICE_ID_LOGITECH_G25_WHEEL | 192 | USB_DEVICE_ID_LOGITECH_G25_WHEEL |
| 186 | }; | 193 | }; |
| 187 | 194 | ||
| 188 | static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = { | 195 | static const struct lg4ff_wheel_ident_info lg4ff_g27_ident_info = { |
| 196 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 189 | 0xfff0, | 197 | 0xfff0, |
| 190 | 0x1230, | 198 | 0x1230, |
| 191 | USB_DEVICE_ID_LOGITECH_G27_WHEEL | 199 | USB_DEVICE_ID_LOGITECH_G27_WHEEL |
| 192 | }; | 200 | }; |
| 193 | 201 | ||
| 194 | static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = { | 202 | static const struct lg4ff_wheel_ident_info lg4ff_dfgt_ident_info = { |
| 203 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 195 | 0xff00, | 204 | 0xff00, |
| 196 | 0x1300, | 205 | 0x1300, |
| 197 | USB_DEVICE_ID_LOGITECH_DFGT_WHEEL | 206 | USB_DEVICE_ID_LOGITECH_DFGT_WHEEL |
| 198 | }; | 207 | }; |
| 199 | 208 | ||
| 209 | static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info = { | ||
| 210 | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 211 | 0xfff8, | ||
| 212 | 0x1350, | ||
| 213 | USB_DEVICE_ID_LOGITECH_G29_WHEEL | ||
| 214 | }; | ||
| 215 | |||
| 216 | static const struct lg4ff_wheel_ident_info lg4ff_g29_ident_info2 = { | ||
| 217 | LG4FF_MODE_G29 | LG4FF_MODE_G27 | LG4FF_MODE_G25 | LG4FF_MODE_DFGT | LG4FF_MODE_DFP | LG4FF_MODE_DFEX, | ||
| 218 | 0xff00, | ||
| 219 | 0x8900, | ||
| 220 | USB_DEVICE_ID_LOGITECH_G29_WHEEL | ||
| 221 | }; | ||
| 222 | |||
| 200 | /* Multimode wheel identification checklists */ | 223 | /* Multimode wheel identification checklists */ |
| 201 | static const struct lg4ff_wheel_ident_checklist lg4ff_main_checklist = { | 224 | static const struct lg4ff_wheel_ident_info *lg4ff_main_checklist[] = { |
| 202 | 4, | 225 | &lg4ff_g29_ident_info, |
| 203 | {&lg4ff_dfgt_ident_info, | 226 | &lg4ff_g29_ident_info2, |
| 204 | &lg4ff_g27_ident_info, | 227 | &lg4ff_dfgt_ident_info, |
| 205 | &lg4ff_g25_ident_info, | 228 | &lg4ff_g27_ident_info, |
| 206 | &lg4ff_dfp_ident_info} | 229 | &lg4ff_g25_ident_info, |
| 230 | &lg4ff_dfp_ident_info | ||
| 207 | }; | 231 | }; |
| 208 | 232 | ||
| 209 | /* Compatibility mode switching commands */ | 233 | /* Compatibility mode switching commands */ |
| @@ -238,6 +262,12 @@ static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g27 = { | |||
| 238 | 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */ | 262 | 0xf8, 0x09, 0x04, 0x01, 0x00, 0x00, 0x00} /* Switch mode to G27 with detach */ |
| 239 | }; | 263 | }; |
| 240 | 264 | ||
| 265 | static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext09_g29 = { | ||
| 266 | 2, | ||
| 267 | {0xf8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, /* Revert mode upon USB reset */ | ||
| 268 | 0xf8, 0x09, 0x05, 0x01, 0x01, 0x00, 0x00} /* Switch mode to G29 with detach */ | ||
| 269 | }; | ||
| 270 | |||
| 241 | /* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */ | 271 | /* EXT_CMD1 - Understood by DFP, G25, G27 and DFGT */ |
| 242 | static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = { | 272 | static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext01_dfp = { |
| 243 | 1, | 273 | 1, |
| @@ -651,6 +681,23 @@ static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(cons | |||
| 651 | return NULL; | 681 | return NULL; |
| 652 | } | 682 | } |
| 653 | break; | 683 | break; |
| 684 | case USB_DEVICE_ID_LOGITECH_G29_WHEEL: | ||
| 685 | switch (target_product_id) { | ||
| 686 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: | ||
| 687 | return &lg4ff_mode_switch_ext09_dfp; | ||
| 688 | case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: | ||
| 689 | return &lg4ff_mode_switch_ext09_dfgt; | ||
| 690 | case USB_DEVICE_ID_LOGITECH_G25_WHEEL: | ||
| 691 | return &lg4ff_mode_switch_ext09_g25; | ||
| 692 | case USB_DEVICE_ID_LOGITECH_G27_WHEEL: | ||
| 693 | return &lg4ff_mode_switch_ext09_g27; | ||
| 694 | case USB_DEVICE_ID_LOGITECH_G29_WHEEL: | ||
| 695 | return &lg4ff_mode_switch_ext09_g29; | ||
| 696 | /* G29 can only be switched to DF-EX, DFP, DFGT, G25, G27 or its native mode */ | ||
| 697 | default: | ||
| 698 | return NULL; | ||
| 699 | } | ||
| 700 | break; | ||
| 654 | case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: | 701 | case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: |
| 655 | switch (target_product_id) { | 702 | switch (target_product_id) { |
| 656 | case USB_DEVICE_ID_LOGITECH_WHEEL: | 703 | case USB_DEVICE_ID_LOGITECH_WHEEL: |
| @@ -1037,41 +1084,28 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde | |||
| 1037 | 1084 | ||
| 1038 | static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice) | 1085 | static u16 lg4ff_identify_multimode_wheel(struct hid_device *hid, const u16 reported_product_id, const u16 bcdDevice) |
| 1039 | { | 1086 | { |
| 1040 | const struct lg4ff_wheel_ident_checklist *checklist; | 1087 | u32 current_mode; |
| 1041 | int i, from_idx, to_idx; | 1088 | int i; |
| 1042 | 1089 | ||
| 1043 | switch (reported_product_id) { | 1090 | /* identify current mode from USB PID */ |
| 1044 | case USB_DEVICE_ID_LOGITECH_WHEEL: | 1091 | for (i = 1; i < ARRAY_SIZE(lg4ff_alternate_modes); i++) { |
| 1045 | case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: | 1092 | dbg_hid("Testing whether PID is %X\n", lg4ff_alternate_modes[i].product_id); |
| 1046 | checklist = &lg4ff_main_checklist; | 1093 | if (reported_product_id == lg4ff_alternate_modes[i].product_id) |
| 1047 | from_idx = 0; | 1094 | break; |
| 1048 | to_idx = checklist->count - 1; | ||
| 1049 | break; | ||
| 1050 | case USB_DEVICE_ID_LOGITECH_G25_WHEEL: | ||
| 1051 | checklist = &lg4ff_main_checklist; | ||
| 1052 | from_idx = 0; | ||
| 1053 | to_idx = checklist->count - 2; /* End identity check at G25 */ | ||
| 1054 | break; | ||
| 1055 | case USB_DEVICE_ID_LOGITECH_G27_WHEEL: | ||
| 1056 | checklist = &lg4ff_main_checklist; | ||
| 1057 | from_idx = 1; /* Start identity check at G27 */ | ||
| 1058 | to_idx = checklist->count - 3; /* End identity check at G27 */ | ||
| 1059 | break; | ||
| 1060 | case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: | ||
| 1061 | checklist = &lg4ff_main_checklist; | ||
| 1062 | from_idx = 0; | ||
| 1063 | to_idx = checklist->count - 4; /* End identity check at DFGT */ | ||
| 1064 | break; | ||
| 1065 | default: | ||
| 1066 | return 0; | ||
| 1067 | } | 1095 | } |
| 1068 | 1096 | ||
| 1069 | for (i = from_idx; i <= to_idx; i++) { | 1097 | if (i == ARRAY_SIZE(lg4ff_alternate_modes)) |
| 1070 | const u16 mask = checklist->models[i]->mask; | 1098 | return 0; |
| 1071 | const u16 result = checklist->models[i]->result; | 1099 | |
| 1072 | const u16 real_product_id = checklist->models[i]->real_product_id; | 1100 | current_mode = BIT(i); |
| 1101 | |||
| 1102 | for (i = 0; i < ARRAY_SIZE(lg4ff_main_checklist); i++) { | ||
| 1103 | const u16 mask = lg4ff_main_checklist[i]->mask; | ||
| 1104 | const u16 result = lg4ff_main_checklist[i]->result; | ||
| 1105 | const u16 real_product_id = lg4ff_main_checklist[i]->real_product_id; | ||
| 1073 | 1106 | ||
| 1074 | if ((bcdDevice & mask) == result) { | 1107 | if ((current_mode & lg4ff_main_checklist[i]->modes) && \ |
| 1108 | (bcdDevice & mask) == result) { | ||
| 1075 | dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id); | 1109 | dbg_hid("Found wheel with real PID %X whose reported PID is %X\n", real_product_id, reported_product_id); |
| 1076 | return real_product_id; | 1110 | return real_product_id; |
| 1077 | } | 1111 | } |
| @@ -1246,12 +1280,13 @@ int lg4ff_init(struct hid_device *hid) | |||
| 1246 | entry->wdata.set_range(hid, entry->wdata.range); | 1280 | entry->wdata.set_range(hid, entry->wdata.range); |
| 1247 | 1281 | ||
| 1248 | #ifdef CONFIG_LEDS_CLASS | 1282 | #ifdef CONFIG_LEDS_CLASS |
| 1249 | /* register led subsystem - G27 only */ | 1283 | /* register led subsystem - G27/G29 only */ |
| 1250 | entry->wdata.led_state = 0; | 1284 | entry->wdata.led_state = 0; |
| 1251 | for (j = 0; j < 5; j++) | 1285 | for (j = 0; j < 5; j++) |
| 1252 | entry->wdata.led[j] = NULL; | 1286 | entry->wdata.led[j] = NULL; |
| 1253 | 1287 | ||
| 1254 | if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) { | 1288 | if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL || |
| 1289 | lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G29_WHEEL) { | ||
| 1255 | struct led_classdev *led; | 1290 | struct led_classdev *led; |
| 1256 | size_t name_sz; | 1291 | size_t name_sz; |
| 1257 | char *name; | 1292 | char *name; |
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 484196459305..5fd97860aec4 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c | |||
| @@ -33,6 +33,11 @@ module_param(disable_raw_mode, bool, 0644); | |||
| 33 | MODULE_PARM_DESC(disable_raw_mode, | 33 | MODULE_PARM_DESC(disable_raw_mode, |
| 34 | "Disable Raw mode reporting for touchpads and keep firmware gestures."); | 34 | "Disable Raw mode reporting for touchpads and keep firmware gestures."); |
| 35 | 35 | ||
| 36 | static bool disable_tap_to_click; | ||
| 37 | module_param(disable_tap_to_click, bool, 0644); | ||
| 38 | MODULE_PARM_DESC(disable_tap_to_click, | ||
| 39 | "Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently)."); | ||
| 40 | |||
| 36 | #define REPORT_ID_HIDPP_SHORT 0x10 | 41 | #define REPORT_ID_HIDPP_SHORT 0x10 |
| 37 | #define REPORT_ID_HIDPP_LONG 0x11 | 42 | #define REPORT_ID_HIDPP_LONG 0x11 |
| 38 | 43 | ||
| @@ -41,10 +46,15 @@ MODULE_PARM_DESC(disable_raw_mode, | |||
| 41 | 46 | ||
| 42 | #define HIDPP_QUIRK_CLASS_WTP BIT(0) | 47 | #define HIDPP_QUIRK_CLASS_WTP BIT(0) |
| 43 | #define HIDPP_QUIRK_CLASS_M560 BIT(1) | 48 | #define HIDPP_QUIRK_CLASS_M560 BIT(1) |
| 49 | #define HIDPP_QUIRK_CLASS_K400 BIT(2) | ||
| 44 | 50 | ||
| 45 | /* bits 2..20 are reserved for classes */ | 51 | /* bits 2..20 are reserved for classes */ |
| 46 | #define HIDPP_QUIRK_DELAYED_INIT BIT(21) | 52 | #define HIDPP_QUIRK_CONNECT_EVENTS BIT(21) |
| 47 | #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) | 53 | #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) |
| 54 | #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) | ||
| 55 | |||
| 56 | #define HIDPP_QUIRK_DELAYED_INIT (HIDPP_QUIRK_NO_HIDINPUT | \ | ||
| 57 | HIDPP_QUIRK_CONNECT_EVENTS) | ||
| 48 | 58 | ||
| 49 | /* | 59 | /* |
| 50 | * There are two hidpp protocols in use, the first version hidpp10 is known | 60 | * There are two hidpp protocols in use, the first version hidpp10 is known |
| @@ -553,6 +563,52 @@ static char *hidpp_get_device_name(struct hidpp_device *hidpp) | |||
| 553 | } | 563 | } |
| 554 | 564 | ||
| 555 | /* -------------------------------------------------------------------------- */ | 565 | /* -------------------------------------------------------------------------- */ |
| 566 | /* 0x6010: Touchpad FW items */ | ||
| 567 | /* -------------------------------------------------------------------------- */ | ||
| 568 | |||
| 569 | #define HIDPP_PAGE_TOUCHPAD_FW_ITEMS 0x6010 | ||
| 570 | |||
| 571 | #define CMD_TOUCHPAD_FW_ITEMS_SET 0x10 | ||
| 572 | |||
| 573 | struct hidpp_touchpad_fw_items { | ||
| 574 | uint8_t presence; | ||
| 575 | uint8_t desired_state; | ||
| 576 | uint8_t state; | ||
| 577 | uint8_t persistent; | ||
| 578 | }; | ||
| 579 | |||
| 580 | /** | ||
| 581 | * send a set state command to the device by reading the current items->state | ||
| 582 | * field. items is then filled with the current state. | ||
| 583 | */ | ||
| 584 | static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp, | ||
| 585 | u8 feature_index, | ||
| 586 | struct hidpp_touchpad_fw_items *items) | ||
| 587 | { | ||
| 588 | struct hidpp_report response; | ||
| 589 | int ret; | ||
| 590 | u8 *params = (u8 *)response.fap.params; | ||
| 591 | |||
| 592 | ret = hidpp_send_fap_command_sync(hidpp, feature_index, | ||
| 593 | CMD_TOUCHPAD_FW_ITEMS_SET, &items->state, 1, &response); | ||
| 594 | |||
| 595 | if (ret > 0) { | ||
| 596 | hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", | ||
| 597 | __func__, ret); | ||
| 598 | return -EPROTO; | ||
| 599 | } | ||
| 600 | if (ret) | ||
| 601 | return ret; | ||
| 602 | |||
| 603 | items->presence = params[0]; | ||
| 604 | items->desired_state = params[1]; | ||
| 605 | items->state = params[2]; | ||
| 606 | items->persistent = params[3]; | ||
| 607 | |||
| 608 | return 0; | ||
| 609 | } | ||
| 610 | |||
| 611 | /* -------------------------------------------------------------------------- */ | ||
| 556 | /* 0x6100: TouchPadRawXY */ | 612 | /* 0x6100: TouchPadRawXY */ |
| 557 | /* -------------------------------------------------------------------------- */ | 613 | /* -------------------------------------------------------------------------- */ |
| 558 | 614 | ||
| @@ -1132,6 +1188,75 @@ static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 1132 | return -1; | 1188 | return -1; |
| 1133 | } | 1189 | } |
| 1134 | 1190 | ||
| 1191 | /* ------------------------------------------------------------------------- */ | ||
| 1192 | /* Logitech K400 devices */ | ||
| 1193 | /* ------------------------------------------------------------------------- */ | ||
| 1194 | |||
| 1195 | /* | ||
| 1196 | * The Logitech K400 keyboard has an embedded touchpad which is seen | ||
| 1197 | * as a mouse from the OS point of view. There is a hardware shortcut to disable | ||
| 1198 | * tap-to-click but the setting is not remembered accross reset, annoying some | ||
| 1199 | * users. | ||
| 1200 | * | ||
| 1201 | * We can toggle this feature from the host by using the feature 0x6010: | ||
| 1202 | * Touchpad FW items | ||
| 1203 | */ | ||
| 1204 | |||
| 1205 | struct k400_private_data { | ||
| 1206 | u8 feature_index; | ||
| 1207 | }; | ||
| 1208 | |||
| 1209 | static int k400_disable_tap_to_click(struct hidpp_device *hidpp) | ||
| 1210 | { | ||
| 1211 | struct k400_private_data *k400 = hidpp->private_data; | ||
| 1212 | struct hidpp_touchpad_fw_items items = {}; | ||
| 1213 | int ret; | ||
| 1214 | u8 feature_type; | ||
| 1215 | |||
| 1216 | if (!k400->feature_index) { | ||
| 1217 | ret = hidpp_root_get_feature(hidpp, | ||
| 1218 | HIDPP_PAGE_TOUCHPAD_FW_ITEMS, | ||
| 1219 | &k400->feature_index, &feature_type); | ||
| 1220 | if (ret) | ||
| 1221 | /* means that the device is not powered up */ | ||
| 1222 | return ret; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | ret = hidpp_touchpad_fw_items_set(hidpp, k400->feature_index, &items); | ||
| 1226 | if (ret) | ||
| 1227 | return ret; | ||
| 1228 | |||
| 1229 | return 0; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static int k400_allocate(struct hid_device *hdev) | ||
| 1233 | { | ||
| 1234 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 1235 | struct k400_private_data *k400; | ||
| 1236 | |||
| 1237 | k400 = devm_kzalloc(&hdev->dev, sizeof(struct k400_private_data), | ||
| 1238 | GFP_KERNEL); | ||
| 1239 | if (!k400) | ||
| 1240 | return -ENOMEM; | ||
| 1241 | |||
| 1242 | hidpp->private_data = k400; | ||
| 1243 | |||
| 1244 | return 0; | ||
| 1245 | }; | ||
| 1246 | |||
| 1247 | static int k400_connect(struct hid_device *hdev, bool connected) | ||
| 1248 | { | ||
| 1249 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | ||
| 1250 | |||
| 1251 | if (!connected) | ||
| 1252 | return 0; | ||
| 1253 | |||
| 1254 | if (!disable_tap_to_click) | ||
| 1255 | return 0; | ||
| 1256 | |||
| 1257 | return k400_disable_tap_to_click(hidpp); | ||
| 1258 | } | ||
| 1259 | |||
| 1135 | /* -------------------------------------------------------------------------- */ | 1260 | /* -------------------------------------------------------------------------- */ |
| 1136 | /* Generic HID++ devices */ | 1261 | /* Generic HID++ devices */ |
| 1137 | /* -------------------------------------------------------------------------- */ | 1262 | /* -------------------------------------------------------------------------- */ |
| @@ -1160,13 +1285,15 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, | |||
| 1160 | m560_populate_input(hidpp, input, origin_is_hid_core); | 1285 | m560_populate_input(hidpp, input, origin_is_hid_core); |
| 1161 | } | 1286 | } |
| 1162 | 1287 | ||
| 1163 | static void hidpp_input_configured(struct hid_device *hdev, | 1288 | static int hidpp_input_configured(struct hid_device *hdev, |
| 1164 | struct hid_input *hidinput) | 1289 | struct hid_input *hidinput) |
| 1165 | { | 1290 | { |
| 1166 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); | 1291 | struct hidpp_device *hidpp = hid_get_drvdata(hdev); |
| 1167 | struct input_dev *input = hidinput->input; | 1292 | struct input_dev *input = hidinput->input; |
| 1168 | 1293 | ||
| 1169 | hidpp_populate_input(hidpp, input, true); | 1294 | hidpp_populate_input(hidpp, input, true); |
| 1295 | |||
| 1296 | return 0; | ||
| 1170 | } | 1297 | } |
| 1171 | 1298 | ||
| 1172 | static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data, | 1299 | 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 | if (unlikely(hidpp_report_is_connect_event(report))) { | 1330 | if (unlikely(hidpp_report_is_connect_event(report))) { |
| 1204 | atomic_set(&hidpp->connected, | 1331 | atomic_set(&hidpp->connected, |
| 1205 | !(report->rap.params[0] & (1 << 6))); | 1332 | !(report->rap.params[0] & (1 << 6))); |
| 1206 | if ((hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) && | 1333 | if ((hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) && |
| 1207 | (schedule_work(&hidpp->work) == 0)) | 1334 | (schedule_work(&hidpp->work) == 0)) |
| 1208 | dbg_hid("%s: connect event already queued\n", __func__); | 1335 | dbg_hid("%s: connect event already queued\n", __func__); |
| 1209 | return 1; | 1336 | return 1; |
| @@ -1328,23 +1455,30 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) | |||
| 1328 | ret = m560_send_config_command(hdev, connected); | 1455 | ret = m560_send_config_command(hdev, connected); |
| 1329 | if (ret) | 1456 | if (ret) |
| 1330 | return; | 1457 | return; |
| 1458 | } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) { | ||
| 1459 | ret = k400_connect(hdev, connected); | ||
| 1460 | if (ret) | ||
| 1461 | return; | ||
| 1331 | } | 1462 | } |
| 1332 | 1463 | ||
| 1333 | if (!connected || hidpp->delayed_input) | 1464 | if (!connected || hidpp->delayed_input) |
| 1334 | return; | 1465 | return; |
| 1335 | 1466 | ||
| 1467 | /* the device is already connected, we can ask for its name and | ||
| 1468 | * protocol */ | ||
| 1336 | if (!hidpp->protocol_major) { | 1469 | if (!hidpp->protocol_major) { |
| 1337 | ret = !hidpp_is_connected(hidpp); | 1470 | ret = !hidpp_is_connected(hidpp); |
| 1338 | if (ret) { | 1471 | if (ret) { |
| 1339 | hid_err(hdev, "Can not get the protocol version.\n"); | 1472 | hid_err(hdev, "Can not get the protocol version.\n"); |
| 1340 | return; | 1473 | return; |
| 1341 | } | 1474 | } |
| 1475 | hid_info(hdev, "HID++ %u.%u device connected.\n", | ||
| 1476 | hidpp->protocol_major, hidpp->protocol_minor); | ||
| 1342 | } | 1477 | } |
| 1343 | 1478 | ||
| 1344 | /* the device is already connected, we can ask for its name and | 1479 | if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT)) |
| 1345 | * protocol */ | 1480 | /* if HID created the input nodes for us, we can stop now */ |
| 1346 | hid_info(hdev, "HID++ %u.%u device connected.\n", | 1481 | return; |
| 1347 | hidpp->protocol_major, hidpp->protocol_minor); | ||
| 1348 | 1482 | ||
| 1349 | if (!hidpp->name || hidpp->name == hdev->name) { | 1483 | if (!hidpp->name || hidpp->name == hdev->name) { |
| 1350 | name = hidpp_get_device_name(hidpp); | 1484 | 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 | 1531 | ||
| 1398 | if (disable_raw_mode) { | 1532 | if (disable_raw_mode) { |
| 1399 | hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; | 1533 | hidpp->quirks &= ~HIDPP_QUIRK_CLASS_WTP; |
| 1400 | hidpp->quirks &= ~HIDPP_QUIRK_DELAYED_INIT; | 1534 | hidpp->quirks &= ~HIDPP_QUIRK_CONNECT_EVENTS; |
| 1535 | hidpp->quirks &= ~HIDPP_QUIRK_NO_HIDINPUT; | ||
| 1401 | } | 1536 | } |
| 1402 | 1537 | ||
| 1403 | if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { | 1538 | 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 | ret = m560_allocate(hdev); | 1543 | ret = m560_allocate(hdev); |
| 1409 | if (ret) | 1544 | if (ret) |
| 1410 | goto allocate_fail; | 1545 | goto allocate_fail; |
| 1546 | } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) { | ||
| 1547 | ret = k400_allocate(hdev); | ||
| 1548 | if (ret) | ||
| 1549 | goto allocate_fail; | ||
| 1411 | } | 1550 | } |
| 1412 | 1551 | ||
| 1413 | INIT_WORK(&hidpp->work, delayed_work_cb); | 1552 | 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 | /* Block incoming packets */ | 1587 | /* Block incoming packets */ |
| 1449 | hid_device_io_stop(hdev); | 1588 | hid_device_io_stop(hdev); |
| 1450 | 1589 | ||
| 1451 | if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) | 1590 | if (hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) |
| 1452 | connect_mask &= ~HID_CONNECT_HIDINPUT; | 1591 | connect_mask &= ~HID_CONNECT_HIDINPUT; |
| 1453 | 1592 | ||
| 1454 | ret = hid_hw_start(hdev, connect_mask); | 1593 | 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 | goto hid_hw_start_fail; | 1596 | goto hid_hw_start_fail; |
| 1458 | } | 1597 | } |
| 1459 | 1598 | ||
| 1460 | if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT) { | 1599 | if (hidpp->quirks & HIDPP_QUIRK_CONNECT_EVENTS) { |
| 1461 | /* Allow incoming packets */ | 1600 | /* Allow incoming packets */ |
| 1462 | hid_device_io_start(hdev); | 1601 | hid_device_io_start(hdev); |
| 1463 | 1602 | ||
| @@ -1502,6 +1641,10 @@ static const struct hid_device_id hidpp_devices[] = { | |||
| 1502 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | 1641 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, |
| 1503 | USB_VENDOR_ID_LOGITECH, 0x402d), | 1642 | USB_VENDOR_ID_LOGITECH, 0x402d), |
| 1504 | .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, | 1643 | .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, |
| 1644 | { /* Keyboard logitech K400 */ | ||
| 1645 | HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | ||
| 1646 | USB_VENDOR_ID_LOGITECH, 0x4024), | ||
| 1647 | .driver_data = HIDPP_QUIRK_CONNECT_EVENTS | HIDPP_QUIRK_CLASS_K400 }, | ||
| 1505 | 1648 | ||
| 1506 | { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, | 1649 | { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, |
| 1507 | USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, | 1650 | USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, |
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 29a74c1efcb8..d6fa496d0ca2 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c | |||
| @@ -471,18 +471,22 @@ static int magicmouse_input_mapping(struct hid_device *hdev, | |||
| 471 | return 0; | 471 | return 0; |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | static void magicmouse_input_configured(struct hid_device *hdev, | 474 | static int magicmouse_input_configured(struct hid_device *hdev, |
| 475 | struct hid_input *hi) | 475 | struct hid_input *hi) |
| 476 | 476 | ||
| 477 | { | 477 | { |
| 478 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); | 478 | struct magicmouse_sc *msc = hid_get_drvdata(hdev); |
| 479 | int ret; | ||
| 479 | 480 | ||
| 480 | int ret = magicmouse_setup_input(msc->input, hdev); | 481 | ret = magicmouse_setup_input(msc->input, hdev); |
| 481 | if (ret) { | 482 | if (ret) { |
| 482 | hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); | 483 | hid_err(hdev, "magicmouse setup input failed (%d)\n", ret); |
| 483 | /* clean msc->input to notify probe() of the failure */ | 484 | /* clean msc->input to notify probe() of the failure */ |
| 484 | msc->input = NULL; | 485 | msc->input = NULL; |
| 486 | return ret; | ||
| 485 | } | 487 | } |
| 488 | |||
| 489 | return 0; | ||
| 486 | } | 490 | } |
| 487 | 491 | ||
| 488 | 492 | ||
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 9aa3515090a7..77a2cf3e4afe 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c | |||
| @@ -278,6 +278,8 @@ static const struct hid_device_id ms_devices[] = { | |||
| 278 | .driver_data = MS_DUPLICATE_USAGES }, | 278 | .driver_data = MS_DUPLICATE_USAGES }, |
| 279 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3), | 279 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3), |
| 280 | .driver_data = MS_HIDINPUT }, | 280 | .driver_data = MS_HIDINPUT }, |
| 281 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2), | ||
| 282 | .driver_data = MS_HIDINPUT }, | ||
| 281 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), | 283 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), |
| 282 | .driver_data = MS_HIDINPUT }, | 284 | .driver_data = MS_HIDINPUT }, |
| 283 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), | 285 | { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 426b2f1a3450..3d664d01305e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = { | |||
| 309 | .attrs = sysfs_attrs | 309 | .attrs = sysfs_attrs |
| 310 | }; | 310 | }; |
| 311 | 311 | ||
| 312 | static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) | ||
| 313 | { | ||
| 314 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 315 | int ret, size = hid_report_len(report); | ||
| 316 | u8 *buf; | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Only fetch the feature report if initial reports are not already | ||
| 320 | * been retrieved. Currently this is only done for Windows 8 touch | ||
| 321 | * devices. | ||
| 322 | */ | ||
| 323 | if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)) | ||
| 324 | return; | ||
| 325 | if (td->mtclass.name != MT_CLS_WIN_8) | ||
| 326 | return; | ||
| 327 | |||
| 328 | buf = hid_alloc_report_buf(report, GFP_KERNEL); | ||
| 329 | if (!buf) | ||
| 330 | return; | ||
| 331 | |||
| 332 | ret = hid_hw_raw_request(hdev, report->id, buf, size, | ||
| 333 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | ||
| 334 | if (ret < 0) { | ||
| 335 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", | ||
| 336 | report->id); | ||
| 337 | } else { | ||
| 338 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, | ||
| 339 | size, 0); | ||
| 340 | if (ret) | ||
| 341 | dev_warn(&hdev->dev, "failed to report feature\n"); | ||
| 342 | } | ||
| 343 | |||
| 344 | kfree(buf); | ||
| 345 | } | ||
| 346 | |||
| 312 | static void mt_feature_mapping(struct hid_device *hdev, | 347 | static void mt_feature_mapping(struct hid_device *hdev, |
| 313 | struct hid_field *field, struct hid_usage *usage) | 348 | struct hid_field *field, struct hid_usage *usage) |
| 314 | { | 349 | { |
| @@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 327 | 362 | ||
| 328 | break; | 363 | break; |
| 329 | case HID_DG_CONTACTMAX: | 364 | case HID_DG_CONTACTMAX: |
| 365 | mt_get_feature(hdev, field->report); | ||
| 366 | |||
| 330 | td->maxcontact_report_id = field->report->id; | 367 | td->maxcontact_report_id = field->report->id; |
| 331 | td->maxcontacts = field->value[0]; | 368 | td->maxcontacts = field->value[0]; |
| 332 | if (!td->maxcontacts && | 369 | if (!td->maxcontacts && |
| @@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 343 | break; | 380 | break; |
| 344 | } | 381 | } |
| 345 | 382 | ||
| 383 | mt_get_feature(hdev, field->report); | ||
| 346 | if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD) | 384 | if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD) |
| 347 | td->is_buttonpad = true; | 385 | td->is_buttonpad = true; |
| 348 | 386 | ||
| @@ -725,12 +763,13 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | |||
| 725 | mt_sync_frame(td, report->field[0]->hidinput->input); | 763 | mt_sync_frame(td, report->field[0]->hidinput->input); |
| 726 | } | 764 | } |
| 727 | 765 | ||
| 728 | static void mt_touch_input_configured(struct hid_device *hdev, | 766 | static int mt_touch_input_configured(struct hid_device *hdev, |
| 729 | struct hid_input *hi) | 767 | struct hid_input *hi) |
| 730 | { | 768 | { |
| 731 | struct mt_device *td = hid_get_drvdata(hdev); | 769 | struct mt_device *td = hid_get_drvdata(hdev); |
| 732 | struct mt_class *cls = &td->mtclass; | 770 | struct mt_class *cls = &td->mtclass; |
| 733 | struct input_dev *input = hi->input; | 771 | struct input_dev *input = hi->input; |
| 772 | int ret; | ||
| 734 | 773 | ||
| 735 | if (!td->maxcontacts) | 774 | if (!td->maxcontacts) |
| 736 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | 775 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; |
| @@ -752,9 +791,12 @@ static void mt_touch_input_configured(struct hid_device *hdev, | |||
| 752 | if (td->is_buttonpad) | 791 | if (td->is_buttonpad) |
| 753 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); | 792 | __set_bit(INPUT_PROP_BUTTONPAD, input->propbit); |
| 754 | 793 | ||
| 755 | input_mt_init_slots(input, td->maxcontacts, td->mt_flags); | 794 | ret = input_mt_init_slots(input, td->maxcontacts, td->mt_flags); |
| 795 | if (ret) | ||
| 796 | return ret; | ||
| 756 | 797 | ||
| 757 | td->mt_flags = 0; | 798 | td->mt_flags = 0; |
| 799 | return 0; | ||
| 758 | } | 800 | } |
| 759 | 801 | ||
| 760 | static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 802 | 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 | cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; | 972 | cls->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE; |
| 931 | } | 973 | } |
| 932 | 974 | ||
| 933 | static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | 975 | static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) |
| 934 | { | 976 | { |
| 935 | struct mt_device *td = hid_get_drvdata(hdev); | 977 | struct mt_device *td = hid_get_drvdata(hdev); |
| 936 | char *name; | 978 | char *name; |
| 937 | const char *suffix = NULL; | 979 | const char *suffix = NULL; |
| 938 | struct hid_field *field = hi->report->field[0]; | 980 | struct hid_field *field = hi->report->field[0]; |
| 981 | int ret; | ||
| 939 | 982 | ||
| 940 | if (hi->report->id == td->mt_report_id) | 983 | if (hi->report->id == td->mt_report_id) { |
| 941 | mt_touch_input_configured(hdev, hi); | 984 | ret = mt_touch_input_configured(hdev, hi); |
| 985 | if (ret) | ||
| 986 | return ret; | ||
| 987 | } | ||
| 942 | 988 | ||
| 943 | /* | 989 | /* |
| 944 | * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" | 990 | * 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 | case HID_DG_TOUCHSCREEN: | 1014 | case HID_DG_TOUCHSCREEN: |
| 969 | /* we do not set suffix = "Touchscreen" */ | 1015 | /* we do not set suffix = "Touchscreen" */ |
| 970 | break; | 1016 | break; |
| 1017 | case HID_DG_TOUCHPAD: | ||
| 1018 | suffix = "Touchpad"; | ||
| 1019 | break; | ||
| 971 | case HID_GD_SYSTEM_CONTROL: | 1020 | case HID_GD_SYSTEM_CONTROL: |
| 972 | suffix = "System Control"; | 1021 | suffix = "System Control"; |
| 973 | break; | 1022 | break; |
| @@ -989,6 +1038,8 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 989 | hi->input->name = name; | 1038 | hi->input->name = name; |
| 990 | } | 1039 | } |
| 991 | } | 1040 | } |
| 1041 | |||
| 1042 | return 0; | ||
| 992 | } | 1043 | } |
| 993 | 1044 | ||
| 994 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | 1045 | 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 | * reports. Fortunately, the Win8 spec says that all touches | 1077 | * reports. Fortunately, the Win8 spec says that all touches |
| 1027 | * should be sent during each report, making the initialization | 1078 | * should be sent during each report, making the initialization |
| 1028 | * of input reports unnecessary. | 1079 | * of input reports unnecessary. |
| 1080 | * | ||
| 1081 | * In addition some touchpads do not behave well if we read | ||
| 1082 | * all feature reports from them. Instead we prevent | ||
| 1083 | * initial report fetching and then selectively fetch each | ||
| 1084 | * report we are interested in. | ||
| 1029 | */ | 1085 | */ |
| 1030 | hdev->quirks |= HID_QUIRK_NO_INIT_INPUT_REPORTS; | 1086 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; |
| 1031 | 1087 | ||
| 1032 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); | 1088 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); |
| 1033 | if (!td) { | 1089 | if (!td) { |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 600f2075512f..756d1ef9bd99 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
| @@ -859,14 +859,14 @@ not_claimed_input: | |||
| 859 | return 1; | 859 | return 1; |
| 860 | } | 860 | } |
| 861 | 861 | ||
| 862 | static void ntrig_input_configured(struct hid_device *hid, | 862 | static int ntrig_input_configured(struct hid_device *hid, |
| 863 | struct hid_input *hidinput) | 863 | struct hid_input *hidinput) |
| 864 | 864 | ||
| 865 | { | 865 | { |
| 866 | struct input_dev *input = hidinput->input; | 866 | struct input_dev *input = hidinput->input; |
| 867 | 867 | ||
| 868 | if (hidinput->report->maxfield < 1) | 868 | if (hidinput->report->maxfield < 1) |
| 869 | return; | 869 | return 0; |
| 870 | 870 | ||
| 871 | switch (hidinput->report->field[0]->application) { | 871 | switch (hidinput->report->field[0]->application) { |
| 872 | case HID_DG_PEN: | 872 | case HID_DG_PEN: |
| @@ -890,6 +890,8 @@ static void ntrig_input_configured(struct hid_device *hid, | |||
| 890 | "N-Trig MultiTouch"; | 890 | "N-Trig MultiTouch"; |
| 891 | break; | 891 | break; |
| 892 | } | 892 | } |
| 893 | |||
| 894 | return 0; | ||
| 893 | } | 895 | } |
| 894 | 896 | ||
| 895 | static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | 897 | static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) |
diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index e3e98ccf137b..3a207c0ac0e3 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c | |||
| @@ -427,7 +427,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) | |||
| 427 | pm->midi_octave = 2; | 427 | pm->midi_octave = 2; |
| 428 | dbg_hid("pcmidi mode: %d octave: %d\n", | 428 | dbg_hid("pcmidi mode: %d octave: %d\n", |
| 429 | pm->midi_mode, pm->midi_octave); | 429 | pm->midi_mode, pm->midi_octave); |
| 430 | continue; | 430 | continue; |
| 431 | } else | 431 | } else |
| 432 | key = KEY_MESSENGER; | 432 | key = KEY_MESSENGER; |
| 433 | break; | 433 | break; |
| @@ -695,7 +695,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) | |||
| 695 | if (err < 0) { | 695 | if (err < 0) { |
| 696 | pk_error("failed to register pc-midi sound card: error %d\n", | 696 | pk_error("failed to register pc-midi sound card: error %d\n", |
| 697 | err); | 697 | err); |
| 698 | goto fail_register; | 698 | goto fail_register; |
| 699 | } | 699 | } |
| 700 | 700 | ||
| 701 | dbg_hid("pcmidi_snd_initialise finished ok\n"); | 701 | dbg_hid("pcmidi_snd_initialise finished ok\n"); |
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 2c148129beb2..67cd059a8f46 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c | |||
| @@ -1173,7 +1173,7 @@ static int rmi_populate(struct hid_device *hdev) | |||
| 1173 | return 0; | 1173 | return 0; |
| 1174 | } | 1174 | } |
| 1175 | 1175 | ||
| 1176 | static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) | 1176 | static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) |
| 1177 | { | 1177 | { |
| 1178 | struct rmi_data *data = hid_get_drvdata(hdev); | 1178 | struct rmi_data *data = hid_get_drvdata(hdev); |
| 1179 | struct input_dev *input = hi->input; | 1179 | struct input_dev *input = hi->input; |
| @@ -1185,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 1185 | hid_dbg(hdev, "Opening low level driver\n"); | 1185 | hid_dbg(hdev, "Opening low level driver\n"); |
| 1186 | ret = hid_hw_open(hdev); | 1186 | ret = hid_hw_open(hdev); |
| 1187 | if (ret) | 1187 | if (ret) |
| 1188 | return; | 1188 | return ret; |
| 1189 | 1189 | ||
| 1190 | if (!(data->device_flags & RMI_DEVICE)) | 1190 | if (!(data->device_flags & RMI_DEVICE)) |
| 1191 | return; | 1191 | return 0; |
| 1192 | 1192 | ||
| 1193 | /* Allow incoming hid reports */ | 1193 | /* Allow incoming hid reports */ |
| 1194 | hid_device_io_start(hdev); | 1194 | hid_device_io_start(hdev); |
| @@ -1228,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 1228 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); | 1228 | input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0); |
| 1229 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); | 1229 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0); |
| 1230 | 1230 | ||
| 1231 | input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER); | 1231 | ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER); |
| 1232 | if (ret < 0) | ||
| 1233 | goto exit; | ||
| 1232 | 1234 | ||
| 1233 | if (data->button_count) { | 1235 | if (data->button_count) { |
| 1234 | __set_bit(EV_KEY, input->evbit); | 1236 | __set_bit(EV_KEY, input->evbit); |
| @@ -1244,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 1244 | exit: | 1246 | exit: |
| 1245 | hid_device_io_stop(hdev); | 1247 | hid_device_io_stop(hdev); |
| 1246 | hid_hw_close(hdev); | 1248 | hid_hw_close(hdev); |
| 1249 | return ret; | ||
| 1247 | } | 1250 | } |
| 1248 | 1251 | ||
| 1249 | static int rmi_input_mapping(struct hid_device *hdev, | 1252 | static int rmi_input_mapping(struct hid_device *hdev, |
diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c index a014f21275d8..2f84b26f1167 100644 --- a/drivers/hid/hid-saitek.c +++ b/drivers/hid/hid-saitek.c | |||
| @@ -177,6 +177,8 @@ static int saitek_event(struct hid_device *hdev, struct hid_field *field, | |||
| 177 | static const struct hid_device_id saitek_devices[] = { | 177 | static const struct hid_device_id saitek_devices[] = { |
| 178 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000), | 178 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000), |
| 179 | .driver_data = SAITEK_FIX_PS1000 }, | 179 | .driver_data = SAITEK_FIX_PS1000 }, |
| 180 | { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5), | ||
| 181 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, | ||
| 180 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD), | 182 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD), |
| 181 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, | 183 | .driver_data = SAITEK_RELEASE_MODE_RAT7 }, |
| 182 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), | 184 | { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), |
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 90116ee1624e..92870cdb52d9 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c | |||
| @@ -660,8 +660,8 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 660 | GFP_KERNEL); | 660 | GFP_KERNEL); |
| 661 | if (sd->hid_sensor_hub_client_devs == NULL) { | 661 | if (sd->hid_sensor_hub_client_devs == NULL) { |
| 662 | hid_err(hdev, "Failed to allocate memory for mfd cells\n"); | 662 | hid_err(hdev, "Failed to allocate memory for mfd cells\n"); |
| 663 | ret = -ENOMEM; | 663 | ret = -ENOMEM; |
| 664 | goto err_stop_hw; | 664 | goto err_stop_hw; |
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | for (i = 0; i < hdev->maxcollection; ++i) { | 667 | for (i = 0; i < hdev->maxcollection; ++i) { |
| @@ -698,8 +698,8 @@ static int sensor_hub_probe(struct hid_device *hdev, | |||
| 698 | collection->usage); | 698 | collection->usage); |
| 699 | if (name == NULL) { | 699 | if (name == NULL) { |
| 700 | hid_err(hdev, "Failed MFD device name\n"); | 700 | hid_err(hdev, "Failed MFD device name\n"); |
| 701 | ret = -ENOMEM; | 701 | ret = -ENOMEM; |
| 702 | goto err_stop_hw; | 702 | goto err_stop_hw; |
| 703 | } | 703 | } |
| 704 | sd->hid_sensor_hub_client_devs[ | 704 | sd->hid_sensor_hub_client_devs[ |
| 705 | sd->hid_sensor_client_cnt].name = name; | 705 | sd->hid_sensor_client_cnt].name = name; |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 661f94f8ab8b..774cd2210566 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -1360,20 +1360,27 @@ static int sony_register_touchpad(struct hid_input *hi, int touch_count, | |||
| 1360 | return 0; | 1360 | return 0; |
| 1361 | } | 1361 | } |
| 1362 | 1362 | ||
| 1363 | static void sony_input_configured(struct hid_device *hdev, | 1363 | static int sony_input_configured(struct hid_device *hdev, |
| 1364 | struct hid_input *hidinput) | 1364 | struct hid_input *hidinput) |
| 1365 | { | 1365 | { |
| 1366 | struct sony_sc *sc = hid_get_drvdata(hdev); | 1366 | struct sony_sc *sc = hid_get_drvdata(hdev); |
| 1367 | int ret; | ||
| 1367 | 1368 | ||
| 1368 | /* | 1369 | /* |
| 1369 | * The Dualshock 4 touchpad supports 2 touches and has a | 1370 | * The Dualshock 4 touchpad supports 2 touches and has a |
| 1370 | * resolution of 1920x942 (44.86 dots/mm). | 1371 | * resolution of 1920x942 (44.86 dots/mm). |
| 1371 | */ | 1372 | */ |
| 1372 | if (sc->quirks & DUALSHOCK4_CONTROLLER) { | 1373 | if (sc->quirks & DUALSHOCK4_CONTROLLER) { |
| 1373 | if (sony_register_touchpad(hidinput, 2, 1920, 942) != 0) | 1374 | ret = sony_register_touchpad(hidinput, 2, 1920, 942); |
| 1375 | if (ret) { | ||
| 1374 | hid_err(sc->hdev, | 1376 | hid_err(sc->hdev, |
| 1375 | "Unable to initialize multi-touch slots\n"); | 1377 | "Unable to initialize multi-touch slots: %d\n", |
| 1378 | ret); | ||
| 1379 | return ret; | ||
| 1380 | } | ||
| 1376 | } | 1381 | } |
| 1382 | |||
| 1383 | return 0; | ||
| 1377 | } | 1384 | } |
| 1378 | 1385 | ||
| 1379 | /* | 1386 | /* |
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index b905d501e752..85ac43517e3f 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c | |||
| @@ -731,7 +731,7 @@ static int uclogic_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 731 | return 0; | 731 | return 0; |
| 732 | } | 732 | } |
| 733 | 733 | ||
| 734 | static void uclogic_input_configured(struct hid_device *hdev, | 734 | static int uclogic_input_configured(struct hid_device *hdev, |
| 735 | struct hid_input *hi) | 735 | struct hid_input *hi) |
| 736 | { | 736 | { |
| 737 | char *name; | 737 | char *name; |
| @@ -741,7 +741,7 @@ static void uclogic_input_configured(struct hid_device *hdev, | |||
| 741 | 741 | ||
| 742 | /* no report associated (HID_QUIRK_MULTI_INPUT not set) */ | 742 | /* no report associated (HID_QUIRK_MULTI_INPUT not set) */ |
| 743 | if (!hi->report) | 743 | if (!hi->report) |
| 744 | return; | 744 | return 0; |
| 745 | 745 | ||
| 746 | field = hi->report->field[0]; | 746 | field = hi->report->field[0]; |
| 747 | 747 | ||
| @@ -774,6 +774,8 @@ static void uclogic_input_configured(struct hid_device *hdev, | |||
| 774 | hi->input->name = name; | 774 | hi->input->name = name; |
| 775 | } | 775 | } |
| 776 | } | 776 | } |
| 777 | |||
| 778 | return 0; | ||
| 777 | } | 779 | } |
| 778 | 780 | ||
| 779 | /** | 781 | /** |
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 2871f3c81a4c..10bd8e6e4c9c 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
| @@ -1028,6 +1028,7 @@ static int i2c_hid_probe(struct i2c_client *client, | |||
| 1028 | 1028 | ||
| 1029 | snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", | 1029 | snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", |
| 1030 | client->name, hid->vendor, hid->product); | 1030 | client->name, hid->vendor, hid->product); |
| 1031 | strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); | ||
| 1031 | 1032 | ||
| 1032 | ret = hid_add_device(hid); | 1033 | ret = hid_add_device(hid); |
| 1033 | if (ret) { | 1034 | if (ret) { |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 26d2f83308c8..94bb137abe32 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
| @@ -92,6 +92,7 @@ static const struct hid_blacklist { | |||
| 92 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, | 92 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, |
| 93 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, | 93 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS }, |
| 94 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS }, | 94 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS }, |
| 95 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS }, | ||
| 95 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS }, | 96 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS }, |
| 96 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, | 97 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, |
| 97 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, | 98 | { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, |
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 9a4912c1828d..e06af5b9f59e 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c | |||
| @@ -211,7 +211,7 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 211 | * Bamboo models do not support HID_DG_CONTACTMAX. | 211 | * Bamboo models do not support HID_DG_CONTACTMAX. |
| 212 | * And, Bamboo Pen only descriptor contains touch. | 212 | * And, Bamboo Pen only descriptor contains touch. |
| 213 | */ | 213 | */ |
| 214 | if (features->type != BAMBOO_PT) { | 214 | if (features->type > BAMBOO_PT) { |
| 215 | /* ISDv4 touch devices at least supports one touch point */ | 215 | /* ISDv4 touch devices at least supports one touch point */ |
| 216 | if (finger && !features->touch_max) | 216 | if (finger && !features->touch_max) |
| 217 | features->touch_max = 1; | 217 | features->touch_max = 1; |
| @@ -222,7 +222,8 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 222 | features->x_max = field->logical_maximum; | 222 | features->x_max = field->logical_maximum; |
| 223 | if (finger) { | 223 | if (finger) { |
| 224 | features->x_phy = field->physical_maximum; | 224 | features->x_phy = field->physical_maximum; |
| 225 | if (features->type != BAMBOO_PT) { | 225 | if ((features->type != BAMBOO_PT) && |
| 226 | (features->type != BAMBOO_TOUCH)) { | ||
| 226 | features->unit = field->unit; | 227 | features->unit = field->unit; |
| 227 | features->unitExpo = field->unit_exponent; | 228 | features->unitExpo = field->unit_exponent; |
| 228 | } | 229 | } |
| @@ -232,7 +233,8 @@ static void wacom_usage_mapping(struct hid_device *hdev, | |||
| 232 | features->y_max = field->logical_maximum; | 233 | features->y_max = field->logical_maximum; |
| 233 | if (finger) { | 234 | if (finger) { |
| 234 | features->y_phy = field->physical_maximum; | 235 | features->y_phy = field->physical_maximum; |
| 235 | if (features->type != BAMBOO_PT) { | 236 | if ((features->type != BAMBOO_PT) && |
| 237 | (features->type != BAMBOO_TOUCH)) { | ||
| 236 | features->unit = field->unit; | 238 | features->unit = field->unit; |
| 237 | features->unitExpo = field->unit_exponent; | 239 | features->unitExpo = field->unit_exponent; |
| 238 | } | 240 | } |
| @@ -420,7 +422,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, | |||
| 420 | /* MT Tablet PC touch */ | 422 | /* MT Tablet PC touch */ |
| 421 | return wacom_set_device_mode(hdev, 3, 4, 4); | 423 | return wacom_set_device_mode(hdev, 3, 4, 4); |
| 422 | } | 424 | } |
| 423 | else if (features->type == WACOM_24HDT || features->type == CINTIQ_HYBRID) { | 425 | else if (features->type == WACOM_24HDT) { |
| 424 | return wacom_set_device_mode(hdev, 18, 3, 2); | 426 | return wacom_set_device_mode(hdev, 18, 3, 2); |
| 425 | } | 427 | } |
| 426 | else if (features->type == WACOM_27QHDT) { | 428 | else if (features->type == WACOM_27QHDT) { |
| @@ -430,7 +432,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, | |||
| 430 | return wacom_set_device_mode(hdev, 2, 2, 2); | 432 | return wacom_set_device_mode(hdev, 2, 2, 2); |
| 431 | } | 433 | } |
| 432 | } else if (features->device_type & WACOM_DEVICETYPE_PEN) { | 434 | } else if (features->device_type & WACOM_DEVICETYPE_PEN) { |
| 433 | if (features->type <= BAMBOO_PT && features->type != WIRELESS) { | 435 | if (features->type <= BAMBOO_PT) { |
| 434 | return wacom_set_device_mode(hdev, 2, 2, 2); | 436 | return wacom_set_device_mode(hdev, 2, 2, 2); |
| 435 | } | 437 | } |
| 436 | } | 438 | } |
| @@ -1547,15 +1549,16 @@ static void wacom_wireless_work(struct work_struct *work) | |||
| 1547 | wacom_wac1->features = | 1549 | wacom_wac1->features = |
| 1548 | *((struct wacom_features *)id->driver_data); | 1550 | *((struct wacom_features *)id->driver_data); |
| 1549 | wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN; | 1551 | wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN; |
| 1550 | if (wacom_wac1->features.type != INTUOSHT && | ||
| 1551 | wacom_wac1->features.type != BAMBOO_PT) | ||
| 1552 | wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1553 | wacom_set_default_phy(&wacom_wac1->features); | 1552 | wacom_set_default_phy(&wacom_wac1->features); |
| 1554 | wacom_calculate_res(&wacom_wac1->features); | 1553 | wacom_calculate_res(&wacom_wac1->features); |
| 1555 | snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen", | 1554 | snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen", |
| 1556 | wacom_wac1->features.name); | 1555 | wacom_wac1->features.name); |
| 1557 | snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", | 1556 | if (wacom_wac1->features.type < BAMBOO_PEN || |
| 1558 | wacom_wac1->features.name); | 1557 | wacom_wac1->features.type > BAMBOO_PT) { |
| 1558 | snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", | ||
| 1559 | wacom_wac1->features.name); | ||
| 1560 | wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD; | ||
| 1561 | } | ||
| 1559 | wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; | 1562 | wacom_wac1->shared->touch_max = wacom_wac1->features.touch_max; |
| 1560 | wacom_wac1->shared->type = wacom_wac1->features.type; | 1563 | wacom_wac1->shared->type = wacom_wac1->features.type; |
| 1561 | wacom_wac1->pid = wacom_wac->pid; | 1564 | wacom_wac1->pid = wacom_wac->pid; |
| @@ -1566,7 +1569,8 @@ static void wacom_wireless_work(struct work_struct *work) | |||
| 1566 | 1569 | ||
| 1567 | /* Touch interface */ | 1570 | /* Touch interface */ |
| 1568 | if (wacom_wac1->features.touch_max || | 1571 | if (wacom_wac1->features.touch_max || |
| 1569 | wacom_wac1->features.type == INTUOSHT) { | 1572 | (wacom_wac1->features.type >= INTUOSHT && |
| 1573 | wacom_wac1->features.type <= BAMBOO_PT)) { | ||
| 1570 | wacom_wac2->features = | 1574 | wacom_wac2->features = |
| 1571 | *((struct wacom_features *)id->driver_data); | 1575 | *((struct wacom_features *)id->driver_data); |
| 1572 | wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; | 1576 | wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; |
| @@ -1575,20 +1579,22 @@ static void wacom_wireless_work(struct work_struct *work) | |||
| 1575 | wacom_calculate_res(&wacom_wac2->features); | 1579 | wacom_calculate_res(&wacom_wac2->features); |
| 1576 | snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX, | 1580 | snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX, |
| 1577 | "%s (WL) Finger",wacom_wac2->features.name); | 1581 | "%s (WL) Finger",wacom_wac2->features.name); |
| 1578 | snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, | ||
| 1579 | "%s (WL) Pad",wacom_wac2->features.name); | ||
| 1580 | if (wacom_wac1->features.touch_max) | 1582 | if (wacom_wac1->features.touch_max) |
| 1581 | wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; | 1583 | wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; |
| 1582 | if (wacom_wac1->features.type == INTUOSHT || | 1584 | if (wacom_wac1->features.type >= INTUOSHT && |
| 1583 | wacom_wac1->features.type == BAMBOO_PT) | 1585 | wacom_wac1->features.type <= BAMBOO_PT) { |
| 1586 | snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, | ||
| 1587 | "%s (WL) Pad",wacom_wac2->features.name); | ||
| 1584 | wacom_wac2->features.device_type |= WACOM_DEVICETYPE_PAD; | 1588 | wacom_wac2->features.device_type |= WACOM_DEVICETYPE_PAD; |
| 1589 | } | ||
| 1585 | wacom_wac2->pid = wacom_wac->pid; | 1590 | wacom_wac2->pid = wacom_wac->pid; |
| 1586 | error = wacom_allocate_inputs(wacom2) || | 1591 | error = wacom_allocate_inputs(wacom2) || |
| 1587 | wacom_register_inputs(wacom2); | 1592 | wacom_register_inputs(wacom2); |
| 1588 | if (error) | 1593 | if (error) |
| 1589 | goto fail; | 1594 | goto fail; |
| 1590 | 1595 | ||
| 1591 | if (wacom_wac1->features.type == INTUOSHT && | 1596 | if ((wacom_wac1->features.type == INTUOSHT || |
| 1597 | wacom_wac1->features.type == INTUOSHT2) && | ||
| 1592 | wacom_wac1->features.touch_max) | 1598 | wacom_wac1->features.touch_max) |
| 1593 | wacom_wac->shared->touch_input = wacom_wac2->touch_input; | 1599 | wacom_wac->shared->touch_input = wacom_wac2->touch_input; |
| 1594 | } | 1600 | } |
| @@ -1812,11 +1818,27 @@ static int wacom_probe(struct hid_device *hdev, | |||
| 1812 | /* Note that if query fails it is not a hard failure */ | 1818 | /* Note that if query fails it is not a hard failure */ |
| 1813 | wacom_query_tablet_data(hdev, features); | 1819 | wacom_query_tablet_data(hdev, features); |
| 1814 | 1820 | ||
| 1821 | /* touch only Bamboo doesn't support pen */ | ||
| 1822 | if ((features->type == BAMBOO_TOUCH) && | ||
| 1823 | (features->device_type & WACOM_DEVICETYPE_PEN)) { | ||
| 1824 | error = -ENODEV; | ||
| 1825 | goto fail_hw_start; | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | /* pen only Bamboo neither support touch nor pad */ | ||
| 1829 | if ((features->type == BAMBOO_PEN) && | ||
| 1830 | ((features->device_type & WACOM_DEVICETYPE_TOUCH) || | ||
| 1831 | (features->device_type & WACOM_DEVICETYPE_PAD))) { | ||
| 1832 | error = -ENODEV; | ||
| 1833 | goto fail_hw_start; | ||
| 1834 | } | ||
| 1835 | |||
| 1815 | if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) | 1836 | if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) |
| 1816 | error = hid_hw_open(hdev); | 1837 | error = hid_hw_open(hdev); |
| 1817 | 1838 | ||
| 1818 | if (wacom_wac->features.type == INTUOSHT && | 1839 | if ((wacom_wac->features.type == INTUOSHT || |
| 1819 | wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { | 1840 | wacom_wac->features.type == INTUOSHT2) && |
| 1841 | (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) { | ||
| 1820 | wacom_wac->shared->touch_input = wacom_wac->touch_input; | 1842 | wacom_wac->shared->touch_input = wacom_wac->touch_input; |
| 1821 | } | 1843 | } |
| 1822 | 1844 | ||
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index cba008ac9cff..8b29949507d1 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c | |||
| @@ -765,13 +765,15 @@ static void wacom_intuos_general(struct wacom_wac *wacom) | |||
| 765 | /* general pen packet */ | 765 | /* general pen packet */ |
| 766 | if ((data[1] & 0xb8) == 0xa0) { | 766 | if ((data[1] & 0xb8) == 0xa0) { |
| 767 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 767 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
| 768 | if (features->type >= INTUOS4S && features->type <= CINTIQ_HYBRID) { | 768 | if (features->pressure_max == 2047) { |
| 769 | t = (t << 1) | (data[1] & 1); | 769 | t = (t << 1) | (data[1] & 1); |
| 770 | } | 770 | } |
| 771 | input_report_abs(input, ABS_PRESSURE, t); | 771 | input_report_abs(input, ABS_PRESSURE, t); |
| 772 | input_report_abs(input, ABS_TILT_X, | 772 | if (features->type != INTUOSHT2) { |
| 773 | input_report_abs(input, ABS_TILT_X, | ||
| 773 | (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); | 774 | (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); |
| 774 | input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); | 775 | input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); |
| 776 | } | ||
| 775 | input_report_key(input, BTN_STYLUS, data[1] & 2); | 777 | input_report_key(input, BTN_STYLUS, data[1] & 2); |
| 776 | input_report_key(input, BTN_STYLUS2, data[1] & 4); | 778 | input_report_key(input, BTN_STYLUS2, data[1] & 4); |
| 777 | input_report_key(input, BTN_TOUCH, t > 10); | 779 | input_report_key(input, BTN_TOUCH, t > 10); |
| @@ -799,6 +801,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 799 | data[0] != WACOM_REPORT_INTUOSREAD && | 801 | data[0] != WACOM_REPORT_INTUOSREAD && |
| 800 | data[0] != WACOM_REPORT_INTUOSWRITE && | 802 | data[0] != WACOM_REPORT_INTUOSWRITE && |
| 801 | data[0] != WACOM_REPORT_INTUOSPAD && | 803 | data[0] != WACOM_REPORT_INTUOSPAD && |
| 804 | data[0] != WACOM_REPORT_INTUOS_PEN && | ||
| 802 | data[0] != WACOM_REPORT_CINTIQ && | 805 | data[0] != WACOM_REPORT_CINTIQ && |
| 803 | data[0] != WACOM_REPORT_CINTIQPAD && | 806 | data[0] != WACOM_REPORT_CINTIQPAD && |
| 804 | data[0] != WACOM_REPORT_INTUOS5PAD) { | 807 | data[0] != WACOM_REPORT_INTUOS5PAD) { |
| @@ -948,6 +951,27 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 948 | } else { | 951 | } else { |
| 949 | input_report_abs(input, ABS_MISC, 0); | 952 | input_report_abs(input, ABS_MISC, 0); |
| 950 | } | 953 | } |
| 954 | |||
| 955 | } else if (features->type == CINTIQ_COMPANION_2) { | ||
| 956 | input_report_key(input, BTN_1, (data[1] & 0x02)); | ||
| 957 | input_report_key(input, BTN_2, (data[2] & 0x01)); | ||
| 958 | input_report_key(input, BTN_3, (data[2] & 0x02)); | ||
| 959 | input_report_key(input, BTN_4, (data[2] & 0x04)); | ||
| 960 | input_report_key(input, BTN_5, (data[2] & 0x08)); | ||
| 961 | input_report_key(input, BTN_6, (data[1] & 0x04)); | ||
| 962 | |||
| 963 | input_report_key(input, BTN_7, (data[2] & 0x10)); /* Right */ | ||
| 964 | input_report_key(input, BTN_8, (data[2] & 0x20)); /* Up */ | ||
| 965 | input_report_key(input, BTN_9, (data[2] & 0x40)); /* Left */ | ||
| 966 | input_report_key(input, BTN_A, (data[2] & 0x80)); /* Down */ | ||
| 967 | input_report_key(input, BTN_0, (data[1] & 0x01)); /* Center */ | ||
| 968 | |||
| 969 | if (data[2] | (data[1] & 0x07)) { | ||
| 970 | input_report_abs(input, ABS_MISC, PAD_DEVICE_ID); | ||
| 971 | } else { | ||
| 972 | input_report_abs(input, ABS_MISC, 0); | ||
| 973 | } | ||
| 974 | |||
| 951 | } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { | 975 | } else if (features->type >= INTUOS5S && features->type <= INTUOSPL) { |
| 952 | int i; | 976 | int i; |
| 953 | 977 | ||
| @@ -1922,7 +1946,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) | |||
| 1922 | int y = (data[3] << 4) | (data[4] & 0x0f); | 1946 | int y = (data[3] << 4) | (data[4] & 0x0f); |
| 1923 | int width, height; | 1947 | int width, height; |
| 1924 | 1948 | ||
| 1925 | if (features->type >= INTUOSPS && features->type <= INTUOSHT) { | 1949 | if (features->type >= INTUOSPS && features->type <= INTUOSHT2) { |
| 1926 | width = data[5] * 100; | 1950 | width = data[5] * 100; |
| 1927 | height = data[6] * 100; | 1951 | height = data[6] * 100; |
| 1928 | } else { | 1952 | } else { |
| @@ -1950,7 +1974,7 @@ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) | |||
| 1950 | struct input_dev *input = wacom->pad_input; | 1974 | struct input_dev *input = wacom->pad_input; |
| 1951 | struct wacom_features *features = &wacom->features; | 1975 | struct wacom_features *features = &wacom->features; |
| 1952 | 1976 | ||
| 1953 | if (features->type == INTUOSHT) { | 1977 | if (features->type == INTUOSHT || features->type == INTUOSHT2) { |
| 1954 | input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); | 1978 | input_report_key(input, BTN_LEFT, (data[1] & 0x02) != 0); |
| 1955 | input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0); | 1979 | input_report_key(input, BTN_BACK, (data[1] & 0x08) != 0); |
| 1956 | } else { | 1980 | } else { |
| @@ -1965,7 +1989,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) | |||
| 1965 | { | 1989 | { |
| 1966 | unsigned char *data = wacom->data; | 1990 | unsigned char *data = wacom->data; |
| 1967 | int count = data[1] & 0x07; | 1991 | int count = data[1] & 0x07; |
| 1968 | int i; | 1992 | int touch_changed = 0, i; |
| 1969 | 1993 | ||
| 1970 | if (data[0] != 0x02) | 1994 | if (data[0] != 0x02) |
| 1971 | return 0; | 1995 | return 0; |
| @@ -1975,15 +1999,16 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) | |||
| 1975 | int offset = (8 * i) + 2; | 1999 | int offset = (8 * i) + 2; |
| 1976 | int msg_id = data[offset]; | 2000 | int msg_id = data[offset]; |
| 1977 | 2001 | ||
| 1978 | if (msg_id >= 2 && msg_id <= 17) | 2002 | if (msg_id >= 2 && msg_id <= 17) { |
| 1979 | wacom_bpt3_touch_msg(wacom, data + offset); | 2003 | wacom_bpt3_touch_msg(wacom, data + offset); |
| 1980 | else if (msg_id == 128) | 2004 | touch_changed++; |
| 2005 | } else if (msg_id == 128) | ||
| 1981 | wacom_bpt3_button_msg(wacom, data + offset); | 2006 | wacom_bpt3_button_msg(wacom, data + offset); |
| 1982 | 2007 | ||
| 1983 | } | 2008 | } |
| 1984 | 2009 | ||
| 1985 | /* only update the touch if we actually have a touchpad */ | 2010 | /* only update touch if we actually have a touchpad and touch data changed */ |
| 1986 | if (wacom->touch_registered) { | 2011 | if (wacom->touch_registered && touch_changed) { |
| 1987 | input_mt_sync_frame(wacom->touch_input); | 2012 | input_mt_sync_frame(wacom->touch_input); |
| 1988 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); | 2013 | wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); |
| 1989 | } | 2014 | } |
| @@ -2064,7 +2089,12 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) | |||
| 2064 | 2089 | ||
| 2065 | static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) | 2090 | static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len) |
| 2066 | { | 2091 | { |
| 2067 | if (len == WACOM_PKGLEN_BBTOUCH) | 2092 | struct wacom_features *features = &wacom->features; |
| 2093 | |||
| 2094 | if ((features->type == INTUOSHT2) && | ||
| 2095 | (features->device_type & WACOM_DEVICETYPE_PEN)) | ||
| 2096 | return wacom_intuos_irq(wacom); | ||
| 2097 | else if (len == WACOM_PKGLEN_BBTOUCH) | ||
| 2068 | return wacom_bpt_touch(wacom); | 2098 | return wacom_bpt_touch(wacom); |
| 2069 | else if (len == WACOM_PKGLEN_BBTOUCH3) | 2099 | else if (len == WACOM_PKGLEN_BBTOUCH3) |
| 2070 | return wacom_bpt3_touch(wacom); | 2100 | return wacom_bpt3_touch(wacom); |
| @@ -2171,7 +2201,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) | |||
| 2171 | if (connected) { | 2201 | if (connected) { |
| 2172 | int pid, battery, charging; | 2202 | int pid, battery, charging; |
| 2173 | 2203 | ||
| 2174 | if ((wacom->shared->type == INTUOSHT) && | 2204 | if ((wacom->shared->type == INTUOSHT || |
| 2205 | wacom->shared->type == INTUOSHT2) && | ||
| 2175 | wacom->shared->touch_input && | 2206 | wacom->shared->touch_input && |
| 2176 | wacom->shared->touch_max) { | 2207 | wacom->shared->touch_max) { |
| 2177 | input_report_switch(wacom->shared->touch_input, | 2208 | input_report_switch(wacom->shared->touch_input, |
| @@ -2209,7 +2240,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 2209 | if (data[0] != WACOM_REPORT_USB) | 2240 | if (data[0] != WACOM_REPORT_USB) |
| 2210 | return 0; | 2241 | return 0; |
| 2211 | 2242 | ||
| 2212 | if (features->type == INTUOSHT && | 2243 | if ((features->type == INTUOSHT || |
| 2244 | features->type == INTUOSHT2) && | ||
| 2213 | wacom_wac->shared->touch_input && | 2245 | wacom_wac->shared->touch_input && |
| 2214 | features->touch_max) { | 2246 | features->touch_max) { |
| 2215 | input_report_switch(wacom_wac->shared->touch_input, | 2247 | input_report_switch(wacom_wac->shared->touch_input, |
| @@ -2290,6 +2322,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 2290 | case WACOM_27QHD: | 2322 | case WACOM_27QHD: |
| 2291 | case DTK: | 2323 | case DTK: |
| 2292 | case CINTIQ_HYBRID: | 2324 | case CINTIQ_HYBRID: |
| 2325 | case CINTIQ_COMPANION_2: | ||
| 2293 | sync = wacom_intuos_irq(wacom_wac); | 2326 | sync = wacom_intuos_irq(wacom_wac); |
| 2294 | break; | 2327 | break; |
| 2295 | 2328 | ||
| @@ -2326,7 +2359,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 2326 | break; | 2359 | break; |
| 2327 | 2360 | ||
| 2328 | case BAMBOO_PT: | 2361 | case BAMBOO_PT: |
| 2362 | case BAMBOO_PEN: | ||
| 2363 | case BAMBOO_TOUCH: | ||
| 2329 | case INTUOSHT: | 2364 | case INTUOSHT: |
| 2365 | case INTUOSHT2: | ||
| 2330 | if (wacom_wac->data[0] == WACOM_REPORT_USB) | 2366 | if (wacom_wac->data[0] == WACOM_REPORT_USB) |
| 2331 | sync = wacom_status_irq(wacom_wac, len); | 2367 | sync = wacom_status_irq(wacom_wac, len); |
| 2332 | else | 2368 | else |
| @@ -2363,22 +2399,31 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | |||
| 2363 | } | 2399 | } |
| 2364 | } | 2400 | } |
| 2365 | 2401 | ||
| 2366 | static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) | 2402 | static void wacom_setup_basic_pro_pen(struct wacom_wac *wacom_wac) |
| 2367 | { | 2403 | { |
| 2368 | struct input_dev *input_dev = wacom_wac->pen_input; | 2404 | struct input_dev *input_dev = wacom_wac->pen_input; |
| 2369 | 2405 | ||
| 2370 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); | 2406 | input_set_capability(input_dev, EV_MSC, MSC_SERIAL); |
| 2371 | 2407 | ||
| 2372 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
| 2373 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 2408 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); |
| 2374 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); | ||
| 2375 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); | ||
| 2376 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); | ||
| 2377 | __set_bit(BTN_STYLUS, input_dev->keybit); | 2409 | __set_bit(BTN_STYLUS, input_dev->keybit); |
| 2378 | __set_bit(BTN_STYLUS2, input_dev->keybit); | 2410 | __set_bit(BTN_STYLUS2, input_dev->keybit); |
| 2379 | 2411 | ||
| 2380 | input_set_abs_params(input_dev, ABS_DISTANCE, | 2412 | input_set_abs_params(input_dev, ABS_DISTANCE, |
| 2381 | 0, wacom_wac->features.distance_max, 0, 0); | 2413 | 0, wacom_wac->features.distance_max, 0, 0); |
| 2414 | } | ||
| 2415 | |||
| 2416 | static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) | ||
| 2417 | { | ||
| 2418 | struct input_dev *input_dev = wacom_wac->pen_input; | ||
| 2419 | |||
| 2420 | wacom_setup_basic_pro_pen(wacom_wac); | ||
| 2421 | |||
| 2422 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
| 2423 | __set_bit(BTN_TOOL_BRUSH, input_dev->keybit); | ||
| 2424 | __set_bit(BTN_TOOL_PENCIL, input_dev->keybit); | ||
| 2425 | __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit); | ||
| 2426 | |||
| 2382 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | 2427 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); |
| 2383 | input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0); | 2428 | input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0); |
| 2384 | input_abs_set_res(input_dev, ABS_TILT_X, 57); | 2429 | input_abs_set_res(input_dev, ABS_TILT_X, 57); |
| @@ -2413,9 +2458,8 @@ void wacom_setup_device_quirks(struct wacom *wacom) | |||
| 2413 | 2458 | ||
| 2414 | /* The pen and pad share the same interface on most devices */ | 2459 | /* The pen and pad share the same interface on most devices */ |
| 2415 | if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || | 2460 | if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || |
| 2416 | features->type == DTUS || features->type == WACOM_MO || | 2461 | features->type == DTUS || |
| 2417 | (features->type >= INTUOS3S && features->type <= WACOM_13HD && | 2462 | (features->type >= INTUOS3S && features->type <= WACOM_MO)) { |
| 2418 | features->type != INTUOSHT)) { | ||
| 2419 | if (features->device_type & WACOM_DEVICETYPE_PEN) | 2463 | if (features->device_type & WACOM_DEVICETYPE_PEN) |
| 2420 | features->device_type |= WACOM_DEVICETYPE_PAD; | 2464 | features->device_type |= WACOM_DEVICETYPE_PAD; |
| 2421 | } | 2465 | } |
| @@ -2432,12 +2476,12 @@ void wacom_setup_device_quirks(struct wacom *wacom) | |||
| 2432 | * interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the | 2476 | * interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the |
| 2433 | * tablet values. | 2477 | * tablet values. |
| 2434 | */ | 2478 | */ |
| 2435 | if ((features->type >= INTUOS5S && features->type <= INTUOSHT) || | 2479 | if ((features->type >= INTUOS5S && features->type <= INTUOSPL) || |
| 2436 | (features->type == BAMBOO_PT)) { | 2480 | (features->type >= INTUOSHT && features->type <= BAMBOO_PT)) { |
| 2437 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { | 2481 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
| 2438 | if (features->touch_max) | 2482 | if (features->touch_max) |
| 2439 | features->device_type |= WACOM_DEVICETYPE_TOUCH; | 2483 | features->device_type |= WACOM_DEVICETYPE_TOUCH; |
| 2440 | if (features->type == BAMBOO_PT || features->type == INTUOSHT) | 2484 | if (features->type >= INTUOSHT || features->type <= BAMBOO_PT) |
| 2441 | features->device_type |= WACOM_DEVICETYPE_PAD; | 2485 | features->device_type |= WACOM_DEVICETYPE_PAD; |
| 2442 | 2486 | ||
| 2443 | features->x_max = 4096; | 2487 | features->x_max = 4096; |
| @@ -2546,6 +2590,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, | |||
| 2546 | case CINTIQ: | 2590 | case CINTIQ: |
| 2547 | case WACOM_13HD: | 2591 | case WACOM_13HD: |
| 2548 | case CINTIQ_HYBRID: | 2592 | case CINTIQ_HYBRID: |
| 2593 | case CINTIQ_COMPANION_2: | ||
| 2549 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); | 2594 | input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); |
| 2550 | input_abs_set_res(input_dev, ABS_Z, 287); | 2595 | input_abs_set_res(input_dev, ABS_Z, 287); |
| 2551 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); | 2596 | __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); |
| @@ -2624,16 +2669,22 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, | |||
| 2624 | 2669 | ||
| 2625 | case INTUOSHT: | 2670 | case INTUOSHT: |
| 2626 | case BAMBOO_PT: | 2671 | case BAMBOO_PT: |
| 2627 | __clear_bit(ABS_MISC, input_dev->absbit); | 2672 | case BAMBOO_PEN: |
| 2628 | 2673 | case INTUOSHT2: | |
| 2629 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | 2674 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); |
| 2630 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | 2675 | |
| 2631 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | 2676 | if (features->type == INTUOSHT2) { |
| 2632 | __set_bit(BTN_STYLUS, input_dev->keybit); | 2677 | wacom_setup_basic_pro_pen(wacom_wac); |
| 2633 | __set_bit(BTN_STYLUS2, input_dev->keybit); | 2678 | } else { |
| 2634 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, | 2679 | __clear_bit(ABS_MISC, input_dev->absbit); |
| 2680 | __set_bit(BTN_TOOL_PEN, input_dev->keybit); | ||
| 2681 | __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); | ||
| 2682 | __set_bit(BTN_STYLUS, input_dev->keybit); | ||
| 2683 | __set_bit(BTN_STYLUS2, input_dev->keybit); | ||
| 2684 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, | ||
| 2635 | features->distance_max, | 2685 | features->distance_max, |
| 2636 | 0, 0); | 2686 | 0, 0); |
| 2687 | } | ||
| 2637 | break; | 2688 | break; |
| 2638 | case BAMBOO_PAD: | 2689 | case BAMBOO_PAD: |
| 2639 | __clear_bit(ABS_MISC, input_dev->absbit); | 2690 | __clear_bit(ABS_MISC, input_dev->absbit); |
| @@ -2714,11 +2765,13 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, | |||
| 2714 | break; | 2765 | break; |
| 2715 | 2766 | ||
| 2716 | case INTUOSHT: | 2767 | case INTUOSHT: |
| 2768 | case INTUOSHT2: | ||
| 2717 | input_dev->evbit[0] |= BIT_MASK(EV_SW); | 2769 | input_dev->evbit[0] |= BIT_MASK(EV_SW); |
| 2718 | __set_bit(SW_MUTE_DEVICE, input_dev->swbit); | 2770 | __set_bit(SW_MUTE_DEVICE, input_dev->swbit); |
| 2719 | /* fall through */ | 2771 | /* fall through */ |
| 2720 | 2772 | ||
| 2721 | case BAMBOO_PT: | 2773 | case BAMBOO_PT: |
| 2774 | case BAMBOO_TOUCH: | ||
| 2722 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { | 2775 | if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { |
| 2723 | input_set_abs_params(input_dev, | 2776 | input_set_abs_params(input_dev, |
| 2724 | ABS_MT_TOUCH_MAJOR, | 2777 | ABS_MT_TOUCH_MAJOR, |
| @@ -2778,6 +2831,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2778 | switch (features->type) { | 2831 | switch (features->type) { |
| 2779 | 2832 | ||
| 2780 | case CINTIQ_HYBRID: | 2833 | case CINTIQ_HYBRID: |
| 2834 | case CINTIQ_COMPANION_2: | ||
| 2781 | case DTK: | 2835 | case DTK: |
| 2782 | case DTUS: | 2836 | case DTUS: |
| 2783 | case GRAPHIRE_BT: | 2837 | case GRAPHIRE_BT: |
| @@ -2871,6 +2925,8 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, | |||
| 2871 | 2925 | ||
| 2872 | case INTUOSHT: | 2926 | case INTUOSHT: |
| 2873 | case BAMBOO_PT: | 2927 | case BAMBOO_PT: |
| 2928 | case BAMBOO_TOUCH: | ||
| 2929 | case INTUOSHT2: | ||
| 2874 | __clear_bit(ABS_MISC, input_dev->absbit); | 2930 | __clear_bit(ABS_MISC, input_dev->absbit); |
| 2875 | 2931 | ||
| 2876 | __set_bit(BTN_LEFT, input_dev->keybit); | 2932 | __set_bit(BTN_LEFT, input_dev->keybit); |
| @@ -3261,11 +3317,10 @@ static const struct wacom_features wacom_features_0x47 = | |||
| 3261 | { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31, | 3317 | { "Wacom Intuos2 6x8", 20320, 16240, 1023, 31, |
| 3262 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3318 | INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3263 | static const struct wacom_features wacom_features_0x84 = | 3319 | static const struct wacom_features wacom_features_0x84 = |
| 3264 | { "Wacom Wireless Receiver", 0, 0, 0, 0, | 3320 | { "Wacom Wireless Receiver", .type = WIRELESS, .touch_max = 16 }; |
| 3265 | WIRELESS, 0, 0, .touch_max = 16 }; | ||
| 3266 | static const struct wacom_features wacom_features_0xD0 = | 3321 | static const struct wacom_features wacom_features_0xD0 = |
| 3267 | { "Wacom Bamboo 2FG", 14720, 9200, 1023, 31, | 3322 | { "Wacom Bamboo 2FG", 14720, 9200, 1023, 31, |
| 3268 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; | 3323 | BAMBOO_TOUCH, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
| 3269 | static const struct wacom_features wacom_features_0xD1 = | 3324 | static const struct wacom_features wacom_features_0xD1 = |
| 3270 | { "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31, | 3325 | { "Wacom Bamboo 2FG 4x5", 14720, 9200, 1023, 31, |
| 3271 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; | 3326 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
| @@ -3277,10 +3332,10 @@ static const struct wacom_features wacom_features_0xD3 = | |||
| 3277 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; | 3332 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
| 3278 | static const struct wacom_features wacom_features_0xD4 = | 3333 | static const struct wacom_features wacom_features_0xD4 = |
| 3279 | { "Wacom Bamboo Pen", 14720, 9200, 1023, 31, | 3334 | { "Wacom Bamboo Pen", 14720, 9200, 1023, 31, |
| 3280 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3335 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3281 | static const struct wacom_features wacom_features_0xD5 = | 3336 | static const struct wacom_features wacom_features_0xD5 = |
| 3282 | { "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31, | 3337 | { "Wacom Bamboo Pen 6x8", 21648, 13700, 1023, 31, |
| 3283 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3338 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3284 | static const struct wacom_features wacom_features_0xD6 = | 3339 | static const struct wacom_features wacom_features_0xD6 = |
| 3285 | { "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31, | 3340 | { "Wacom BambooPT 2FG 4x5", 14720, 9200, 1023, 31, |
| 3286 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; | 3341 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 2 }; |
| @@ -3307,7 +3362,7 @@ static const struct wacom_features wacom_features_0xDF = | |||
| 3307 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; | 3362 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16 }; |
| 3308 | static const struct wacom_features wacom_features_0x300 = | 3363 | static const struct wacom_features wacom_features_0x300 = |
| 3309 | { "Wacom Bamboo One S", 14720, 9225, 1023, 31, | 3364 | { "Wacom Bamboo One S", 14720, 9225, 1023, 31, |
| 3310 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3365 | BAMBOO_PEN, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| 3311 | static const struct wacom_features wacom_features_0x301 = | 3366 | static const struct wacom_features wacom_features_0x301 = |
| 3312 | { "Wacom Bamboo One M", 21648, 13530, 1023, 31, | 3367 | { "Wacom Bamboo One M", 21648, 13530, 1023, 31, |
| 3313 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 3368 | BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
| @@ -3350,14 +3405,38 @@ static const struct wacom_features wacom_features_0x318 = | |||
| 3350 | static const struct wacom_features wacom_features_0x319 = | 3405 | static const struct wacom_features wacom_features_0x319 = |
| 3351 | { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */ | 3406 | { "Wacom Wireless Bamboo PAD", 4095, 4095, /* Touch */ |
| 3352 | .type = BAMBOO_PAD, 35, 48, .touch_max = 4 }; | 3407 | .type = BAMBOO_PAD, 35, 48, .touch_max = 4 }; |
| 3408 | static const struct wacom_features wacom_features_0x325 = | ||
| 3409 | { "Wacom ISDv5 325", 59552, 33848, 2047, 63, | ||
| 3410 | CINTIQ_COMPANION_2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 11, | ||
| 3411 | WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, | ||
| 3412 | .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x326 }; | ||
| 3413 | static const struct wacom_features wacom_features_0x326 = /* Touch */ | ||
| 3414 | { "Wacom ISDv5 326", .type = HID_GENERIC, .oVid = USB_VENDOR_ID_WACOM, | ||
| 3415 | .oPid = 0x325 }; | ||
| 3353 | static const struct wacom_features wacom_features_0x323 = | 3416 | static const struct wacom_features wacom_features_0x323 = |
| 3354 | { "Wacom Intuos P M", 21600, 13500, 1023, 31, | 3417 | { "Wacom Intuos P M", 21600, 13500, 1023, 31, |
| 3355 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | 3418 | INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, |
| 3356 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | 3419 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; |
| 3357 | static const struct wacom_features wacom_features_0x331 = | 3420 | static const struct wacom_features wacom_features_0x331 = |
| 3358 | { "Wacom Express Key Remote", 0, 0, 0, 0, | 3421 | { "Wacom Express Key Remote", .type = REMOTE, |
| 3359 | REMOTE, 0, 0, 18, .check_for_hid_type = true, | 3422 | .numbered_buttons = 18, .check_for_hid_type = true, |
| 3360 | .hid_type = HID_TYPE_USBNONE }; | 3423 | .hid_type = HID_TYPE_USBNONE }; |
| 3424 | static const struct wacom_features wacom_features_0x33B = | ||
| 3425 | { "Wacom Intuos S 2", 15200, 9500, 2047, 63, | ||
| 3426 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | ||
| 3427 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | ||
| 3428 | static const struct wacom_features wacom_features_0x33C = | ||
| 3429 | { "Wacom Intuos PT S 2", 15200, 9500, 2047, 63, | ||
| 3430 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, | ||
| 3431 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | ||
| 3432 | static const struct wacom_features wacom_features_0x33D = | ||
| 3433 | { "Wacom Intuos P M 2", 21600, 13500, 2047, 63, | ||
| 3434 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, | ||
| 3435 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | ||
| 3436 | static const struct wacom_features wacom_features_0x33E = | ||
| 3437 | { "Wacom Intuos PT M 2", 21600, 13500, 2047, 63, | ||
| 3438 | INTUOSHT2, WACOM_INTUOS_RES, WACOM_INTUOS_RES, .touch_max = 16, | ||
| 3439 | .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; | ||
| 3361 | 3440 | ||
| 3362 | static const struct wacom_features wacom_features_HID_ANY_ID = | 3441 | static const struct wacom_features wacom_features_HID_ANY_ID = |
| 3363 | { "Wacom HID", .type = HID_GENERIC }; | 3442 | { "Wacom HID", .type = HID_GENERIC }; |
| @@ -3509,6 +3588,8 @@ const struct hid_device_id wacom_ids[] = { | |||
| 3509 | { USB_DEVICE_WACOM(0x318) }, | 3588 | { USB_DEVICE_WACOM(0x318) }, |
| 3510 | { USB_DEVICE_WACOM(0x319) }, | 3589 | { USB_DEVICE_WACOM(0x319) }, |
| 3511 | { USB_DEVICE_WACOM(0x323) }, | 3590 | { USB_DEVICE_WACOM(0x323) }, |
| 3591 | { USB_DEVICE_WACOM(0x325) }, | ||
| 3592 | { USB_DEVICE_WACOM(0x326) }, | ||
| 3512 | { USB_DEVICE_WACOM(0x32A) }, | 3593 | { USB_DEVICE_WACOM(0x32A) }, |
| 3513 | { USB_DEVICE_WACOM(0x32B) }, | 3594 | { USB_DEVICE_WACOM(0x32B) }, |
| 3514 | { USB_DEVICE_WACOM(0x32C) }, | 3595 | { USB_DEVICE_WACOM(0x32C) }, |
| @@ -3517,6 +3598,10 @@ const struct hid_device_id wacom_ids[] = { | |||
| 3517 | { USB_DEVICE_WACOM(0x333) }, | 3598 | { USB_DEVICE_WACOM(0x333) }, |
| 3518 | { USB_DEVICE_WACOM(0x335) }, | 3599 | { USB_DEVICE_WACOM(0x335) }, |
| 3519 | { USB_DEVICE_WACOM(0x336) }, | 3600 | { USB_DEVICE_WACOM(0x336) }, |
| 3601 | { USB_DEVICE_WACOM(0x33B) }, | ||
| 3602 | { USB_DEVICE_WACOM(0x33C) }, | ||
| 3603 | { USB_DEVICE_WACOM(0x33D) }, | ||
| 3604 | { USB_DEVICE_WACOM(0x33E) }, | ||
| 3520 | { USB_DEVICE_WACOM(0x4001) }, | 3605 | { USB_DEVICE_WACOM(0x4001) }, |
| 3521 | { USB_DEVICE_WACOM(0x4004) }, | 3606 | { USB_DEVICE_WACOM(0x4004) }, |
| 3522 | { USB_DEVICE_WACOM(0x5000) }, | 3607 | { USB_DEVICE_WACOM(0x5000) }, |
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 809c03e34f74..877c24a5df94 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #define WACOM_REPORT_BPAD_PEN 3 | 68 | #define WACOM_REPORT_BPAD_PEN 3 |
| 69 | #define WACOM_REPORT_BPAD_TOUCH 16 | 69 | #define WACOM_REPORT_BPAD_TOUCH 16 |
| 70 | #define WACOM_REPORT_DEVICE_LIST 16 | 70 | #define WACOM_REPORT_DEVICE_LIST 16 |
| 71 | #define WACOM_REPORT_INTUOS_PEN 16 | ||
| 71 | #define WACOM_REPORT_REMOTE 17 | 72 | #define WACOM_REPORT_REMOTE 17 |
| 72 | 73 | ||
| 73 | /* device quirks */ | 74 | /* device quirks */ |
| @@ -117,22 +118,26 @@ enum { | |||
| 117 | INTUOSPS, | 118 | INTUOSPS, |
| 118 | INTUOSPM, | 119 | INTUOSPM, |
| 119 | INTUOSPL, | 120 | INTUOSPL, |
| 120 | INTUOSHT, | ||
| 121 | WACOM_21UX2, | 121 | WACOM_21UX2, |
| 122 | WACOM_22HD, | 122 | WACOM_22HD, |
| 123 | DTK, | 123 | DTK, |
| 124 | WACOM_24HD, | 124 | WACOM_24HD, |
| 125 | WACOM_27QHD, | 125 | WACOM_27QHD, |
| 126 | CINTIQ_HYBRID, | 126 | CINTIQ_HYBRID, |
| 127 | CINTIQ_COMPANION_2, | ||
| 127 | CINTIQ, | 128 | CINTIQ, |
| 128 | WACOM_BEE, | 129 | WACOM_BEE, |
| 129 | WACOM_13HD, | 130 | WACOM_13HD, |
| 130 | WACOM_MO, | 131 | WACOM_MO, |
| 131 | WIRELESS, | 132 | BAMBOO_PEN, |
| 133 | INTUOSHT, | ||
| 134 | INTUOSHT2, | ||
| 135 | BAMBOO_TOUCH, | ||
| 132 | BAMBOO_PT, | 136 | BAMBOO_PT, |
| 133 | WACOM_24HDT, | 137 | WACOM_24HDT, |
| 134 | WACOM_27QHDT, | 138 | WACOM_27QHDT, |
| 135 | BAMBOO_PAD, | 139 | BAMBOO_PAD, |
| 140 | WIRELESS, | ||
| 136 | REMOTE, | 141 | REMOTE, |
| 137 | TABLETPC, /* add new TPC below */ | 142 | TABLETPC, /* add new TPC below */ |
| 138 | TABLETPCE, | 143 | TABLETPCE, |
diff --git a/include/linux/hid.h b/include/linux/hid.h index f17980de2662..251a1d382e23 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -698,8 +698,8 @@ struct hid_driver { | |||
| 698 | int (*input_mapped)(struct hid_device *hdev, | 698 | int (*input_mapped)(struct hid_device *hdev, |
| 699 | struct hid_input *hidinput, struct hid_field *field, | 699 | struct hid_input *hidinput, struct hid_field *field, |
| 700 | struct hid_usage *usage, unsigned long **bit, int *max); | 700 | struct hid_usage *usage, unsigned long **bit, int *max); |
| 701 | void (*input_configured)(struct hid_device *hdev, | 701 | int (*input_configured)(struct hid_device *hdev, |
| 702 | struct hid_input *hidinput); | 702 | struct hid_input *hidinput); |
| 703 | void (*feature_mapping)(struct hid_device *hdev, | 703 | void (*feature_mapping)(struct hid_device *hdev, |
| 704 | struct hid_field *field, | 704 | struct hid_field *field, |
| 705 | struct hid_usage *usage); | 705 | struct hid_usage *usage); |
