From patchwork Thu Oct 6 21:22:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gerecke X-Patchwork-Id: 9365333 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id BA4A96077E for ; Thu, 6 Oct 2016 21:22:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A472629253 for ; Thu, 6 Oct 2016 21:22:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 993E929256; Thu, 6 Oct 2016 21:22:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2030A29253 for ; Thu, 6 Oct 2016 21:22:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935171AbcJFVWx (ORCPT ); Thu, 6 Oct 2016 17:22:53 -0400 Received: from mail-qk0-f195.google.com ([209.85.220.195]:33610 "EHLO mail-qk0-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935088AbcJFVWw (ORCPT ); Thu, 6 Oct 2016 17:22:52 -0400 Received: by mail-qk0-f195.google.com with SMTP id n66so1672122qkf.0 for ; Thu, 06 Oct 2016 14:22:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=IJowjD06Zl5G/BQq4280e6RmeL5i3zBedExvA1V8kco=; b=w21CSSEU2VFUSYeSOkWrOeYGtUGqdMPuYcf1lxnyYw1DjZLjAuR+dPVQ85LK3gw6Oa bdr1aw26Cuhu46HbfY3PYOdDs5IW0K7Kse6mVLhi+jZ3jiEcJiPGh6ijW6imlZU7sLgU WybDkazlY7hWMZFSDbxr5qNGbi7iAn7PZwEYEI2GBwIDORJfv4ilA6tjpBmH5+nAQry/ LWH6WAv1ZM0DxYvXpTUXfyUmj6Y35c4DfRNWSGWvzi1yFHXEEyESE2/ptkDIgssvIp/D zv5mbulXVBGFqHodbFRCModf+EQTAK8JRy3aU395Tfb164VGC4bVFZe87mL/py/ZCtJ2 Xoww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=IJowjD06Zl5G/BQq4280e6RmeL5i3zBedExvA1V8kco=; b=lnV1NAcyZCcqQweiU+8ZPGDGsdcb9wDx3XHYI7H0SE4AaAQI1d57vz0EVlwL2qo6oH ttgDt2sHVMURLoTaOjs9Z4bxMYUynF6IeSkcctTRcK5rruJ+eCpnue/mSxgleZ1reCvq CsQR1xDSojNLeLDwOt8/w2UDetbR+CLWhx1PV4eNHB4fFdkC6LvQn3/LS00yXgQLo3nP THAWBT4dO8pOWAqRekDjfoFJYATbj8DT+Wyj6ifuJfY6IpvkUW2W/hMNQlmZUSsCt2RB Dx1QajJ2C1QPGfImG5hGsv+N1rSComvSVfRHy+spM9JPC0T8j2l6d8cVOrDPu0yQAxvD YLkA== X-Gm-Message-State: AA6/9RmGKQmmiKBJ4XKhKkiES7vekCBj/NOhLImv7SmBYs97s8FGETSjgfJzPEIFVxJjgA== X-Received: by 10.55.78.75 with SMTP id c72mr16074628qkb.168.1475788971601; Thu, 06 Oct 2016 14:22:51 -0700 (PDT) Received: from wacom-arch2.corp.onewacom.com ([50.225.60.4]) by smtp.gmail.com with ESMTPSA id m4sm5773714qkf.29.2016.10.06.14.22.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 06 Oct 2016 14:22:51 -0700 (PDT) From: Jason Gerecke To: linux-input@vger.kernel.org, Jiri Kosina Cc: Benjamin Tissoires , Ping Cheng , Ping Cheng , Aaron Skomra , Jason Gerecke , Jason Gerecke Subject: [PATCH 07/19] HID: wacom: generic: Support and use 'Custom HID' mode and usages Date: Thu, 6 Oct 2016 14:22:19 -0700 Message-Id: <20161006212231.31440-8-killertofu@gmail.com> X-Mailer: git-send-email 2.10.0 In-Reply-To: <20161006212231.31440-1-killertofu@gmail.com> References: <20161006212231.31440-1-killertofu@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Wacom's new "MobileStudio Pro" tablets are the first devices in their branded product line-up to include a usable HID descriptor for the pen interface. Like prior branded products, the device can operate in one of two modes: 'Standard HID', and 'Wacom Custom HID'. Although the first mode is usable by the HID_GENERIC codepath as-is (huzzah!), it is subject to some restrictions -- most notably pressure being limited to 2048 levels instead of 8192. To ensure tablets that include support for Custom HID mode work optimally, we add support for its usages and switch the device to Custom HID mode if possible. The usages defined for Custom HID mode are often numerically similar to their standard HID equivalents, allowing us to write a simple translation function that takes arbitrary HID usages as input and which returns the corresponding standard HID usage as output (if one exists). Switching on this translated usage instead of the actual usage allows the existing cases to apply to both modes of operation without having to explicitly define every Custom HID usage. Signed-off-by: Jason Gerecke --- drivers/hid/wacom_sys.c | 5 +++++ drivers/hid/wacom_wac.c | 37 +++++++++++++++++++++++++++++++------ drivers/hid/wacom_wac.h | 3 +++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 7b9bff2..b2e2471 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -166,6 +166,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, } break; + case WACOM_HID_WD_DATAMODE: + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value = 2; + break; + case WACOM_HID_UP_G9: case WACOM_HID_UP_G11: if (field->report->id == 0x03 && diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index e2eae91..edc2c14 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1435,14 +1435,35 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return 0; } +static int wacom_equivalent_usage(int usage) +{ + if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { + int subpage = (usage & 0xFF00) << 8; + int subusage = (usage & 0xFF); + + if (subpage == WACOM_HID_SP_DIGITIZER || + subpage == WACOM_HID_SP_DIGITIZERINFO) { + return usage; + } + + if (subpage == HID_UP_UNDEFINED) + subpage = HID_UP_DIGITIZER; + + return subpage | subusage; + } + + return usage; +} + static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, struct hid_field *field, __u8 type, __u16 code, int fuzz) { int fmin = field->logical_minimum; int fmax = field->logical_maximum; + unsigned int equivalent_usage = wacom_equivalent_usage(usage->hid); int resolution_code = code; - if (usage->hid == HID_DG_TWIST) { + if (equivalent_usage == HID_DG_TWIST) { resolution_code = ABS_RZ; } @@ -1472,8 +1493,9 @@ 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 input_dev *input = wacom_wac->pen_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); break; @@ -1524,8 +1546,9 @@ 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 input_dev *input = wacom_wac->pen_input; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_Z: /* * HID_GD_Z "should increase as the control's position is @@ -1598,8 +1621,9 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, struct wacom_features *features = &wacom_wac->features; struct input_dev *input = wacom_wac->touch_input; unsigned touch_max = wacom_wac->features.touch_max; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: features->last_slot_field = usage->hid; if (touch_max == 1) @@ -1687,8 +1711,9 @@ static int wacom_wac_finger_event(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; + unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); - switch (usage->hid) { + switch (equivalent_usage) { case HID_GD_X: wacom_wac->hid_data.x = value; break; @@ -1711,7 +1736,7 @@ static int wacom_wac_finger_event(struct hid_device *hdev, if (usage->usage_index + 1 == field->report_count) { - if (usage->hid == wacom_wac->features.last_slot_field) + if (equivalent_usage == wacom_wac->features.last_slot_field) wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 472b0a7..c82233d 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -85,7 +85,10 @@ #define WACOM_DEVICETYPE_DIRECT 0x0010 #define WACOM_HID_UP_WACOMDIGITIZER 0xff0d0000 +#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_DATAMODE (WACOM_HID_UP_WACOMDIGITIZER | 0x1002) #define WACOM_HID_UP_G9 0xff090000 #define WACOM_HID_G9_PEN (WACOM_HID_UP_G9 | 0x02) #define WACOM_HID_G9_TOUCHSCREEN (WACOM_HID_UP_G9 | 0x11)