aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei-Ning Huang <wnhuang@chromium.org>2017-10-12 02:21:43 -0400
committerJiri Kosina <jkosina@suse.cz>2017-12-01 04:01:01 -0500
commit00720277a517e6dcc4773fb413711fe0131ee9bd (patch)
treeef9e7d02143daab51abe1d03fefd41238812fb6a
parent127e71bd462b87301f5ff1d1fd686515b4a4af9c (diff)
HID: hid-multitouch: support fine-grain orientation reporting
The current hid-multitouch driver only allow the report of two orientations, vertical and horizontal. We use the Azimuth orientation usage 0x3F under the Digitizer usage page to report orientation if the device supports it. Changelog: v1 -> v2: - Fix commit message. - Remove resolution reporting for ABS_MT_ORIENTATION. v2 -> v3: - Fix commit message. v3 -> v4: - Fix ABS_MT_ORIENTATION ABS param range. - Don't set ABS_MT_ORIENTATION in ABS_DG_HEIGHT when it is already set by ABS_DG_AZIMUTH. v4 -> v5: - Improve multi-touch-protocol.rst documentation. Signed-off-by: Wei-Ning Huang <wnhuang@chromium.org> Signed-off-by: Wei-Ning Huang <wnhuang@google.com> Reviewed-by: Dmitry Torokhov <dtor@chromium.org> Reviewed-by: Henrik Rydberg <rydberg@bitmath.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--Documentation/input/multi-touch-protocol.rst9
-rw-r--r--drivers/hid/hid-multitouch.c52
-rw-r--r--include/linux/hid.h1
3 files changed, 54 insertions, 8 deletions
diff --git a/Documentation/input/multi-touch-protocol.rst b/Documentation/input/multi-touch-protocol.rst
index 8035868c56bc..b51751a0cd5d 100644
--- a/Documentation/input/multi-touch-protocol.rst
+++ b/Documentation/input/multi-touch-protocol.rst
@@ -269,10 +269,11 @@ ABS_MT_ORIENTATION
269 The orientation of the touching ellipse. The value should describe a signed 269 The orientation of the touching ellipse. The value should describe a signed
270 quarter of a revolution clockwise around the touch center. The signed value 270 quarter of a revolution clockwise around the touch center. The signed value
271 range is arbitrary, but zero should be returned for an ellipse aligned with 271 range is arbitrary, but zero should be returned for an ellipse aligned with
272 the Y axis of the surface, a negative value when the ellipse is turned to 272 the Y axis (north) of the surface, a negative value when the ellipse is
273 the left, and a positive value when the ellipse is turned to the 273 turned to the left, and a positive value when the ellipse is turned to the
274 right. When completely aligned with the X axis, the range max should be 274 right. When aligned with the X axis in the positive direction, the range
275 returned. 275 max should be returned; when aligned with the X axis in the negative
276 direction, the range -max should be returned.
276 277
277 Touch ellipsis are symmetrical by default. For devices capable of true 360 278 Touch ellipsis are symmetrical by default. For devices capable of true 360
278 degree orientation, the reported orientation must exceed the range max to 279 degree orientation, the reported orientation must exceed the range max to
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 76088f2cf598..3b4739bde05d 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -85,11 +85,12 @@ MODULE_LICENSE("GPL");
85#define MT_IO_FLAGS_PENDING_SLOTS 2 85#define MT_IO_FLAGS_PENDING_SLOTS 2
86 86
87struct mt_slot { 87struct mt_slot {
88 __s32 x, y, cx, cy, p, w, h; 88 __s32 x, y, cx, cy, p, w, h, a;
89 __s32 contactid; /* the device ContactID assigned to this slot */ 89 __s32 contactid; /* the device ContactID assigned to this slot */
90 bool touch_state; /* is the touch valid? */ 90 bool touch_state; /* is the touch valid? */
91 bool inrange_state; /* is the finger in proximity of the sensor? */ 91 bool inrange_state; /* is the finger in proximity of the sensor? */
92 bool confidence_state; /* is the touch made by a finger? */ 92 bool confidence_state; /* is the touch made by a finger? */
93 bool has_azimuth; /* the contact reports azimuth */
93}; 94};
94 95
95struct mt_class { 96struct mt_class {
@@ -586,8 +587,15 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
586 if (!(cls->quirks & MT_QUIRK_NO_AREA)) { 587 if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
587 set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, 588 set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
588 cls->sn_height); 589 cls->sn_height);
589 input_set_abs_params(hi->input, 590
590 ABS_MT_ORIENTATION, 0, 1, 0, 0); 591 /*
592 * Only set ABS_MT_ORIENTATION if it is not
593 * already set by the HID_DG_AZIMUTH usage.
594 */
595 if (!test_bit(ABS_MT_ORIENTATION,
596 hi->input->absbit))
597 input_set_abs_params(hi->input,
598 ABS_MT_ORIENTATION, 0, 1, 0, 0);
591 } 599 }
592 mt_store_field(usage, td, hi); 600 mt_store_field(usage, td, hi);
593 return 1; 601 return 1;
@@ -618,6 +626,21 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
618 td->cc_index = field->index; 626 td->cc_index = field->index;
619 td->cc_value_index = usage->usage_index; 627 td->cc_value_index = usage->usage_index;
620 return 1; 628 return 1;
629 case HID_DG_AZIMUTH:
630 hid_map_usage(hi, usage, bit, max,
631 EV_ABS, ABS_MT_ORIENTATION);
632 /*
633 * Azimuth has the range of [0, MAX) representing a full
634 * revolution. Set ABS_MT_ORIENTATION to a quarter of
635 * MAX according the definition of ABS_MT_ORIENTATION
636 */
637 input_set_abs_params(hi->input, ABS_MT_ORIENTATION,
638 -field->logical_maximum / 4,
639 field->logical_maximum / 4,
640 cls->sn_move ?
641 field->logical_maximum / cls->sn_move : 0, 0);
642 mt_store_field(usage, td, hi);
643 return 1;
621 case HID_DG_CONTACTMAX: 644 case HID_DG_CONTACTMAX:
622 /* we don't set td->last_slot_field as contactcount and 645 /* we don't set td->last_slot_field as contactcount and
623 * contact max are global to the report */ 646 * contact max are global to the report */
@@ -710,6 +733,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
710 int wide = (s->w > s->h); 733 int wide = (s->w > s->h);
711 int major = max(s->w, s->h); 734 int major = max(s->w, s->h);
712 int minor = min(s->w, s->h); 735 int minor = min(s->w, s->h);
736 int orientation = wide;
737
738 if (s->has_azimuth)
739 orientation = s->a;
713 740
714 /* 741 /*
715 * divided by two to match visual scale of touch 742 * divided by two to match visual scale of touch
@@ -726,7 +753,8 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
726 input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy); 753 input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
727 input_event(input, EV_ABS, ABS_MT_DISTANCE, 754 input_event(input, EV_ABS, ABS_MT_DISTANCE,
728 !s->touch_state); 755 !s->touch_state);
729 input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); 756 input_event(input, EV_ABS, ABS_MT_ORIENTATION,
757 orientation);
730 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p); 758 input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
731 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); 759 input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
732 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); 760 input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor);
@@ -850,6 +878,22 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
850 break; 878 break;
851 case HID_DG_CONTACTCOUNT: 879 case HID_DG_CONTACTCOUNT:
852 break; 880 break;
881 case HID_DG_AZIMUTH:
882 /*
883 * Azimuth is counter-clockwise and ranges from [0, MAX)
884 * (a full revolution). Convert it to clockwise ranging
885 * [-MAX/2, MAX/2].
886 *
887 * Note that ABS_MT_ORIENTATION require us to report
888 * the limit of [-MAX/4, MAX/4], but the value can go
889 * out of range to [-MAX/2, MAX/2] to report an upside
890 * down ellipsis.
891 */
892 if (value > field->logical_maximum / 2)
893 value -= field->logical_maximum;
894 td->curdata.a = -value;
895 td->curdata.has_azimuth = true;
896 break;
853 case HID_DG_TOUCH: 897 case HID_DG_TOUCH:
854 /* do nothing */ 898 /* do nothing */
855 break; 899 break;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 39cdeb205caa..091a81cf330f 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -281,6 +281,7 @@ struct hid_item {
281 281
282#define HID_DG_DEVICECONFIG 0x000d000e 282#define HID_DG_DEVICECONFIG 0x000d000e
283#define HID_DG_DEVICESETTINGS 0x000d0023 283#define HID_DG_DEVICESETTINGS 0x000d0023
284#define HID_DG_AZIMUTH 0x000d003f
284#define HID_DG_CONFIDENCE 0x000d0047 285#define HID_DG_CONFIDENCE 0x000d0047
285#define HID_DG_WIDTH 0x000d0048 286#define HID_DG_WIDTH 0x000d0048
286#define HID_DG_HEIGHT 0x000d0049 287#define HID_DG_HEIGHT 0x000d0049