Skip to content

Commit 94b1790

Browse files
jigpuJiri Kosina
authored andcommitted
HID: wacom: Force pen out of prox if no events have been received in a while
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: linuxwacom/input-wacom#310 Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1 parent ab5f340 commit 94b1790

3 files changed

Lines changed: 44 additions & 0 deletions

File tree

drivers/hid/wacom.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
#include <linux/leds.h>
9292
#include <linux/usb/input.h>
9393
#include <linux/power_supply.h>
94+
#include <linux/timer.h>
9495
#include <asm/unaligned.h>
9596

9697
/*
@@ -167,6 +168,7 @@ struct wacom {
167168
struct delayed_work init_work;
168169
struct wacom_remote *remote;
169170
struct work_struct mode_change_work;
171+
struct timer_list idleprox_timer;
170172
bool generic_has_leds;
171173
struct wacom_leds {
172174
struct wacom_group_leds *groups;
@@ -239,4 +241,5 @@ struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group,
239241
struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur);
240242
int wacom_equivalent_usage(int usage);
241243
int wacom_initialize_leds(struct wacom *wacom);
244+
void wacom_idleprox_timeout(struct timer_list *list);
242245
#endif

drivers/hid/wacom_sys.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,7 @@ static int wacom_probe(struct hid_device *hdev,
27812781
INIT_WORK(&wacom->battery_work, wacom_battery_work);
27822782
INIT_WORK(&wacom->remote_work, wacom_remote_work);
27832783
INIT_WORK(&wacom->mode_change_work, wacom_mode_change_work);
2784+
timer_setup(&wacom->idleprox_timer, &wacom_idleprox_timeout, TIMER_DEFERRABLE);
27842785

27852786
/* ask for the report descriptor to be loaded by HID */
27862787
error = hid_parse(hdev);
@@ -2821,6 +2822,7 @@ static void wacom_remove(struct hid_device *hdev)
28212822
cancel_work_sync(&wacom->battery_work);
28222823
cancel_work_sync(&wacom->remote_work);
28232824
cancel_work_sync(&wacom->mode_change_work);
2825+
del_timer_sync(&wacom->idleprox_timer);
28242826
if (hdev->bus == BUS_BLUETOOTH)
28252827
device_remove_file(&hdev->dev, &dev_attr_speed);
28262828

drivers/hid/wacom_wac.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "wacom_wac.h"
1212
#include "wacom.h"
1313
#include <linux/input/mt.h>
14+
#include <linux/jiffies.h>
1415

1516
/* resolution for penabled devices */
1617
#define WACOM_PL_RES 20
@@ -41,6 +42,43 @@ static int wacom_numbered_button_to_key(int n);
4142

4243
static void wacom_update_led(struct wacom *wacom, int button_count, int mask,
4344
int group);
45+
46+
static void wacom_force_proxout(struct wacom_wac *wacom_wac)
47+
{
48+
struct input_dev *input = wacom_wac->pen_input;
49+
50+
wacom_wac->shared->stylus_in_proximity = 0;
51+
52+
input_report_key(input, BTN_TOUCH, 0);
53+
input_report_key(input, BTN_STYLUS, 0);
54+
input_report_key(input, BTN_STYLUS2, 0);
55+
input_report_key(input, BTN_STYLUS3, 0);
56+
input_report_key(input, wacom_wac->tool[0], 0);
57+
if (wacom_wac->serial[0]) {
58+
input_report_abs(input, ABS_MISC, 0);
59+
}
60+
input_report_abs(input, ABS_PRESSURE, 0);
61+
62+
wacom_wac->tool[0] = 0;
63+
wacom_wac->id[0] = 0;
64+
wacom_wac->serial[0] = 0;
65+
66+
input_sync(input);
67+
}
68+
69+
void wacom_idleprox_timeout(struct timer_list *list)
70+
{
71+
struct wacom *wacom = from_timer(wacom, list, idleprox_timer);
72+
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
73+
74+
if (!wacom_wac->hid_data.sense_state) {
75+
return;
76+
}
77+
78+
hid_warn(wacom->hdev, "%s: tool appears to be hung in-prox. forcing it out.\n", __func__);
79+
wacom_force_proxout(wacom_wac);
80+
}
81+
4482
/*
4583
* Percent of battery capacity for Graphire.
4684
* 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
23292367
value = field->logical_maximum - value;
23302368
break;
23312369
case HID_DG_INRANGE:
2370+
mod_timer(&wacom->idleprox_timer, jiffies + msecs_to_jiffies(100));
23322371
wacom_wac->hid_data.inrange_state = value;
23332372
if (!(features->quirks & WACOM_QUIRK_SENSE))
23342373
wacom_wac->hid_data.sense_state = value;

0 commit comments

Comments
 (0)