aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>2013-03-22 13:38:32 -0400
committerJiri Kosina <jkosina@suse.cz>2013-03-27 09:02:46 -0400
commitfa11aa72bd3c72d8129f433aaf6e1af7dd11fa3d (patch)
treebdfbcfa0490dff188dacab12ebfce90da963d301 /drivers/hid
parent5b6498a1c89be9f3a545ab163e33e5abf45493e9 (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.c66
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
371static 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
382static 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
389static 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
396static 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
403static void mt_pen_input_configured(struct hid_device *hdev,
404 struct hid_input *hi)
405{
406}
407
370static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, 408static 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
785static void mt_set_input_mode(struct hid_device *hdev) 830static 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
866static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) 914static 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);