aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-lg.c
diff options
context:
space:
mode:
authorMichal Malý <madcatxster@gmail.com>2012-03-31 05:17:25 -0400
committerJiri Kosina <jkosina@suse.cz>2012-04-02 22:09:50 -0400
commit8577dbf9d6eb07213caefb49e2017c177c5f023d (patch)
tree2c22ad4bad6a927220f76ab157b65d902deb8288 /drivers/hid/hid-lg.c
parentd464c92b5234227c1698862a1906827e2e398ae0 (diff)
HID: hid-lg: Allow for custom device-specific properties to be stored in priv drvdata
This patch adds support for custom device-specific properties which can now be stored as private driver data and read/saved using hid_get/set_drvdata(). Signed-off-by: Michal Malý <madcatxster@gmail.com> Tested-by: simon@mungewell.org Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-lg.c')
-rw-r--r--drivers/hid/hid-lg.c55
1 files changed, 32 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[] = {
109static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, 109static __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,
335static int lg_event(struct hid_device *hdev, struct hid_field *field, 335static 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
349static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) 349static 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;
405err_free: 412err_free:
413 kfree(drv_data);
406 return ret; 414 return ret;
407} 415}
408 416
409static void lg_remove(struct hid_device *hdev) 417static 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
418static const struct hid_device_id lg_devices[] = { 427static const struct hid_device_id lg_devices[] = {