diff options
Diffstat (limited to 'drivers/hid/hid-lg.c')
-rw-r--r-- | drivers/hid/hid-lg.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 0f870a3243ed..3677c9037a11 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #define LG_NOGET 0x100 | 33 | #define LG_NOGET 0x100 |
34 | #define LG_FF 0x200 | 34 | #define LG_FF 0x200 |
35 | #define LG_FF2 0x400 | 35 | #define LG_FF2 0x400 |
36 | #define LG_RDESC_REL_ABS 0x800 | ||
37 | #define LG_FF3 0x1000 | ||
36 | 38 | ||
37 | /* | 39 | /* |
38 | * Certain Logitech keyboards send in report #3 keys which are far | 40 | * Certain Logitech keyboards send in report #3 keys which are far |
@@ -51,6 +53,13 @@ static void lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
51 | rdesc[84] = rdesc[89] = 0x4d; | 53 | rdesc[84] = rdesc[89] = 0x4d; |
52 | rdesc[85] = rdesc[90] = 0x10; | 54 | rdesc[85] = rdesc[90] = 0x10; |
53 | } | 55 | } |
56 | if ((quirks & LG_RDESC_REL_ABS) && rsize >= 50 && | ||
57 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && | ||
58 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { | ||
59 | dev_info(&hdev->dev, "fixing up rel/abs in Logitech " | ||
60 | "report descriptor\n"); | ||
61 | rdesc[33] = rdesc[50] = 0x02; | ||
62 | } | ||
54 | } | 63 | } |
55 | 64 | ||
56 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | 65 | #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ |
@@ -89,6 +98,22 @@ static int lg_ultrax_remote_mapping(struct hid_input *hi, | |||
89 | return 1; | 98 | return 1; |
90 | } | 99 | } |
91 | 100 | ||
101 | static int lg_dinovo_mapping(struct hid_input *hi, struct hid_usage *usage, | ||
102 | unsigned long **bit, int *max) | ||
103 | { | ||
104 | if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) | ||
105 | return 0; | ||
106 | |||
107 | switch (usage->hid & HID_USAGE) { | ||
108 | |||
109 | case 0x00d: lg_map_key_clear(KEY_MEDIA); break; | ||
110 | default: | ||
111 | return 0; | ||
112 | |||
113 | } | ||
114 | return 1; | ||
115 | } | ||
116 | |||
92 | static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, | 117 | static int lg_wireless_mapping(struct hid_input *hi, struct hid_usage *usage, |
93 | unsigned long **bit, int *max) | 118 | unsigned long **bit, int *max) |
94 | { | 119 | { |
@@ -164,6 +189,10 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
164 | lg_ultrax_remote_mapping(hi, usage, bit, max)) | 189 | lg_ultrax_remote_mapping(hi, usage, bit, max)) |
165 | return 1; | 190 | return 1; |
166 | 191 | ||
192 | if (hdev->product == USB_DEVICE_ID_DINOVO_MINI && | ||
193 | lg_dinovo_mapping(hi, usage, bit, max)) | ||
194 | return 1; | ||
195 | |||
167 | if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) | 196 | if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) |
168 | return 1; | 197 | return 1; |
169 | 198 | ||
@@ -238,7 +267,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
238 | goto err_free; | 267 | goto err_free; |
239 | } | 268 | } |
240 | 269 | ||
241 | if (quirks & (LG_FF | LG_FF2)) | 270 | if (quirks & (LG_FF | LG_FF2 | LG_FF3)) |
242 | connect_mask &= ~HID_CONNECT_FF; | 271 | connect_mask &= ~HID_CONNECT_FF; |
243 | 272 | ||
244 | ret = hid_hw_start(hdev, connect_mask); | 273 | ret = hid_hw_start(hdev, connect_mask); |
@@ -251,6 +280,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
251 | lgff_init(hdev); | 280 | lgff_init(hdev); |
252 | if (quirks & LG_FF2) | 281 | if (quirks & LG_FF2) |
253 | lg2ff_init(hdev); | 282 | lg2ff_init(hdev); |
283 | if (quirks & LG_FF3) | ||
284 | lg3ff_init(hdev); | ||
254 | 285 | ||
255 | return 0; | 286 | return 0; |
256 | err_free: | 287 | err_free: |
@@ -303,8 +334,15 @@ static const struct hid_device_id lg_devices[] = { | |||
303 | .driver_data = LG_FF }, | 334 | .driver_data = LG_FF }, |
304 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), | 335 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), |
305 | .driver_data = LG_FF2 }, | 336 | .driver_data = LG_FF2 }, |
337 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940), | ||
338 | .driver_data = LG_FF3 }, | ||
339 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR), | ||
340 | .driver_data = LG_RDESC_REL_ABS }, | ||
341 | { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER), | ||
342 | .driver_data = LG_RDESC_REL_ABS }, | ||
306 | { } | 343 | { } |
307 | }; | 344 | }; |
345 | |||
308 | MODULE_DEVICE_TABLE(hid, lg_devices); | 346 | MODULE_DEVICE_TABLE(hid, lg_devices); |
309 | 347 | ||
310 | static struct hid_driver lg_driver = { | 348 | static struct hid_driver lg_driver = { |