diff options
Diffstat (limited to 'drivers/hid/hid-lg.c')
-rw-r--r-- | drivers/hid/hid-lg.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index f6433d8050a9..9e92c27002ca 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (c) 2006-2007 Jiri Kosina | 7 | * Copyright (c) 2006-2007 Jiri Kosina |
8 | * Copyright (c) 2007 Paul Walmsley | 8 | * Copyright (c) 2007 Paul Walmsley |
9 | * Copyright (c) 2008 Jiri Slaby | 9 | * Copyright (c) 2008 Jiri Slaby |
10 | * Copyright (c) 2010 Hendrik Iben | ||
10 | */ | 11 | */ |
11 | 12 | ||
12 | /* | 13 | /* |
@@ -19,6 +20,9 @@ | |||
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <linux/hid.h> | 21 | #include <linux/hid.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/random.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/wait.h> | ||
22 | 26 | ||
23 | #include "hid-ids.h" | 27 | #include "hid-ids.h" |
24 | #include "hid-lg.h" | 28 | #include "hid-lg.h" |
@@ -35,6 +39,7 @@ | |||
35 | #define LG_FF2 0x400 | 39 | #define LG_FF2 0x400 |
36 | #define LG_RDESC_REL_ABS 0x800 | 40 | #define LG_RDESC_REL_ABS 0x800 |
37 | #define LG_FF3 0x1000 | 41 | #define LG_FF3 0x1000 |
42 | #define LG_FF4 0x2000 | ||
38 | 43 | ||
39 | /* | 44 | /* |
40 | * Certain Logitech keyboards send in report #3 keys which are far | 45 | * Certain Logitech keyboards send in report #3 keys which are far |
@@ -60,6 +65,17 @@ static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
60 | "report descriptor\n"); | 65 | "report descriptor\n"); |
61 | rdesc[33] = rdesc[50] = 0x02; | 66 | rdesc[33] = rdesc[50] = 0x02; |
62 | } | 67 | } |
68 | |||
69 | if ((quirks & LG_FF4) && rsize >= 101 && | ||
70 | rdesc[41] == 0x95 && rdesc[42] == 0x0B && | ||
71 | rdesc[47] == 0x05 && rdesc[48] == 0x09) { | ||
72 | dev_info(&hdev->dev, "fixing up Logitech Speed Force Wireless " | ||
73 | "button descriptor\n"); | ||
74 | rdesc[41] = 0x05; | ||
75 | rdesc[42] = 0x09; | ||
76 | rdesc[47] = 0x95; | ||
77 | rdesc[48] = 0x0B; | ||
78 | } | ||
63 | } | 79 | } |
64 | 80 | ||
65 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 81 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
@@ -285,12 +301,33 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
285 | goto err_free; | 301 | goto err_free; |
286 | } | 302 | } |
287 | 303 | ||
304 | if (quirks & LG_FF4) { | ||
305 | unsigned char buf[] = { 0x00, 0xAF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
306 | |||
307 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
308 | |||
309 | if (ret >= 0) { | ||
310 | /* insert a little delay of 10 jiffies ~ 40ms */ | ||
311 | wait_queue_head_t wait; | ||
312 | init_waitqueue_head (&wait); | ||
313 | wait_event_interruptible_timeout(wait, 0, 10); | ||
314 | |||
315 | /* Select random Address */ | ||
316 | buf[1] = 0xB2; | ||
317 | get_random_bytes(&buf[2], 2); | ||
318 | |||
319 | ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | ||
320 | } | ||
321 | } | ||
322 | |||
288 | if (quirks & LG_FF) | 323 | if (quirks & LG_FF) |
289 | lgff_init(hdev); | 324 | lgff_init(hdev); |
290 | if (quirks & LG_FF2) | 325 | if (quirks & LG_FF2) |
291 | lg2ff_init(hdev); | 326 | lg2ff_init(hdev); |
292 | if (quirks & LG_FF3) | 327 | if (quirks & LG_FF3) |
293 | lg3ff_init(hdev); | 328 | lg3ff_init(hdev); |
329 | if (quirks & LG_FF4) | ||
330 | lg4ff_init(hdev); | ||
294 | 331 | ||
295 | return 0; | 332 | return 0; |
296 | err_free: | 333 | err_free: |
@@ -325,6 +362,8 @@ static const struct hid_device_id lg_devices[] = { | |||
325 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), | 362 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL), |
326 | .driver_data = LG_NOGET | LG_FF }, | 363 | .driver_data = LG_NOGET | LG_FF }, |
327 | 364 | ||
365 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD_CORD), | ||
366 | .driver_data = LG_FF2 }, | ||
328 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), | 367 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD), |
329 | .driver_data = LG_FF }, | 368 | .driver_data = LG_FF }, |
330 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), | 369 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2), |
@@ -339,6 +378,8 @@ static const struct hid_device_id lg_devices[] = { | |||
339 | .driver_data = LG_FF }, | 378 | .driver_data = LG_FF }, |
340 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), | 379 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL), |
341 | .driver_data = LG_FF }, | 380 | .driver_data = LG_FF }, |
381 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), | ||
382 | .driver_data = LG_FF4 }, | ||
342 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), | 383 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), |
343 | .driver_data = LG_FF }, | 384 | .driver_data = LG_FF }, |
344 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), | 385 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), |