diff options
| -rw-r--r-- | Documentation/input/multi-touch-protocol.rst | 9 | ||||
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 52 | ||||
| -rw-r--r-- | include/linux/hid.h | 1 |
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 | ||
| 87 | struct mt_slot { | 87 | struct 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 | ||
| 95 | struct mt_class { | 96 | struct 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 |
