From f0a979c1211cb5052028841df4bac192617c955c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: May 25 2023 06:18:53 +0000 Subject: HID: wacom: Force pen out of prox if no events have been received in a while (git-fixes). --- diff --git a/patches.suse/HID-wacom-Force-pen-out-of-prox-if-no-events-have-be.patch b/patches.suse/HID-wacom-Force-pen-out-of-prox-if-no-events-have-be.patch new file mode 100644 index 0000000..9f314cd --- /dev/null +++ b/patches.suse/HID-wacom-Force-pen-out-of-prox-if-no-events-have-be.patch @@ -0,0 +1,141 @@ +From 94b179052f95c294d83e9c9c34f7833cf3cd4305 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Fri, 15 Jul 2022 16:05:19 -0700 +Subject: [PATCH] HID: wacom: Force pen out of prox if no events have been received in a while +Git-commit: 94b179052f95c294d83e9c9c34f7833cf3cd4305 +Patch-mainline: v6.0-rc1 +References: git-fixes + +Prox-out events may not be reliably sent by some AES firmware. This can +cause problems for users, particularly due to arbitration logic disabling +touch input while the pen is in prox. + +This commit adds a timer which is reset every time a new prox event is +received. When the timer expires we check to see if the pen is still in +prox and force it out if necessary. This is patterend off of the same +solution used by 'hid-letsketch' driver which has a similar problem. + +Link: https://github.com/linuxwacom/input-wacom/issues/310 +Signed-off-by: Jason Gerecke +Signed-off-by: Jiri Kosina +Acked-by: Takashi Iwai + +--- + drivers/hid/wacom.h | 3 +++ + drivers/hid/wacom_sys.c | 2 ++ + drivers/hid/wacom_wac.c | 39 +++++++++++++++++++++++++++++++++++++++ + 3 files changed, 44 insertions(+) + +diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h +index 203d27d198b8..3f8b24a57014 100644 +--- a/drivers/hid/wacom.h ++++ b/drivers/hid/wacom.h +@@ -91,6 +91,7 @@ + #include + #include + #include ++#include + #include + + /* +@@ -167,6 +168,7 @@ struct wacom { + struct delayed_work init_work; + struct wacom_remote *remote; + struct work_struct mode_change_work; ++ struct timer_list idleprox_timer; + bool generic_has_leds; + struct wacom_leds { + struct wacom_group_leds *groups; +@@ -239,4 +241,5 @@ struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group, + struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur); + int wacom_equivalent_usage(int usage); + int wacom_initialize_leds(struct wacom *wacom); ++void wacom_idleprox_timeout(struct timer_list *list); + #endif +diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c +index 98384b911288..194a2e327591 100644 +--- a/drivers/hid/wacom_sys.c ++++ b/drivers/hid/wacom_sys.c +@@ -2781,6 +2781,7 @@ static int wacom_probe(struct hid_device *hdev, + INIT_WORK(&wacom->battery_work, wacom_battery_work); + INIT_WORK(&wacom->remote_work, wacom_remote_work); + INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work); ++ timer_setup(&wacom->idleprox_timer, &wacom_idleprox_timeout, TIMER_DEFERRABLE); + + /* ask for the report descriptor to be loaded by HID */ + error = hid_parse(hdev); +@@ -2821,6 +2822,7 @@ static void wacom_remove(struct hid_device *hdev) + cancel_work_sync(&wacom->battery_work); + cancel_work_sync(&wacom->remote_work); + cancel_work_sync(&wacom->mode_change_work); ++ del_timer_sync(&wacom->idleprox_timer); + if (hdev->bus == BUS_BLUETOOTH) + device_remove_file(&hdev->dev, &dev_attr_speed); + +diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c +index f8cc4bb3e3a7..d049239256a2 100644 +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -11,6 +11,7 @@ + #include "wacom_wac.h" + #include "wacom.h" + #include ++#include + + /* resolution for penabled devices */ + #define WACOM_PL_RES 20 +@@ -41,6 +42,43 @@ static int wacom_numbered_button_to_key(int n); + + static void wacom_update_led(struct wacom *wacom, int button_count, int mask, + int group); ++ ++static void wacom_force_proxout(struct wacom_wac *wacom_wac) ++{ ++ struct input_dev *input = wacom_wac->pen_input; ++ ++ wacom_wac->shared->stylus_in_proximity = 0; ++ ++ input_report_key(input, BTN_TOUCH, 0); ++ input_report_key(input, BTN_STYLUS, 0); ++ input_report_key(input, BTN_STYLUS2, 0); ++ input_report_key(input, BTN_STYLUS3, 0); ++ input_report_key(input, wacom_wac->tool[0], 0); ++ if (wacom_wac->serial[0]) { ++ input_report_abs(input, ABS_MISC, 0); ++ } ++ input_report_abs(input, ABS_PRESSURE, 0); ++ ++ wacom_wac->tool[0] = 0; ++ wacom_wac->id[0] = 0; ++ wacom_wac->serial[0] = 0; ++ ++ input_sync(input); ++} ++ ++void wacom_idleprox_timeout(struct timer_list *list) ++{ ++ struct wacom *wacom = from_timer(wacom, list, idleprox_timer); ++ struct wacom_wac *wacom_wac = &wacom->wacom_wac; ++ ++ if (!wacom_wac->hid_data.sense_state) { ++ return; ++ } ++ ++ hid_warn(wacom->hdev, "%s: tool appears to be hung in-prox. forcing it out.\n", __func__); ++ wacom_force_proxout(wacom_wac); ++} ++ + /* + * Percent of battery capacity for Graphire. + * 8th value means AC online and show 100% capacity. +@@ -2329,6 +2367,7 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field + value = field->logical_maximum - value; + break; + case HID_DG_INRANGE: ++ mod_timer(&wacom->idleprox_timer, jiffies + msecs_to_jiffies(100)); + wacom_wac->hid_data.inrange_state = value; + if (!(features->quirks & WACOM_QUIRK_SENSE)) + wacom_wac->hid_data.sense_state = value; +-- +2.35.3 + diff --git a/series.conf b/series.conf index 52d8dc9..6eb5de5 100644 --- a/series.conf +++ b/series.conf @@ -15143,6 +15143,7 @@ patches.suse/HID-cp2112-prevent-a-buffer-overflow-in-cp2112_xfer.patch patches.suse/HID-multitouch-new-device-class-fix-Lenovo-X12-track.patch patches.suse/HID-mcp2221-prevent-a-buffer-overflow-in-mcp_smbus_w.patch + patches.suse/HID-wacom-Force-pen-out-of-prox-if-no-events-have-be.patch patches.suse/HID-alps-Declare-U1_UNICORN_LEGACY-support.patch patches.suse/HID-amd_sfh-Add-NULL-check-for-hid-device.patch patches.suse/HID-amd_sfh-Handle-condition-of-no-sensors.patch