Commit 57832512 authored by Jason Gerecke's avatar Jason Gerecke Committed by Jiri Kosina

HID: wacom: Move handling of HID quirks into a dedicated function

We want to keep device-specific quirks as contained as possible so that the
the code remains maintainable. Our 'wacom_setup_device_quirks' function is
the usual place for this, but some quirks need to be applied to the HID
descriptor as it is parsed. This commit introduces a new function which is
called for each usage so that any HID-specific quirks can be applied. The
function now houses quirks that were being done in 'wacom_feature_mapping'
and 'wacom_usage_mapping'.
Signed-off-by: default avatarJason Gerecke <jason.gerecke@wacom.com>
Reviewed-by: default avatarPing Cheng <ping.cheng@wacom.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 29b9e148
...@@ -210,6 +210,57 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents, ...@@ -210,6 +210,57 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
return hidinput_calc_abs_res(&field, ABS_X); return hidinput_calc_abs_res(&field, ABS_X);
} }
static void wacom_hid_usage_quirk(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage)
{
struct wacom *wacom = hid_get_drvdata(hdev);
struct wacom_features *features = &wacom->wacom_wac.features;
unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid);
/*
* The Dell Canvas 27 needs to be switched to its vendor-defined
* report to provide the best resolution.
*/
if (hdev->vendor == USB_VENDOR_ID_WACOM &&
hdev->product == 0x4200 &&
field->application == HID_UP_MSVENDOR) {
wacom->wacom_wac.mode_report = field->report->id;
wacom->wacom_wac.mode_value = 2;
}
/*
* ISDv4 devices which predate HID's adoption of the
* HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
* position instead. We can accurately detect if a
* usage with that value should be HID_DG_BARRELSWITCH2
* based on the surrounding usages, which have remained
* constant across generations.
*/
if (features->type == HID_GENERIC &&
usage->hid == 0x000D0000 &&
field->application == HID_DG_PEN &&
field->physical == HID_DG_STYLUS) {
int i = usage->usage_index;
if (i-4 >= 0 && i+1 < field->maxusage &&
field->usage[i-4].hid == HID_DG_TIPSWITCH &&
field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
field->usage[i-2].hid == HID_DG_ERASER &&
field->usage[i-1].hid == HID_DG_INVERT &&
field->usage[i+1].hid == HID_DG_INRANGE) {
usage->hid = HID_DG_BARRELSWITCH2;
}
}
/* 2nd-generation Intuos Pro Large has incorrect Y maximum */
if (hdev->vendor == USB_VENDOR_ID_WACOM &&
hdev->product == 0x0358 &&
WACOM_PEN_FIELD(field) &&
equivalent_usage == HID_GD_Y) {
field->logical_maximum = 43200;
}
}
static void wacom_feature_mapping(struct hid_device *hdev, static void wacom_feature_mapping(struct hid_device *hdev,
struct hid_field *field, struct hid_usage *usage) struct hid_field *field, struct hid_usage *usage)
{ {
...@@ -221,6 +272,8 @@ static void wacom_feature_mapping(struct hid_device *hdev, ...@@ -221,6 +272,8 @@ static void wacom_feature_mapping(struct hid_device *hdev,
int ret; int ret;
u32 n; u32 n;
wacom_hid_usage_quirk(hdev, field, usage);
switch (equivalent_usage) { switch (equivalent_usage) {
case HID_DG_CONTACTMAX: case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */ /* leave touch_max as is if predefined */
...@@ -300,13 +353,6 @@ static void wacom_feature_mapping(struct hid_device *hdev, ...@@ -300,13 +353,6 @@ static void wacom_feature_mapping(struct hid_device *hdev,
kfree(data); kfree(data);
break; break;
} }
if (hdev->vendor == USB_VENDOR_ID_WACOM &&
hdev->product == 0x4200 /* Dell Canvas 27 */ &&
field->application == HID_UP_MSVENDOR) {
wacom->wacom_wac.mode_report = field->report->id;
wacom->wacom_wac.mode_value = 2;
}
} }
/* /*
...@@ -361,37 +407,7 @@ static void wacom_usage_mapping(struct hid_device *hdev, ...@@ -361,37 +407,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
else else
return; return;
/* wacom_hid_usage_quirk(hdev, field, usage);
* ISDv4 devices which predate HID's adoption of the
* HID_DG_BARELSWITCH2 usage use 0x000D0000 in its
* position instead. We can accurately detect if a
* usage with that value should be HID_DG_BARRELSWITCH2
* based on the surrounding usages, which have remained
* constant across generations.
*/
if (features->type == HID_GENERIC &&
usage->hid == 0x000D0000 &&
field->application == HID_DG_PEN &&
field->physical == HID_DG_STYLUS) {
int i = usage->usage_index;
if (i-4 >= 0 && i+1 < field->maxusage &&
field->usage[i-4].hid == HID_DG_TIPSWITCH &&
field->usage[i-3].hid == HID_DG_BARRELSWITCH &&
field->usage[i-2].hid == HID_DG_ERASER &&
field->usage[i-1].hid == HID_DG_INVERT &&
field->usage[i+1].hid == HID_DG_INRANGE) {
usage->hid = HID_DG_BARRELSWITCH2;
}
}
/* 2nd-generation Intuos Pro Large has incorrect Y maximum */
if (hdev->vendor == USB_VENDOR_ID_WACOM &&
hdev->product == 0x0358 &&
WACOM_PEN_FIELD(field) &&
wacom_equivalent_usage(usage->hid) == HID_GD_Y) {
field->logical_maximum = 43200;
}
switch (usage->hid) { switch (usage->hid) {
case HID_GD_X: case HID_GD_X:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment