diff options
author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2018-04-24 04:04:37 -0400 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2018-04-26 08:17:55 -0400 |
commit | 02946f4b43b11026b1a76857a33b09078b900939 (patch) | |
tree | 30c29479630913323655eacd359a53de78094b78 | |
parent | 7f81c8db54898a793cc2916a936f6bf3fca41434 (diff) |
HID: multitouch: implement precision touchpad latency and switches
The Win 8.1 precision touchpad spec introduce new modes for touchpads
that can come in handy[1].
Implement the settings of these modes, so we are not taken off-guard if
a firmware decides to enforce them.
[1] https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/windows-precision-touchpad-required-hid-top-level-collections
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | drivers/hid/hid-multitouch.c | 34 | ||||
-rw-r--r-- | include/linux/hid.h | 3 |
2 files changed, 32 insertions, 5 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 8878de9eedba..82c98bf14d60 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -81,6 +81,11 @@ MODULE_LICENSE("GPL"); | |||
81 | 81 | ||
82 | #define MT_BUTTONTYPE_CLICKPAD 0 | 82 | #define MT_BUTTONTYPE_CLICKPAD 0 |
83 | 83 | ||
84 | enum latency_mode { | ||
85 | HID_LATENCY_NORMAL = 0, | ||
86 | HID_LATENCY_HIGH = 1, | ||
87 | }; | ||
88 | |||
84 | #define MT_IO_FLAGS_RUNNING 0 | 89 | #define MT_IO_FLAGS_RUNNING 0 |
85 | #define MT_IO_FLAGS_ACTIVE_SLOTS 1 | 90 | #define MT_IO_FLAGS_ACTIVE_SLOTS 1 |
86 | #define MT_IO_FLAGS_PENDING_SLOTS 2 | 91 | #define MT_IO_FLAGS_PENDING_SLOTS 2 |
@@ -1156,7 +1161,10 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) | |||
1156 | 1161 | ||
1157 | static bool mt_need_to_apply_feature(struct hid_device *hdev, | 1162 | static bool mt_need_to_apply_feature(struct hid_device *hdev, |
1158 | struct hid_field *field, | 1163 | struct hid_field *field, |
1159 | struct hid_usage *usage) | 1164 | struct hid_usage *usage, |
1165 | enum latency_mode latency, | ||
1166 | bool surface_switch, | ||
1167 | bool button_switch) | ||
1160 | { | 1168 | { |
1161 | struct mt_device *td = hid_get_drvdata(hdev); | 1169 | struct mt_device *td = hid_get_drvdata(hdev); |
1162 | struct mt_class *cls = &td->mtclass; | 1170 | struct mt_class *cls = &td->mtclass; |
@@ -1195,12 +1203,25 @@ static bool mt_need_to_apply_feature(struct hid_device *hdev, | |||
1195 | } | 1203 | } |
1196 | } | 1204 | } |
1197 | break; | 1205 | break; |
1206 | |||
1207 | case HID_DG_LATENCYMODE: | ||
1208 | field->value[index] = latency; | ||
1209 | return 1; | ||
1210 | |||
1211 | case HID_DG_SURFACESWITCH: | ||
1212 | field->value[index] = surface_switch; | ||
1213 | return 1; | ||
1214 | |||
1215 | case HID_DG_BUTTONSWITCH: | ||
1216 | field->value[index] = button_switch; | ||
1217 | return 1; | ||
1198 | } | 1218 | } |
1199 | 1219 | ||
1200 | return false; /* no need to update the report */ | 1220 | return false; /* no need to update the report */ |
1201 | } | 1221 | } |
1202 | 1222 | ||
1203 | static void mt_set_modes(struct hid_device *hdev) | 1223 | static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency, |
1224 | bool surface_switch, bool button_switch) | ||
1204 | { | 1225 | { |
1205 | struct hid_report_enum *rep_enum; | 1226 | struct hid_report_enum *rep_enum; |
1206 | struct hid_report *rep; | 1227 | struct hid_report *rep; |
@@ -1222,7 +1243,10 @@ static void mt_set_modes(struct hid_device *hdev) | |||
1222 | 1243 | ||
1223 | if (mt_need_to_apply_feature(hdev, | 1244 | if (mt_need_to_apply_feature(hdev, |
1224 | rep->field[i], | 1245 | rep->field[i], |
1225 | usage)) | 1246 | usage, |
1247 | latency, | ||
1248 | surface_switch, | ||
1249 | button_switch)) | ||
1226 | update_report = true; | 1250 | update_report = true; |
1227 | } | 1251 | } |
1228 | } | 1252 | } |
@@ -1467,7 +1491,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1467 | dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", | 1491 | dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", |
1468 | hdev->name); | 1492 | hdev->name); |
1469 | 1493 | ||
1470 | mt_set_modes(hdev); | 1494 | mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); |
1471 | 1495 | ||
1472 | /* release .fields memory as it is not used anymore */ | 1496 | /* release .fields memory as it is not used anymore */ |
1473 | devm_kfree(&hdev->dev, td->fields); | 1497 | devm_kfree(&hdev->dev, td->fields); |
@@ -1480,7 +1504,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
1480 | static int mt_reset_resume(struct hid_device *hdev) | 1504 | static int mt_reset_resume(struct hid_device *hdev) |
1481 | { | 1505 | { |
1482 | mt_release_contacts(hdev); | 1506 | mt_release_contacts(hdev); |
1483 | mt_set_modes(hdev); | 1507 | mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); |
1484 | return 0; | 1508 | return 0; |
1485 | } | 1509 | } |
1486 | 1510 | ||
diff --git a/include/linux/hid.h b/include/linux/hid.h index f03d7a410c5d..a1be991e1eae 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
@@ -292,9 +292,12 @@ struct hid_item { | |||
292 | #define HID_DG_CONTACTCOUNT 0x000d0054 | 292 | #define HID_DG_CONTACTCOUNT 0x000d0054 |
293 | #define HID_DG_CONTACTMAX 0x000d0055 | 293 | #define HID_DG_CONTACTMAX 0x000d0055 |
294 | #define HID_DG_SCANTIME 0x000d0056 | 294 | #define HID_DG_SCANTIME 0x000d0056 |
295 | #define HID_DG_SURFACESWITCH 0x000d0057 | ||
296 | #define HID_DG_BUTTONSWITCH 0x000d0058 | ||
295 | #define HID_DG_BUTTONTYPE 0x000d0059 | 297 | #define HID_DG_BUTTONTYPE 0x000d0059 |
296 | #define HID_DG_BARRELSWITCH2 0x000d005a | 298 | #define HID_DG_BARRELSWITCH2 0x000d005a |
297 | #define HID_DG_TOOLSERIALNUMBER 0x000d005b | 299 | #define HID_DG_TOOLSERIALNUMBER 0x000d005b |
300 | #define HID_DG_LATENCYMODE 0x000d0060 | ||
298 | 301 | ||
299 | #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 | 302 | #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 |
300 | /* | 303 | /* |