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); |