Skip to content

Commit 0072027

Browse files
Wei-Ning HuangJiri Kosina
authored andcommitted
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 <[email protected]> Signed-off-by: Wei-Ning Huang <[email protected]> Reviewed-by: Dmitry Torokhov <[email protected]> Reviewed-by: Henrik Rydberg <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 127e71b commit 0072027

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

Documentation/input/multi-touch-protocol.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,11 @@ ABS_MT_ORIENTATION
269269
The orientation of the touching ellipse. The value should describe a signed
270270
quarter of a revolution clockwise around the touch center. The signed value
271271
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
273-
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
275-
returned.
272+
the Y axis (north) of the surface, a negative value when the ellipse is
273+
turned to the left, and a positive value when the ellipse is turned to the
274+
right. When aligned with the X axis in the positive direction, the range
275+
max should be returned; when aligned with the X axis in the negative
276+
direction, the range -max should be returned.
276277

277278
Touch ellipsis are symmetrical by default. For devices capable of true 360
278279
degree orientation, the reported orientation must exceed the range max to

drivers/hid/hid-multitouch.c

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,12 @@ MODULE_LICENSE("GPL");
8585
#define MT_IO_FLAGS_PENDING_SLOTS 2
8686

8787
struct mt_slot {
88-
__s32 x, y, cx, cy, p, w, h;
88+
__s32 x, y, cx, cy, p, w, h, a;
8989
__s32 contactid; /* the device ContactID assigned to this slot */
9090
bool touch_state; /* is the touch valid? */
9191
bool inrange_state; /* is the finger in proximity of the sensor? */
9292
bool confidence_state; /* is the touch made by a finger? */
93+
bool has_azimuth; /* the contact reports azimuth */
9394
};
9495

9596
struct mt_class {
@@ -586,8 +587,15 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
586587
if (!(cls->quirks & MT_QUIRK_NO_AREA)) {
587588
set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
588589
cls->sn_height);
589-
input_set_abs_params(hi->input,
590-
ABS_MT_ORIENTATION, 0, 1, 0, 0);
590+
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);
591599
}
592600
mt_store_field(usage, td, hi);
593601
return 1;
@@ -618,6 +626,21 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
618626
td->cc_index = field->index;
619627
td->cc_value_index = usage->usage_index;
620628
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;
621644
case HID_DG_CONTACTMAX:
622645
/* we don't set td->last_slot_field as contactcount and
623646
* contact max are global to the report */
@@ -710,6 +733,10 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
710733
int wide = (s->w > s->h);
711734
int major = max(s->w, s->h);
712735
int minor = min(s->w, s->h);
736+
int orientation = wide;
737+
738+
if (s->has_azimuth)
739+
orientation = s->a;
713740

714741
/*
715742
* 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)
726753
input_event(input, EV_ABS, ABS_MT_TOOL_Y, s->cy);
727754
input_event(input, EV_ABS, ABS_MT_DISTANCE,
728755
!s->touch_state);
729-
input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide);
756+
input_event(input, EV_ABS, ABS_MT_ORIENTATION,
757+
orientation);
730758
input_event(input, EV_ABS, ABS_MT_PRESSURE, s->p);
731759
input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major);
732760
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,
850878
break;
851879
case HID_DG_CONTACTCOUNT:
852880
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;
853897
case HID_DG_TOUCH:
854898
/* do nothing */
855899
break;

include/linux/hid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ struct hid_item {
281281

282282
#define HID_DG_DEVICECONFIG 0x000d000e
283283
#define HID_DG_DEVICESETTINGS 0x000d0023
284+
#define HID_DG_AZIMUTH 0x000d003f
284285
#define HID_DG_CONFIDENCE 0x000d0047
285286
#define HID_DG_WIDTH 0x000d0048
286287
#define HID_DG_HEIGHT 0x000d0049

0 commit comments

Comments
 (0)