Skip to content

Commit

Permalink
HID: wacom: Support "in range" for Intuos/Bamboo tablets where possible
Browse files Browse the repository at this point in the history
The 1st-generation Intuos tablets (CTL-X80) include an "in range" flag
like some professional tablets. To ensure the pen remains usable at as
large as distance as possible (and to preemptively disable touch when
it is nearby) we need to ensure that we handle these "in range" events.
Handling of tool type identification has been moved to occur only when
the pen is fully in prox rather than any time the "stylus_in_proximity"
flag changes (which is controlled by the further-out "in range" flag).

Link: https://sourceforge.net/p/linuxwacom/bugs/358/
Link: https://github.com/linuxwacom/xf86-input-wacom/issues/14
Link: https://github.com/linuxwacom/xf86-input-wacom/issues/17
Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Tested-by: Ping Cheng <ping.cheng@wacom.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Jason Gerecke authored and Jiri Kosina committed May 22, 2018
1 parent 008464a commit 8947b0c
Showing 1 changed file with 39 additions and 35 deletions.
74 changes: 39 additions & 35 deletions drivers/hid/wacom_wac.c
Original file line number Diff line number Diff line change
Expand Up @@ -2894,41 +2894,41 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
struct wacom_features *features = &wacom->features;
struct input_dev *input = wacom->pen_input;
unsigned char *data = wacom->data;
int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
int x = 0, y = 0, p = 0, d = 0;
bool pen = false, btn1 = false, btn2 = false;
bool range, prox, rdy;

if (data[0] != WACOM_REPORT_PENABLED)
return 0;

prox = (data[1] & 0x20) == 0x20;
range = (data[1] & 0x80) == 0x80;
prox = (data[1] & 0x40) == 0x40;
rdy = (data[1] & 0x20) == 0x20;

wacom->shared->stylus_in_proximity = range;
if (delay_pen_events(wacom))
return 0;

if (rdy) {
p = le16_to_cpup((__le16 *)&data[6]);
pen = data[1] & 0x01;
btn1 = data[1] & 0x02;
btn2 = data[1] & 0x04;
}
if (prox) {
x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]);

/*
* All reports shared between PEN and RUBBER tool must be
* forced to a known starting value (zero) when transitioning to
* out-of-prox.
*
* If not reset then, to userspace, it will look like lost events
* if new tool comes in-prox with same values as previous tool sent.
*
* Hardware does report zero in most out-of-prox cases but not all.
*/
if (!wacom->shared->stylus_in_proximity) {
if (data[1] & 0x08) {
wacom->tool[0] = BTN_TOOL_RUBBER;
wacom->id[0] = ERASER_DEVICE_ID;
} else {
wacom->tool[0] = BTN_TOOL_PEN;
wacom->id[0] = STYLUS_DEVICE_ID;
}
wacom->reporting_data = true;
}

wacom->shared->stylus_in_proximity = prox;
if (delay_pen_events(wacom))
return 0;

if (prox) {
x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]);
p = le16_to_cpup((__le16 *)&data[6]);
if (range) {
/*
* Convert distance from out prox to distance from tablet.
* distance will be greater than distance_max once
Expand All @@ -2937,25 +2937,29 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
*/
if (data[8] <= features->distance_max)
d = features->distance_max - data[8];

pen = data[1] & 0x01;
btn1 = data[1] & 0x02;
btn2 = data[1] & 0x04;
} else {
wacom->id[0] = 0;
}

input_report_key(input, BTN_TOUCH, pen);
input_report_key(input, BTN_STYLUS, btn1);
input_report_key(input, BTN_STYLUS2, btn2);
if (wacom->reporting_data) {
input_report_key(input, BTN_TOUCH, pen);
input_report_key(input, BTN_STYLUS, btn1);
input_report_key(input, BTN_STYLUS2, btn2);

input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
input_report_abs(input, ABS_PRESSURE, p);
input_report_abs(input, ABS_DISTANCE, d);
if (prox || !range) {
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
}
input_report_abs(input, ABS_PRESSURE, p);
input_report_abs(input, ABS_DISTANCE, d);

input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
input_report_key(input, wacom->tool[0], range); /* PEN or RUBBER */
input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
}

if (!range) {
wacom->reporting_data = false;
}

return 1;
}
Expand Down

0 comments on commit 8947b0c

Please sign in to comment.