aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/wacom_sys.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-20 15:59:01 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-20 15:59:01 -0700
commit7a324b3f0535ceb0f6676fa20ca2a7b6213008cb (patch)
tree4c03a2f9382ee8264ddbe79a60293f825364fac3 /drivers/hid/wacom_sys.c
parentMerge tag 'backlight-next-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight (diff)
parentMerge branch 'for-4.19/wiimote' into for-linus (diff)
downloadlinux-dev-7a324b3f0535ceb0f6676fa20ca2a7b6213008cb.tar.xz
linux-dev-7a324b3f0535ceb0f6676fa20ca2a7b6213008cb.zip
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID updates from Jiri Kosina: - touch_max detection improvements and quirk handling fixes in wacom driver from Jason Gerecke and Ping Cheng - Palm rejection from Dmitry Torokhov and _dial support from Benjamin Tissoires for hid-multitouch driver - Low voltage support for i2c-hid driver from Stephen Boyd - Guitar-Hero support from Nicolas Adenis-Lamarre - other assorted small fixes and device ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (40 commits) HID: intel_ish-hid: tx_buf memory leak on probe/remove HID: intel-ish-hid: Prevent loading of driver on Mehlow HID: cougar: Add support for the Cougar 500k Gaming Keyboard HID: cougar: make compare_device_paths reusable HID: intel-ish-hid: remove redundant variable num_frags HID: multitouch: handle palm for touchscreens HID: multitouch: touchscreens also use confidence reports HID: multitouch: report MT_TOOL_PALM for non-confident touches HID: microsoft: support the Surface Dial HID: core: do not upper bound the collection stack HID: input: enable Totem on the Dell Canvas 27 HID: multitouch: remove one copy of values HID: multitouch: ditch mt_report_id HID: multitouch: store a per application quirks value HID: multitouch: Store per collection multitouch data HID: multitouch: make sure the static list of class is not changed input: add MT_TOOL_DIAL HID: elan: Add support for touchpad on the Toshiba Click Mini L9W HID: elan: Add USB-id for HP x2 10-n000nd touchpad HID: elan: Add a flag for selecting if the touchpad has a LED ...
Diffstat (limited to 'drivers/hid/wacom_sys.c')
-rw-r--r--drivers/hid/wacom_sys.c123
1 files changed, 59 insertions, 64 deletions
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index d6797535fff9..0bdd85d486fe 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -210,6 +210,57 @@ static int wacom_calc_hid_res(int logical_extents, int physical_extents,
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,
struct hid_field *field, struct hid_usage *usage)
{
@@ -221,6 +272,8 @@ static void wacom_feature_mapping(struct hid_device *hdev,
int ret;
u32 n;
+ wacom_hid_usage_quirk(hdev, field, usage);
+
switch (equivalent_usage) {
case HID_DG_CONTACTMAX:
/* leave touch_max as is if predefined */
@@ -300,13 +353,6 @@ static void wacom_feature_mapping(struct hid_device *hdev,
kfree(data);
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;
- }
}
/*
@@ -348,6 +394,7 @@ static void wacom_usage_mapping(struct hid_device *hdev,
struct wacom_features *features = &wacom->wacom_wac.features;
bool finger = WACOM_FINGER_FIELD(field);
bool pen = WACOM_PEN_FIELD(field);
+ unsigned equivalent_usage = wacom_equivalent_usage(usage->hid);
/*
* Requiring Stylus Usage will ignore boot mouse
@@ -361,49 +408,9 @@ static void wacom_usage_mapping(struct hid_device *hdev,
else
return;
- /*
- * Bamboo models do not support HID_DG_CONTACTMAX.
- * And, Bamboo Pen only descriptor contains touch.
- */
- if (features->type > BAMBOO_PT) {
- /* ISDv4 touch devices at least supports one touch point */
- if (finger && !features->touch_max)
- features->touch_max = 1;
- }
-
- /*
- * 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;
+ wacom_hid_usage_quirk(hdev, field, usage);
- 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 (equivalent_usage) {
case HID_GD_X:
features->x_max = field->logical_maximum;
if (finger) {
@@ -703,18 +710,6 @@ struct wacom_hdev_data {
static LIST_HEAD(wacom_udev_list);
static DEFINE_MUTEX(wacom_udev_list_lock);
-static bool compare_device_paths(struct hid_device *hdev_a,
- struct hid_device *hdev_b, char separator)
-{
- int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys;
- int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys;
-
- if (n1 != n2 || n1 <= 0 || n2 <= 0)
- return false;
-
- return !strncmp(hdev_a->phys, hdev_b->phys, n1);
-}
-
static bool wacom_are_sibling(struct hid_device *hdev,
struct hid_device *sibling)
{
@@ -737,10 +732,10 @@ static bool wacom_are_sibling(struct hid_device *hdev,
* the same physical parent device path.
*/
if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) {
- if (!compare_device_paths(hdev, sibling, '/'))
+ if (!hid_compare_device_paths(hdev, sibling, '/'))
return false;
} else {
- if (!compare_device_paths(hdev, sibling, '.'))
+ if (!hid_compare_device_paths(hdev, sibling, '.'))
return false;
}
@@ -787,7 +782,7 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev)
/* Try to find an already-probed interface from the same device */
list_for_each_entry(data, &wacom_udev_list, list) {
- if (compare_device_paths(hdev, data->dev, '/')) {
+ if (hid_compare_device_paths(hdev, data->dev, '/')) {
kref_get(&data->kref);
return data;
}