Skip to content

Commit

Permalink
HID: wacom: generic: Add support for vendor-defined "Sense" usage
Browse files Browse the repository at this point in the history
Wacom's professional tablets beginning with the Intuos4 are capable of
reporting an intermediate degree of proximity where the pen is no longer
close enough to communicate with ("in prox"), but still close enough to
be sensed ("in range"). This additional state is particularly useful for
performing palm rejection as it allows the driver to disable the touch
sensor while the pen is a greater distance from the tablet.

Like other professional tablets, the new MobileStudio Pro also reports
this intermeidate "in range" proximity state. Its descriptor assigns
usage 0xff0d0036 to this bit. Normally 'wacom_equivalent_usage' would
translate this to the standard HID "Quality" usage, but since this has
a different meaning we have it explicitly ignore the usage and define
it ourselves as "Sense" (since "In Range" is already defined by the
HID standard and interpreted by our driver as meaning "in prox").

Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Jason Gerecke authored and Jiri Kosina committed Oct 20, 2016
1 parent 929d6d5 commit 61ce346
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
26 changes: 23 additions & 3 deletions drivers/hid/wacom_wac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,7 @@ static int wacom_equivalent_usage(int usage)

if (subpage == WACOM_HID_SP_DIGITIZER ||
subpage == WACOM_HID_SP_DIGITIZERINFO ||
usage == WACOM_HID_WD_SENSE ||
usage == WACOM_HID_WD_DISTANCE) {
return usage;
}
Expand Down Expand Up @@ -1493,6 +1494,7 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct wacom_features *features = &wacom_wac->features;
struct input_dev *input = wacom_wac->pen_input;
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);

Expand Down Expand Up @@ -1539,6 +1541,10 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
case HID_DG_TOOLSERIALNUMBER:
wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0);
break;
case WACOM_HID_WD_SENSE:
features->quirks |= WACOM_QUIRK_SENSE;
wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0);
break;
case WACOM_HID_WD_FINGERWHEEL:
wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0);
break;
Expand All @@ -1550,6 +1556,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct wacom_features *features = &wacom_wac->features;
struct input_dev *input = wacom_wac->pen_input;
unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);

Expand All @@ -1564,6 +1571,8 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
break;
case HID_DG_INRANGE:
wacom_wac->hid_data.inrange_state = value;
if (!(features->quirks & WACOM_QUIRK_SENSE))
wacom_wac->hid_data.sense_state = value;
return 0;
case HID_DG_INVERT:
wacom_wac->hid_data.invert_state = value;
Expand All @@ -1572,6 +1581,9 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
case HID_DG_TIPSWITCH:
wacom_wac->hid_data.tipswitch |= value;
return 0;
case WACOM_HID_WD_SENSE:
wacom_wac->hid_data.sense_state = value;
return 0;
}

/* send pen events only when touch is up or forced out
Expand All @@ -1580,6 +1592,10 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field,
if (!usage->type || delay_pen_events(wacom_wac))
return 0;

/* send pen events only when the pen is in/entering/leaving proximity */
if (!wacom_wac->hid_data.inrange_state && !wacom_wac->tool[0])
return 0;

input_event(input, usage->type, usage->code, value);

return 0;
Expand All @@ -1598,16 +1614,17 @@ static void wacom_wac_pen_report(struct hid_device *hdev,
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct input_dev *input = wacom_wac->pen_input;
bool prox = wacom_wac->hid_data.inrange_state;
bool range = wacom_wac->hid_data.sense_state;

if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */
if (!wacom_wac->tool[0] && prox) /* first in prox */
/* Going into proximity select tool */
wacom_wac->tool[0] = wacom_wac->hid_data.invert_state ?
BTN_TOOL_RUBBER : BTN_TOOL_PEN;

/* keep pen state for touch events */
wacom_wac->shared->stylus_in_proximity = prox;
wacom_wac->shared->stylus_in_proximity = range;

if (!delay_pen_events(wacom_wac)) {
if (!delay_pen_events(wacom_wac) && wacom_wac->tool[0]) {
input_report_key(input, BTN_TOUCH,
wacom_wac->hid_data.tipswitch);
input_report_key(input, wacom_wac->tool[0], prox);
Expand All @@ -1616,6 +1633,9 @@ static void wacom_wac_pen_report(struct hid_device *hdev,

input_sync(input);
}

if (!prox)
wacom_wac->tool[0] = 0;
}

static void wacom_wac_finger_usage_mapping(struct hid_device *hdev,
Expand Down
3 changes: 3 additions & 0 deletions drivers/hid/wacom_wac.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

/* device quirks */
#define WACOM_QUIRK_BBTOUCH_LOWRES 0x0001
#define WACOM_QUIRK_SENSE 0x0002
#define WACOM_QUIRK_BATTERY 0x0008

/* device types */
Expand All @@ -88,6 +89,7 @@
#define WACOM_HID_SP_DIGITIZER 0x000d0000
#define WACOM_HID_SP_DIGITIZERINFO 0x00100000
#define WACOM_HID_WD_DIGITIZER (WACOM_HID_UP_WACOMDIGITIZER | 0x01)
#define WACOM_HID_WD_SENSE (WACOM_HID_UP_WACOMDIGITIZER | 0x36)
#define WACOM_HID_WD_DISTANCE (WACOM_HID_UP_WACOMDIGITIZER | 0x0132)
#define WACOM_HID_WD_FINGERWHEEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0d03)
#define WACOM_HID_WD_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002)
Expand Down Expand Up @@ -212,6 +214,7 @@ struct wacom_shared {
struct hid_data {
__s16 inputmode; /* InputMode HID feature, -1 if non-existent */
__s16 inputmode_index; /* InputMode HID feature index in the report */
bool sense_state;
bool inrange_state;
bool invert_state;
bool tipswitch;
Expand Down

0 comments on commit 61ce346

Please sign in to comment.