diff options
author | Nicolas Boichat <drinkcat@chromium.org> | 2017-08-21 21:10:11 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-10-05 05:18:18 -0400 |
commit | 29cc309d8bf19a36c5196bf626662319af6e3c0b (patch) | |
tree | 7cda1e048d81ab5cb01ce761d7fec4f6a7020ec9 | |
parent | b42a362e6d10c342004b183defcb9940331b6737 (diff) |
HID: hid-multitouch: forward MSC_TIMESTAMP
Computes and forwards the device timestamp according to the specification.
Many devices use a 16-bit timestamp field, with a resolution of 100us,
therefore rolling around very frequently (every 6.5 seconds). To make sure
there is no ambiguity, the timestamp reported to the input stack reset to
0 whenever the time between 2 received events is greater than
MAX_TIMESTAMP_INTERVAL (1 second).
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-multitouch.c | 42 | ||||
-rw-r--r-- | include/linux/hid.h | 1 |
2 files changed, 43 insertions, 0 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 440b999304a5..996bdc9bf0e5 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/input/mt.h> | 45 | #include <linux/input/mt.h> |
46 | #include <linux/jiffies.h> | ||
46 | #include <linux/string.h> | 47 | #include <linux/string.h> |
47 | #include <linux/timer.h> | 48 | #include <linux/timer.h> |
48 | 49 | ||
@@ -136,6 +137,9 @@ struct mt_device { | |||
136 | bool serial_maybe; /* need to check for serial protocol */ | 137 | bool serial_maybe; /* need to check for serial protocol */ |
137 | bool curvalid; /* is the current contact valid? */ | 138 | bool curvalid; /* is the current contact valid? */ |
138 | unsigned mt_flags; /* flags to pass to input-mt */ | 139 | unsigned mt_flags; /* flags to pass to input-mt */ |
140 | __s32 dev_time; /* the scan time provided by the device */ | ||
141 | unsigned long jiffies; /* the frame's jiffies */ | ||
142 | int timestamp; /* the timestamp to be sent */ | ||
139 | }; | 143 | }; |
140 | 144 | ||
141 | static void mt_post_parse_default_settings(struct mt_device *td); | 145 | static void mt_post_parse_default_settings(struct mt_device *td); |
@@ -177,6 +181,12 @@ static void mt_post_parse(struct mt_device *td); | |||
177 | #define MT_DEFAULT_MAXCONTACT 10 | 181 | #define MT_DEFAULT_MAXCONTACT 10 |
178 | #define MT_MAX_MAXCONTACT 250 | 182 | #define MT_MAX_MAXCONTACT 250 |
179 | 183 | ||
184 | /* | ||
185 | * Resync device and local timestamps after that many microseconds without | ||
186 | * receiving data. | ||
187 | */ | ||
188 | #define MAX_TIMESTAMP_INTERVAL 1000000 | ||
189 | |||
180 | #define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p) | 190 | #define MT_USB_DEVICE(v, p) HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH, v, p) |
181 | #define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p) | 191 | #define MT_BT_DEVICE(v, p) HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH, v, p) |
182 | 192 | ||
@@ -583,6 +593,12 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
583 | cls->sn_pressure); | 593 | cls->sn_pressure); |
584 | mt_store_field(usage, td, hi); | 594 | mt_store_field(usage, td, hi); |
585 | return 1; | 595 | return 1; |
596 | case HID_DG_SCANTIME: | ||
597 | hid_map_usage(hi, usage, bit, max, | ||
598 | EV_MSC, MSC_TIMESTAMP); | ||
599 | input_set_capability(hi->input, EV_MSC, MSC_TIMESTAMP); | ||
600 | mt_store_field(usage, td, hi); | ||
601 | return 1; | ||
586 | case HID_DG_CONTACTCOUNT: | 602 | case HID_DG_CONTACTCOUNT: |
587 | /* Ignore if indexes are out of bounds. */ | 603 | /* Ignore if indexes are out of bounds. */ |
588 | if (field->index >= field->report->maxfield || | 604 | if (field->index >= field->report->maxfield || |
@@ -718,6 +734,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input) | |||
718 | static void mt_sync_frame(struct mt_device *td, struct input_dev *input) | 734 | static void mt_sync_frame(struct mt_device *td, struct input_dev *input) |
719 | { | 735 | { |
720 | input_mt_sync_frame(input); | 736 | input_mt_sync_frame(input); |
737 | input_event(input, EV_MSC, MSC_TIMESTAMP, td->timestamp); | ||
721 | input_sync(input); | 738 | input_sync(input); |
722 | td->num_received = 0; | 739 | td->num_received = 0; |
723 | if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) | 740 | if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) |
@@ -727,6 +744,28 @@ static void mt_sync_frame(struct mt_device *td, struct input_dev *input) | |||
727 | clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags); | 744 | clear_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags); |
728 | } | 745 | } |
729 | 746 | ||
747 | static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field, | ||
748 | __s32 value) | ||
749 | { | ||
750 | long delta = value - td->dev_time; | ||
751 | unsigned long jdelta = jiffies_to_usecs(jiffies - td->jiffies); | ||
752 | |||
753 | td->jiffies = jiffies; | ||
754 | td->dev_time = value; | ||
755 | |||
756 | if (delta < 0) | ||
757 | delta += field->logical_maximum; | ||
758 | |||
759 | /* HID_DG_SCANTIME is expressed in 100us, we want it in us. */ | ||
760 | delta *= 100; | ||
761 | |||
762 | if (jdelta > MAX_TIMESTAMP_INTERVAL) | ||
763 | /* No data received for a while, resync the timestamp. */ | ||
764 | return 0; | ||
765 | else | ||
766 | return td->timestamp + delta; | ||
767 | } | ||
768 | |||
730 | static int mt_touch_event(struct hid_device *hid, struct hid_field *field, | 769 | static int mt_touch_event(struct hid_device *hid, struct hid_field *field, |
731 | struct hid_usage *usage, __s32 value) | 770 | struct hid_usage *usage, __s32 value) |
732 | { | 771 | { |
@@ -787,6 +826,9 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | |||
787 | case HID_DG_HEIGHT: | 826 | case HID_DG_HEIGHT: |
788 | td->curdata.h = value; | 827 | td->curdata.h = value; |
789 | break; | 828 | break; |
829 | case HID_DG_SCANTIME: | ||
830 | td->timestamp = mt_compute_timestamp(td, field, value); | ||
831 | break; | ||
790 | case HID_DG_CONTACTCOUNT: | 832 | case HID_DG_CONTACTCOUNT: |
791 | break; | 833 | break; |
792 | case HID_DG_TOUCH: | 834 | case HID_DG_TOUCH: |
diff --git a/include/linux/hid.h b/include/linux/hid.h index ab05a86269dc..47dd962d9a7a 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -289,6 +289,7 @@ struct hid_item { | |||
289 | #define HID_DG_DEVICEINDEX 0x000d0053 | 289 | #define HID_DG_DEVICEINDEX 0x000d0053 |
290 | #define HID_DG_CONTACTCOUNT 0x000d0054 | 290 | #define HID_DG_CONTACTCOUNT 0x000d0054 |
291 | #define HID_DG_CONTACTMAX 0x000d0055 | 291 | #define HID_DG_CONTACTMAX 0x000d0055 |
292 | #define HID_DG_SCANTIME 0x000d0056 | ||
292 | #define HID_DG_BUTTONTYPE 0x000d0059 | 293 | #define HID_DG_BUTTONTYPE 0x000d0059 |
293 | #define HID_DG_BARRELSWITCH2 0x000d005a | 294 | #define HID_DG_BARRELSWITCH2 0x000d005a |
294 | #define HID_DG_TOOLSERIALNUMBER 0x000d005b | 295 | #define HID_DG_TOOLSERIALNUMBER 0x000d005b |