diff options
| author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2013-03-22 13:38:32 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2013-03-27 09:02:46 -0400 |
| commit | fa11aa72bd3c72d8129f433aaf6e1af7dd11fa3d (patch) | |
| tree | bdfbcfa0490dff188dacab12ebfce90da963d301 | |
| parent | 5b6498a1c89be9f3a545ab163e33e5abf45493e9 (diff) | |
HID: multitouch: add handling for pen in dual-sensors device
Dual sensors devices reports pen and touch on two different reports.
Using the quirk HID_QUIRK_MULTI_INPUT allows us to create a new input
device to forward pen events.
The quirk HID_QUIRK_NO_EMPTY_INPUT avoids the creation of input devices
for the not used mouse emulation present on Win7 certified devices.
Since hid-multitouch sets the quirk HID_QUIRK_NO_INPUT_SYNC, we need
to manually send SYN events for pen report too.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 66 |
1 files changed, 62 insertions, 4 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 6a934dee1b82..099a7ada13c7 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -99,6 +99,7 @@ struct mt_device { | |||
| 99 | int cc_value_index; /* contact count value index in the field */ | 99 | int cc_value_index; /* contact count value index in the field */ |
| 100 | unsigned last_slot_field; /* the last field of a slot */ | 100 | unsigned last_slot_field; /* the last field of a slot */ |
| 101 | unsigned mt_report_id; /* the report ID of the multitouch device */ | 101 | unsigned mt_report_id; /* the report ID of the multitouch device */ |
| 102 | unsigned pen_report_id; /* the report ID of the pen device */ | ||
| 102 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ | 103 | __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ |
| 103 | __s8 inputmode_index; /* InputMode HID feature index in the report */ | 104 | __s8 inputmode_index; /* InputMode HID feature index in the report */ |
| 104 | __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, | 105 | __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, |
| @@ -367,6 +368,43 @@ static void mt_store_field(struct hid_usage *usage, struct mt_device *td, | |||
| 367 | f->usages[f->length++] = usage->hid; | 368 | f->usages[f->length++] = usage->hid; |
| 368 | } | 369 | } |
| 369 | 370 | ||
| 371 | static int mt_pen_input_mapping(struct hid_device *hdev, struct hid_input *hi, | ||
| 372 | struct hid_field *field, struct hid_usage *usage, | ||
| 373 | unsigned long **bit, int *max) | ||
| 374 | { | ||
| 375 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 376 | |||
| 377 | td->pen_report_id = field->report->id; | ||
| 378 | |||
| 379 | return 0; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int mt_pen_input_mapped(struct hid_device *hdev, struct hid_input *hi, | ||
| 383 | struct hid_field *field, struct hid_usage *usage, | ||
| 384 | unsigned long **bit, int *max) | ||
| 385 | { | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static int mt_pen_event(struct hid_device *hid, struct hid_field *field, | ||
| 390 | struct hid_usage *usage, __s32 value) | ||
| 391 | { | ||
| 392 | /* let hid-input handle it */ | ||
| 393 | return 0; | ||
| 394 | } | ||
| 395 | |||
| 396 | static void mt_pen_report(struct hid_device *hid, struct hid_report *report) | ||
| 397 | { | ||
| 398 | struct hid_field *field = report->field[0]; | ||
| 399 | |||
| 400 | input_sync(field->hidinput->input); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void mt_pen_input_configured(struct hid_device *hdev, | ||
| 404 | struct hid_input *hi) | ||
| 405 | { | ||
| 406 | } | ||
| 407 | |||
| 370 | static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | 408 | static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, |
| 371 | struct hid_field *field, struct hid_usage *usage, | 409 | struct hid_field *field, struct hid_usage *usage, |
| 372 | unsigned long **bit, int *max) | 410 | unsigned long **bit, int *max) |
| @@ -740,14 +778,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 740 | * We need to ignore fields that belong to other collections | 778 | * We need to ignore fields that belong to other collections |
| 741 | * such as Mouse that might have the same GenericDesktop usages. */ | 779 | * such as Mouse that might have the same GenericDesktop usages. */ |
| 742 | if (field->application != HID_DG_TOUCHSCREEN && | 780 | if (field->application != HID_DG_TOUCHSCREEN && |
| 781 | field->application != HID_DG_PEN && | ||
| 743 | field->application != HID_DG_TOUCHPAD) | 782 | field->application != HID_DG_TOUCHPAD) |
| 744 | return -1; | 783 | return -1; |
| 745 | 784 | ||
| 746 | /* eGalax devices provide a Digitizer.Stylus input which overrides | ||
| 747 | * the correct Digitizers.Finger X/Y ranges. | ||
| 748 | * Let's just ignore this input. */ | ||
| 749 | if (field->physical == HID_DG_STYLUS) | 785 | if (field->physical == HID_DG_STYLUS) |
| 750 | return -1; | 786 | return mt_pen_input_mapping(hdev, hi, field, usage, bit, max); |
| 751 | 787 | ||
| 752 | return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); | 788 | return mt_touch_input_mapping(hdev, hi, field, usage, bit, max); |
| 753 | } | 789 | } |
| @@ -756,6 +792,9 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi, | |||
| 756 | struct hid_field *field, struct hid_usage *usage, | 792 | struct hid_field *field, struct hid_usage *usage, |
| 757 | unsigned long **bit, int *max) | 793 | unsigned long **bit, int *max) |
| 758 | { | 794 | { |
| 795 | if (field->physical == HID_DG_STYLUS) | ||
| 796 | return mt_pen_input_mapped(hdev, hi, field, usage, bit, max); | ||
| 797 | |||
| 759 | return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); | 798 | return mt_touch_input_mapped(hdev, hi, field, usage, bit, max); |
| 760 | } | 799 | } |
| 761 | 800 | ||
| @@ -767,6 +806,9 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
| 767 | if (field->report->id == td->mt_report_id) | 806 | if (field->report->id == td->mt_report_id) |
| 768 | return mt_touch_event(hid, field, usage, value); | 807 | return mt_touch_event(hid, field, usage, value); |
| 769 | 808 | ||
| 809 | if (field->report->id == td->pen_report_id) | ||
| 810 | return mt_pen_event(hid, field, usage, value); | ||
| 811 | |||
| 770 | /* ignore other reports */ | 812 | /* ignore other reports */ |
| 771 | return 1; | 813 | return 1; |
| 772 | } | 814 | } |
| @@ -780,6 +822,9 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) | |||
| 780 | 822 | ||
| 781 | if (report->id == td->mt_report_id) | 823 | if (report->id == td->mt_report_id) |
| 782 | mt_touch_report(hid, report); | 824 | mt_touch_report(hid, report); |
| 825 | |||
| 826 | if (report->id == td->pen_report_id) | ||
| 827 | mt_pen_report(hid, report); | ||
| 783 | } | 828 | } |
| 784 | 829 | ||
| 785 | static void mt_set_input_mode(struct hid_device *hdev) | 830 | static void mt_set_input_mode(struct hid_device *hdev) |
| @@ -861,6 +906,9 @@ static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 861 | 906 | ||
| 862 | if (hi->report->id == td->mt_report_id) | 907 | if (hi->report->id == td->mt_report_id) |
| 863 | mt_touch_input_configured(hdev, hi); | 908 | mt_touch_input_configured(hdev, hi); |
| 909 | |||
| 910 | if (hi->report->id == td->pen_report_id) | ||
| 911 | mt_pen_input_configured(hdev, hi); | ||
| 864 | } | 912 | } |
| 865 | 913 | ||
| 866 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | 914 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) |
| @@ -881,6 +929,14 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 881 | */ | 929 | */ |
| 882 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; | 930 | hdev->quirks |= HID_QUIRK_NO_INPUT_SYNC; |
| 883 | 931 | ||
| 932 | /* | ||
| 933 | * This allows the driver to handle different input sensors | ||
| 934 | * that emits events through different reports on the same HID | ||
| 935 | * device. | ||
| 936 | */ | ||
| 937 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | ||
| 938 | hdev->quirks |= HID_QUIRK_NO_EMPTY_INPUT; | ||
| 939 | |||
| 884 | td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); | 940 | td = kzalloc(sizeof(struct mt_device), GFP_KERNEL); |
| 885 | if (!td) { | 941 | if (!td) { |
| 886 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); | 942 | dev_err(&hdev->dev, "cannot allocate multitouch data\n"); |
| @@ -890,6 +946,8 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 890 | td->inputmode = -1; | 946 | td->inputmode = -1; |
| 891 | td->maxcontact_report_id = -1; | 947 | td->maxcontact_report_id = -1; |
| 892 | td->cc_index = -1; | 948 | td->cc_index = -1; |
| 949 | td->mt_report_id = -1; | ||
| 950 | td->pen_report_id = -1; | ||
| 893 | hid_set_drvdata(hdev, td); | 951 | hid_set_drvdata(hdev, td); |
| 894 | 952 | ||
| 895 | td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); | 953 | td->fields = kzalloc(sizeof(struct mt_fields), GFP_KERNEL); |
