diff options
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 25b94253e68f..6e3332a99976 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -70,9 +70,16 @@ struct mt_class { | |||
| 70 | bool is_indirect; /* true for touchpads */ | 70 | bool is_indirect; /* true for touchpads */ |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | struct mt_fields { | ||
| 74 | unsigned usages[HID_MAX_FIELDS]; | ||
| 75 | unsigned int length; | ||
| 76 | }; | ||
| 77 | |||
| 73 | struct mt_device { | 78 | struct mt_device { |
| 74 | struct mt_slot curdata; /* placeholder of incoming data */ | 79 | struct mt_slot curdata; /* placeholder of incoming data */ |
| 75 | struct mt_class mtclass; /* our mt device class */ | 80 | struct mt_class mtclass; /* our mt device class */ |
| 81 | struct mt_fields *fields; /* temporary placeholder for storing the | ||
| 82 | multitouch fields */ | ||
| 76 | unsigned last_field_index; /* last field index of the report */ | 83 | unsigned last_field_index; /* last field index of the report */ |
| 77 | unsigned last_slot_field; /* the last field of a slot */ | 84 | unsigned last_slot_field; /* the last field of a slot */ |
| 78 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | 85 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| @@ -278,11 +285,15 @@ static void set_abs(struct input_dev *input, unsigned int code, | |||
| 278 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); | 285 | input_set_abs_params(input, code, fmin, fmax, fuzz, 0); |
| 279 | } | 286 | } |
| 280 | 287 | ||
| 281 | static void set_last_slot_field(struct hid_usage *usage, struct mt_device *td, | 288 | static void mt_store_field(struct hid_usage *usage, struct mt_device *td, |
| 282 | struct hid_input *hi) | 289 | struct hid_input *hi) |
| 283 | { | 290 | { |
| 284 | if (!test_bit(usage->hid, hi->input->absbit)) | 291 | struct mt_fields *f = td->fields; |
| 285 | td->last_slot_field = usage->hid; | 292 | |
| 293 | if (f->length >= HID_MAX_FIELDS) | ||
| 294 | return; | ||
| 295 | |||
| 296 | f->usages[f->length++] = usage->hid; | ||
| 286 | } | 297 | } |
| 287 | 298 | ||
| 288 | static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 299 | static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
| @@ -333,7 +344,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 333 | cls->sn_move); | 344 | cls->sn_move); |
| 334 | /* touchscreen emulation */ | 345 | /* touchscreen emulation */ |
| 335 | set_abs(hi->input, ABS_X, field, cls->sn_move); | 346 | set_abs(hi->input, ABS_X, field, cls->sn_move); |
| 336 | set_last_slot_field(usage, td, hi); | 347 | mt_store_field(usage, td, hi); |
| 337 | td->last_field_index = field->index; | 348 | td->last_field_index = field->index; |
| 338 | return 1; | 349 | return 1; |
| 339 | case HID_GD_Y: | 350 | case HID_GD_Y: |
| @@ -343,7 +354,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 343 | cls->sn_move); | 354 | cls->sn_move); |
| 344 | /* touchscreen emulation */ | 355 | /* touchscreen emulation */ |
| 345 | set_abs(hi->input, ABS_Y, field, cls->sn_move); | 356 | set_abs(hi->input, ABS_Y, field, cls->sn_move); |
| 346 | set_last_slot_field(usage, td, hi); | 357 | mt_store_field(usage, td, hi); |
| 347 | td->last_field_index = field->index; | 358 | td->last_field_index = field->index; |
| 348 | return 1; | 359 | return 1; |
| 349 | } | 360 | } |
| @@ -352,24 +363,24 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 352 | case HID_UP_DIGITIZER: | 363 | case HID_UP_DIGITIZER: |
| 353 | switch (usage->hid) { | 364 | switch (usage->hid) { |
| 354 | case HID_DG_INRANGE: | 365 | case HID_DG_INRANGE: |
| 355 | set_last_slot_field(usage, td, hi); | 366 | mt_store_field(usage, td, hi); |
| 356 | td->last_field_index = field->index; | 367 | td->last_field_index = field->index; |
| 357 | return 1; | 368 | return 1; |
| 358 | case HID_DG_CONFIDENCE: | 369 | case HID_DG_CONFIDENCE: |
| 359 | set_last_slot_field(usage, td, hi); | 370 | mt_store_field(usage, td, hi); |
| 360 | td->last_field_index = field->index; | 371 | td->last_field_index = field->index; |
| 361 | return 1; | 372 | return 1; |
| 362 | case HID_DG_TIPSWITCH: | 373 | case HID_DG_TIPSWITCH: |
| 363 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); | 374 | hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); |
| 364 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); | 375 | input_set_capability(hi->input, EV_KEY, BTN_TOUCH); |
| 365 | set_last_slot_field(usage, td, hi); | 376 | mt_store_field(usage, td, hi); |
| 366 | td->last_field_index = field->index; | 377 | td->last_field_index = field->index; |
| 367 | return 1; | 378 | return 1; |
| 368 | case HID_DG_CONTACTID: | 379 | case HID_DG_CONTACTID: |
| 369 | if (!td->maxcontacts) | 380 | if (!td->maxcontacts) |
| 370 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | 381 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; |
| 371 | input_mt_init_slots(hi->input, td->maxcontacts); | 382 | input_mt_init_slots(hi->input, td->maxcontacts); |
| 372 | td->last_slot_field = usage->hid; | 383 | mt_store_field(usage, td, hi); |
| 373 | td->last_field_index = field->index; | 384 | td->last_field_index = field->index; |
| 374 | td->touches_by_report++; | 385 | td->touches_by_report++; |
| 375 | return 1; | 386 | return 1; |
| @@ -378,7 +389,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 378 | EV_ABS, ABS_MT_TOUCH_MAJOR); | 389 | EV_ABS, ABS_MT_TOUCH_MAJOR); |
| 379 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, | 390 | set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, |
| 380 | cls->sn_width); | 391 | cls->sn_width); |
| 381 | set_last_slot_field(usage, td, hi); | 392 | mt_store_field(usage, td, hi); |
| 382 | td->last_field_index = field->index; | 393 | td->last_field_index = field->index; |
| 383 | return 1; | 394 | return 1; |
| 384 | case HID_DG_HEIGHT: | 395 | case HID_DG_HEIGHT: |
| @@ -388,7 +399,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 388 | cls->sn_height); | 399 | cls->sn_height); |
| 389 | input_set_abs_params(hi->input, | 400 | input_set_abs_params(hi->input, |
| 390 | ABS_MT_ORIENTATION, 0, 1, 0, 0); | 401 | ABS_MT_ORIENTATION, 0, 1, 0, 0); |
| 391 | set_last_slot_field(usage, td, hi); | 402 | mt_store_field(usage, td, hi); |
| 392 | td->last_field_index = field->index; | 403 | td->last_field_index = field->index; |
| 393 | return 1; | 404 | return 1; |
| 394 | case HID_DG_TIPPRESSURE: | 405 | case HID_DG_TIPPRESSURE: |
| @@ -399,7 +410,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 399 | /* touchscreen emulation */ | 410 | /* touchscreen emulation */ |
| 400 | set_abs(hi->input, ABS_PRESSURE, field, | 411 | set_abs(hi->input, ABS_PRESSURE, field, |
| 401 | cls->sn_pressure); | 412 | cls->sn_pressure); |
| 402 | set_last_slot_field(usage, td, hi); | 413 | mt_store_field(usage, td, hi); |
| 403 | td->last_field_index = field->index; | 414 | td->last_field_index = field->index; |
| 404 | return 1; | 415 | return 1; |
| 405 | case HID_DG_CONTACTCOUNT: | 416 | case HID_DG_CONTACTCOUNT: |
| @@ -653,6 +664,16 @@ static void mt_post_parse_default_settings(struct mt_device *td) | |||
| 653 | td->mtclass.quirks = quirks; | 664 | td->mtclass.quirks = quirks; |
| 654 | } | 665 | } |
| 655 | 666 | ||
| 667 | static void mt_post_parse(struct mt_device *td) | ||
| 668 | { | ||
| 669 | struct mt_fields *f = td->fields; | ||
| 670 | |||
| 671 | if (td->touches_by_report > 0) { | ||
| 672 | int field_count_per_touch = f->length / td->touches_by_report; | ||
| 673 | td->last_slot_field = f->usages[field_count_per_touch - 1]; | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 656 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | 677 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| 657 | { | 678 | { |
| 658 | int ret, i; | 679 | int ret, i; |
| @@ -683,6 +704,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 683 | td->maxcontact_report_id = -1; | 704 | td->maxcontact_report_id = -1; |
| 684 | hid_set_drvdata(hdev, td); | 705 | hid_set_drvdata(hdev, td); |
| 685 | 706 | ||
| 707 | td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); | ||
| 708 | if (!td->fields) { | ||
| 709 | dev_err(&hdev->dev, "cannot allocate multitouch fields data\n"); | ||
| 710 | ret = -ENOMEM; | ||
| 711 | goto fail; | ||
| 712 | } | ||
| 713 | |||
| 686 | ret = hid_parse(hdev); | 714 | ret = hid_parse(hdev); |
| 687 | if (ret != 0) | 715 | if (ret != 0) |
| 688 | goto fail; | 716 | goto fail; |
| @@ -691,6 +719,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 691 | if (ret) | 719 | if (ret) |
| 692 | goto fail; | 720 | goto fail; |
| 693 | 721 | ||
| 722 | mt_post_parse(td); | ||
| 723 | |||
| 694 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) | 724 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) |
| 695 | mt_post_parse_default_settings(td); | 725 | mt_post_parse_default_settings(td); |
| 696 | 726 | ||
| @@ -708,9 +738,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 708 | mt_set_maxcontacts(hdev); | 738 | mt_set_maxcontacts(hdev); |
| 709 | mt_set_input_mode(hdev); | 739 | mt_set_input_mode(hdev); |
| 710 | 740 | ||
| 741 | kfree(td->fields); | ||
| 742 | td->fields = NULL; | ||
| 743 | |||
| 711 | return 0; | 744 | return 0; |
| 712 | 745 | ||
| 713 | fail: | 746 | fail: |
| 747 | kfree(td->fields); | ||
| 714 | kfree(td); | 748 | kfree(td); |
| 715 | return ret; | 749 | return ret; |
| 716 | } | 750 | } |
