diff options
| -rw-r--r-- | drivers/hid/hid-lg.c | 55 | ||||
| -rw-r--r-- | drivers/hid/hid-lg.h | 7 |
2 files changed, 39 insertions, 23 deletions
diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index e7a7bd1eb34a..fc37ed6b108c 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c | |||
| @@ -109,23 +109,23 @@ static __u8 dfp_rdesc_fixed[] = { | |||
| 109 | static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, | 109 | static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, |
| 110 | unsigned int *rsize) | 110 | unsigned int *rsize) |
| 111 | { | 111 | { |
| 112 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 112 | struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); |
| 113 | 113 | ||
| 114 | if ((quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && | 114 | if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 && |
| 115 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { | 115 | rdesc[84] == 0x8c && rdesc[85] == 0x02) { |
| 116 | hid_info(hdev, | 116 | hid_info(hdev, |
| 117 | "fixing up Logitech keyboard report descriptor\n"); | 117 | "fixing up Logitech keyboard report descriptor\n"); |
| 118 | rdesc[84] = rdesc[89] = 0x4d; | 118 | rdesc[84] = rdesc[89] = 0x4d; |
| 119 | rdesc[85] = rdesc[90] = 0x10; | 119 | rdesc[85] = rdesc[90] = 0x10; |
| 120 | } | 120 | } |
| 121 | if ((quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && | 121 | if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 && |
| 122 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && | 122 | rdesc[32] == 0x81 && rdesc[33] == 0x06 && |
| 123 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { | 123 | rdesc[49] == 0x81 && rdesc[50] == 0x06) { |
| 124 | hid_info(hdev, | 124 | hid_info(hdev, |
| 125 | "fixing up rel/abs in Logitech report descriptor\n"); | 125 | "fixing up rel/abs in Logitech report descriptor\n"); |
| 126 | rdesc[33] = rdesc[50] = 0x02; | 126 | rdesc[33] = rdesc[50] = 0x02; |
| 127 | } | 127 | } |
| 128 | if ((quirks & LG_FF4) && *rsize >= 101 && | 128 | if ((drv_data->quirks & LG_FF4) && *rsize >= 101 && |
| 129 | rdesc[41] == 0x95 && rdesc[42] == 0x0B && | 129 | rdesc[41] == 0x95 && rdesc[42] == 0x0B && |
| 130 | rdesc[47] == 0x05 && rdesc[48] == 0x09) { | 130 | rdesc[47] == 0x05 && rdesc[48] == 0x09) { |
| 131 | hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n"); | 131 | hid_info(hdev, "fixing up Logitech Speed Force Wireless button descriptor\n"); |
| @@ -278,7 +278,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 278 | 0, 0, 0, 0, 0,183,184,185,186,187, | 278 | 0, 0, 0, 0, 0,183,184,185,186,187, |
| 279 | 188,189,190,191,192,193,194, 0, 0, 0 | 279 | 188,189,190,191,192,193,194, 0, 0, 0 |
| 280 | }; | 280 | }; |
| 281 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 281 | struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); |
| 282 | unsigned int hid = usage->hid; | 282 | unsigned int hid = usage->hid; |
| 283 | 283 | ||
| 284 | if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && | 284 | if (hdev->product == USB_DEVICE_ID_LOGITECH_RECEIVER && |
| @@ -289,7 +289,7 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 289 | lg_dinovo_mapping(hi, usage, bit, max)) | 289 | lg_dinovo_mapping(hi, usage, bit, max)) |
| 290 | return 1; | 290 | return 1; |
| 291 | 291 | ||
| 292 | if ((quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) | 292 | if ((drv_data->quirks & LG_WIRELESS) && lg_wireless_mapping(hi, usage, bit, max)) |
| 293 | return 1; | 293 | return 1; |
| 294 | 294 | ||
| 295 | if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON) | 295 | if ((hid & HID_USAGE_PAGE) != HID_UP_BUTTON) |
| @@ -299,11 +299,11 @@ static int lg_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 299 | 299 | ||
| 300 | /* Special handling for Logitech Cordless Desktop */ | 300 | /* Special handling for Logitech Cordless Desktop */ |
| 301 | if (field->application == HID_GD_MOUSE) { | 301 | if (field->application == HID_GD_MOUSE) { |
| 302 | if ((quirks & LG_IGNORE_DOUBLED_WHEEL) && | 302 | if ((drv_data->quirks & LG_IGNORE_DOUBLED_WHEEL) && |
| 303 | (hid == 7 || hid == 8)) | 303 | (hid == 7 || hid == 8)) |
| 304 | return -1; | 304 | return -1; |
| 305 | } else { | 305 | } else { |
| 306 | if ((quirks & LG_EXPANDED_KEYMAP) && | 306 | if ((drv_data->quirks & LG_EXPANDED_KEYMAP) && |
| 307 | hid < ARRAY_SIZE(e_keymap) && | 307 | hid < ARRAY_SIZE(e_keymap) && |
| 308 | e_keymap[hid] != 0) { | 308 | e_keymap[hid] != 0) { |
| 309 | hid_map_usage(hi, usage, bit, max, EV_KEY, | 309 | hid_map_usage(hi, usage, bit, max, EV_KEY, |
| @@ -319,13 +319,13 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 319 | struct hid_field *field, struct hid_usage *usage, | 319 | struct hid_field *field, struct hid_usage *usage, |
| 320 | unsigned long **bit, int *max) | 320 | unsigned long **bit, int *max) |
| 321 | { | 321 | { |
| 322 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 322 | struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); |
| 323 | 323 | ||
| 324 | if ((quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && | 324 | if ((drv_data->quirks & LG_BAD_RELATIVE_KEYS) && usage->type == EV_KEY && |
| 325 | (field->flags & HID_MAIN_ITEM_RELATIVE)) | 325 | (field->flags & HID_MAIN_ITEM_RELATIVE)) |
| 326 | field->flags &= ~HID_MAIN_ITEM_RELATIVE; | 326 | field->flags &= ~HID_MAIN_ITEM_RELATIVE; |
| 327 | 327 | ||
| 328 | if ((quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY || | 328 | if ((drv_data->quirks & LG_DUPLICATE_USAGES) && (usage->type == EV_KEY || |
| 329 | usage->type == EV_REL || usage->type == EV_ABS)) | 329 | usage->type == EV_REL || usage->type == EV_ABS)) |
| 330 | clear_bit(usage->code, *bit); | 330 | clear_bit(usage->code, *bit); |
| 331 | 331 | ||
| @@ -335,9 +335,9 @@ static int lg_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 335 | static int lg_event(struct hid_device *hdev, struct hid_field *field, | 335 | static int lg_event(struct hid_device *hdev, struct hid_field *field, |
| 336 | struct hid_usage *usage, __s32 value) | 336 | struct hid_usage *usage, __s32 value) |
| 337 | { | 337 | { |
| 338 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 338 | struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); |
| 339 | 339 | ||
| 340 | if ((quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { | 340 | if ((drv_data->quirks & LG_INVERT_HWHEEL) && usage->code == REL_HWHEEL) { |
| 341 | input_event(field->hidinput->input, usage->type, usage->code, | 341 | input_event(field->hidinput->input, usage->type, usage->code, |
| 342 | -value); | 342 | -value); |
| 343 | return 1; | 343 | return 1; |
| @@ -348,13 +348,20 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field, | |||
| 348 | 348 | ||
| 349 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | 349 | static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 350 | { | 350 | { |
| 351 | unsigned long quirks = id->driver_data; | ||
| 352 | unsigned int connect_mask = HID_CONNECT_DEFAULT; | 351 | unsigned int connect_mask = HID_CONNECT_DEFAULT; |
| 352 | struct lg_drv_data *drv_data; | ||
| 353 | int ret; | 353 | int ret; |
| 354 | 354 | ||
| 355 | hid_set_drvdata(hdev, (void *)quirks); | 355 | drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL); |
| 356 | if (!drv_data) { | ||
| 357 | hid_err(hdev, "Insufficient memory, cannot allocate driver data\n"); | ||
| 358 | return -ENOMEM; | ||
| 359 | } | ||
| 360 | drv_data->quirks = id->driver_data; | ||
| 361 | |||
| 362 | hid_set_drvdata(hdev, (void *)drv_data); | ||
| 356 | 363 | ||
| 357 | if (quirks & LG_NOGET) | 364 | if (drv_data->quirks & LG_NOGET) |
| 358 | hdev->quirks |= HID_QUIRK_NOGET; | 365 | hdev->quirks |= HID_QUIRK_NOGET; |
| 359 | 366 | ||
| 360 | ret = hid_parse(hdev); | 367 | ret = hid_parse(hdev); |
| @@ -363,7 +370,7 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 363 | goto err_free; | 370 | goto err_free; |
| 364 | } | 371 | } |
| 365 | 372 | ||
| 366 | if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) | 373 | if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4)) |
| 367 | connect_mask &= ~HID_CONNECT_FF; | 374 | connect_mask &= ~HID_CONNECT_FF; |
| 368 | 375 | ||
| 369 | ret = hid_hw_start(hdev, connect_mask); | 376 | ret = hid_hw_start(hdev, connect_mask); |
| @@ -392,27 +399,29 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 392 | } | 399 | } |
| 393 | } | 400 | } |
| 394 | 401 | ||
| 395 | if (quirks & LG_FF) | 402 | if (drv_data->quirks & LG_FF) |
| 396 | lgff_init(hdev); | 403 | lgff_init(hdev); |
| 397 | if (quirks & LG_FF2) | 404 | if (drv_data->quirks & LG_FF2) |
| 398 | lg2ff_init(hdev); | 405 | lg2ff_init(hdev); |
| 399 | if (quirks & LG_FF3) | 406 | if (drv_data->quirks & LG_FF3) |
| 400 | lg3ff_init(hdev); | 407 | lg3ff_init(hdev); |
| 401 | if (quirks & LG_FF4) | 408 | if (drv_data->quirks & LG_FF4) |
| 402 | lg4ff_init(hdev); | 409 | lg4ff_init(hdev); |
| 403 | 410 | ||
| 404 | return 0; | 411 | return 0; |
| 405 | err_free: | 412 | err_free: |
| 413 | kfree(drv_data); | ||
| 406 | return ret; | 414 | return ret; |
| 407 | } | 415 | } |
| 408 | 416 | ||
| 409 | static void lg_remove(struct hid_device *hdev) | 417 | static void lg_remove(struct hid_device *hdev) |
| 410 | { | 418 | { |
| 411 | unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); | 419 | struct lg_drv_data *drv_data = (struct lg_drv_data *)hid_get_drvdata(hdev); |
| 412 | if(quirks & LG_FF4) | 420 | if (drv_data->quirks & LG_FF4) |
| 413 | lg4ff_deinit(hdev); | 421 | lg4ff_deinit(hdev); |
| 414 | 422 | ||
| 415 | hid_hw_stop(hdev); | 423 | hid_hw_stop(hdev); |
| 424 | kfree(drv_data); | ||
| 416 | } | 425 | } |
| 417 | 426 | ||
| 418 | static const struct hid_device_id lg_devices[] = { | 427 | static const struct hid_device_id lg_devices[] = { |
diff --git a/drivers/hid/hid-lg.h b/drivers/hid/hid-lg.h index 4b097286dc78..500457b67b21 100644 --- a/drivers/hid/hid-lg.h +++ b/drivers/hid/hid-lg.h | |||
| @@ -1,6 +1,13 @@ | |||
| 1 | #ifndef __HID_LG_H | 1 | #ifndef __HID_LG_H |
| 2 | #define __HID_LG_H | 2 | #define __HID_LG_H |
| 3 | 3 | ||
| 4 | #include <linux/spinlock.h> | ||
| 5 | |||
| 6 | struct lg_drv_data { | ||
| 7 | unsigned long quirks; | ||
| 8 | void *device_props; /* Device specific properties */ | ||
| 9 | }; | ||
| 10 | |||
| 4 | #ifdef CONFIG_LOGITECH_FF | 11 | #ifdef CONFIG_LOGITECH_FF |
| 5 | int lgff_init(struct hid_device *hdev); | 12 | int lgff_init(struct hid_device *hdev); |
| 6 | #else | 13 | #else |
