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 /drivers/hid | |
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>
Diffstat (limited to 'drivers/hid')
-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); |