diff options
author | Nikolai Kondrashov <spbnick@gmail.com> | 2011-01-28 06:50:52 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-02-01 05:01:06 -0500 |
commit | e05eefb9be109e6cbbfd362b49ee83397130a7e4 (patch) | |
tree | 008eb48a5df684b1607725eda88ce5b8e2a4325a | |
parent | 152fd6347e63d176d1f03c8d142e534a5227ef3f (diff) |
HID: add support for DragonRise PID 0011 gamepad
Add support for DragonRise Inc. gamepad with USB PID 0x0011 by fixing its report
descriptor. This mainly removes spurious axis.
Signed-off-by: Nikolai Kondrashov <spbnick@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-core.c | 1 | ||||
-rw-r--r-- | drivers/hid/hid-dr.c | 117 |
2 files changed, 117 insertions, 1 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d678cf3d33d5..75af1f835320 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1328,6 +1328,7 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
1328 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, | 1328 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, |
1329 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, | 1329 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, |
1330 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, | 1330 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, |
1331 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) }, | ||
1331 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, | 1332 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) }, |
1332 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, | 1333 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) }, |
1333 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, | 1334 | { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) }, |
diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index afcf3d67eb02..61eece47204d 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c | |||
@@ -145,6 +145,110 @@ static inline int drff_init(struct hid_device *hid) | |||
145 | } | 145 | } |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | /* | ||
149 | * The original descriptor of joystick with PID 0x0011, represented by DVTech PC | ||
150 | * JS19. It seems both copied from another device and a result of confusion | ||
151 | * either about the specification or about the program used to create the | ||
152 | * descriptor. In any case, it's a wonder it works on Windows. | ||
153 | * | ||
154 | * Usage Page (Desktop), ; Generic desktop controls (01h) | ||
155 | * Usage (Joystik), ; Joystik (04h, application collection) | ||
156 | * Collection (Application), | ||
157 | * Collection (Logical), | ||
158 | * Report Size (8), | ||
159 | * Report Count (5), | ||
160 | * Logical Minimum (0), | ||
161 | * Logical Maximum (255), | ||
162 | * Physical Minimum (0), | ||
163 | * Physical Maximum (255), | ||
164 | * Usage (X), ; X (30h, dynamic value) | ||
165 | * Usage (X), ; X (30h, dynamic value) | ||
166 | * Usage (X), ; X (30h, dynamic value) | ||
167 | * Usage (X), ; X (30h, dynamic value) | ||
168 | * Usage (Y), ; Y (31h, dynamic value) | ||
169 | * Input (Variable), | ||
170 | * Report Size (4), | ||
171 | * Report Count (1), | ||
172 | * Logical Maximum (7), | ||
173 | * Physical Maximum (315), | ||
174 | * Unit (Degrees), | ||
175 | * Usage (00h), | ||
176 | * Input (Variable, Null State), | ||
177 | * Unit, | ||
178 | * Report Size (1), | ||
179 | * Report Count (10), | ||
180 | * Logical Maximum (1), | ||
181 | * Physical Maximum (1), | ||
182 | * Usage Page (Button), ; Button (09h) | ||
183 | * Usage Minimum (01h), | ||
184 | * Usage Maximum (0Ah), | ||
185 | * Input (Variable), | ||
186 | * Usage Page (FF00h), ; FF00h, vendor-defined | ||
187 | * Report Size (1), | ||
188 | * Report Count (10), | ||
189 | * Logical Maximum (1), | ||
190 | * Physical Maximum (1), | ||
191 | * Usage (01h), | ||
192 | * Input (Variable), | ||
193 | * End Collection, | ||
194 | * Collection (Logical), | ||
195 | * Report Size (8), | ||
196 | * Report Count (4), | ||
197 | * Physical Maximum (255), | ||
198 | * Logical Maximum (255), | ||
199 | * Usage (02h), | ||
200 | * Output (Variable), | ||
201 | * End Collection, | ||
202 | * End Collection | ||
203 | */ | ||
204 | |||
205 | /* Size of the original descriptor of the PID 0x0011 joystick */ | ||
206 | #define PID0011_RDESC_ORIG_SIZE 101 | ||
207 | |||
208 | /* Fixed report descriptor for PID 0x011 joystick */ | ||
209 | static __u8 pid0011_rdesc_fixed[] = { | ||
210 | 0x05, 0x01, /* Usage Page (Desktop), */ | ||
211 | 0x09, 0x04, /* Usage (Joystik), */ | ||
212 | 0xA1, 0x01, /* Collection (Application), */ | ||
213 | 0xA1, 0x02, /* Collection (Logical), */ | ||
214 | 0x14, /* Logical Minimum (0), */ | ||
215 | 0x75, 0x08, /* Report Size (8), */ | ||
216 | 0x95, 0x03, /* Report Count (3), */ | ||
217 | 0x81, 0x01, /* Input (Constant), */ | ||
218 | 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ | ||
219 | 0x95, 0x02, /* Report Count (2), */ | ||
220 | 0x09, 0x30, /* Usage (X), */ | ||
221 | 0x09, 0x31, /* Usage (Y), */ | ||
222 | 0x81, 0x02, /* Input (Variable), */ | ||
223 | 0x75, 0x01, /* Report Size (1), */ | ||
224 | 0x95, 0x04, /* Report Count (4), */ | ||
225 | 0x81, 0x01, /* Input (Constant), */ | ||
226 | 0x25, 0x01, /* Logical Maximum (1), */ | ||
227 | 0x95, 0x0A, /* Report Count (10), */ | ||
228 | 0x05, 0x09, /* Usage Page (Button), */ | ||
229 | 0x19, 0x01, /* Usage Minimum (01h), */ | ||
230 | 0x29, 0x0A, /* Usage Maximum (0Ah), */ | ||
231 | 0x81, 0x02, /* Input (Variable), */ | ||
232 | 0x95, 0x0A, /* Report Count (10), */ | ||
233 | 0x81, 0x01, /* Input (Constant), */ | ||
234 | 0xC0, /* End Collection, */ | ||
235 | 0xC0 /* End Collection */ | ||
236 | }; | ||
237 | |||
238 | static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, | ||
239 | unsigned int *rsize) | ||
240 | { | ||
241 | switch (hdev->product) { | ||
242 | case 0x0011: | ||
243 | if (*rsize == PID0011_RDESC_ORIG_SIZE) { | ||
244 | rdesc = pid0011_rdesc_fixed; | ||
245 | *rsize = sizeof(pid0011_rdesc_fixed); | ||
246 | } | ||
247 | break; | ||
248 | } | ||
249 | return rdesc; | ||
250 | } | ||
251 | |||
148 | static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) | 252 | static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) |
149 | { | 253 | { |
150 | int ret; | 254 | int ret; |
@@ -163,7 +267,16 @@ static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
163 | goto err; | 267 | goto err; |
164 | } | 268 | } |
165 | 269 | ||
166 | drff_init(hdev); | 270 | switch (hdev->product) { |
271 | case 0x0006: | ||
272 | ret = drff_init(hdev); | ||
273 | if (ret) { | ||
274 | dev_err(&hdev->dev, "force feedback init failed\n"); | ||
275 | hid_hw_stop(hdev); | ||
276 | goto err; | ||
277 | } | ||
278 | break; | ||
279 | } | ||
167 | 280 | ||
168 | return 0; | 281 | return 0; |
169 | err: | 282 | err: |
@@ -172,6 +285,7 @@ err: | |||
172 | 285 | ||
173 | static const struct hid_device_id dr_devices[] = { | 286 | static const struct hid_device_id dr_devices[] = { |
174 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, | 287 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006), }, |
288 | { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011), }, | ||
175 | { } | 289 | { } |
176 | }; | 290 | }; |
177 | MODULE_DEVICE_TABLE(hid, dr_devices); | 291 | MODULE_DEVICE_TABLE(hid, dr_devices); |
@@ -179,6 +293,7 @@ MODULE_DEVICE_TABLE(hid, dr_devices); | |||
179 | static struct hid_driver dr_driver = { | 293 | static struct hid_driver dr_driver = { |
180 | .name = "dragonrise", | 294 | .name = "dragonrise", |
181 | .id_table = dr_devices, | 295 | .id_table = dr_devices, |
296 | .report_fixup = dr_report_fixup, | ||
182 | .probe = dr_probe, | 297 | .probe = dr_probe, |
183 | }; | 298 | }; |
184 | 299 | ||