From patchwork Mon Aug 8 19:06:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gerecke, Jason" X-Patchwork-Id: 9269171 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 9EB15607D6 for ; Mon, 8 Aug 2016 19:06:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8B55328159 for ; Mon, 8 Aug 2016 19:06:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7FB2128161; Mon, 8 Aug 2016 19:06:50 +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 0044928159 for ; Mon, 8 Aug 2016 19:06:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752301AbcHHTGt (ORCPT ); Mon, 8 Aug 2016 15:06:49 -0400 Received: from mail-pa0-f65.google.com ([209.85.220.65]:36403 "EHLO mail-pa0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752292AbcHHTGs (ORCPT ); Mon, 8 Aug 2016 15:06:48 -0400 Received: by mail-pa0-f65.google.com with SMTP id ez1so24443761pab.3 for ; Mon, 08 Aug 2016 12:06:48 -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=L4TAR7XJ/x9ttSFoqWx8Ip9qgZF0hzrcPHrQ5IBTyK0=; b=oCKS+6jq57OCoFDo6dNEvTHLL8B1VTwz0FWnuM/3c8+ossE+84A7Kpemln2H0UPCGC 3JrgE5a9Y/qn5zHbBqKM5FfRKbXcVCOnbbWp8rqcAbLDkXdTE/loteytEDK/mdO6IR5/ Et3zBO1Z0aCV9pP1SoQ01YJyXMBwBjpsfNqygN+RrRsC6/Yi9GyV32ikSMeIDcPr0Sks n12dMtKAVQ4V6Zw6VO1be7q0QQnUAu20Umu1VmS0aQvIThYZdzFpX4zD31nYJjv7P+vv QVSyuyvxlTY6K/hlklztmooxbyVXW2iTUYn+fcWT8OtaZvDNtV7VqOxbTguVSCfojtfy yg/Q== 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=L4TAR7XJ/x9ttSFoqWx8Ip9qgZF0hzrcPHrQ5IBTyK0=; b=HhJ9AdcLUO7BYHXyq9JnkkksabzeR1zGzEzy5qJNiS7Vi2XkmXbxZtVVv37ru0SNVn B2OX1pa2F0Xe5hiWlTbh3qfsNt/PNa4+/bdOzqVAA63uVyABCNqFcOJ1EJYxxFlzmgQW 36G2ANvk4H19UJcdWVOBHEgHsbzMZQEql38C5tKObsW7e8KkTNMJ7JFTp2kcHAmnEMRV LNHubmhgwn3+1dfPg//JBJVY0t0ZNrrJcAZ9s3pOBLRNjrqheTRMHcky4uQTD6Ci80Wp j2h8s7APxdZJGkKA5la6jNy65auE8Qt+SY0d+Ku9bsZkN22aYrCP+lYxRK4b8DLOsMe9 Hwaw== X-Gm-Message-State: AEkoousR7HkjT0iCtVnAPgjZvStmvpU8FZ1nCThk8zwBBvGQMzrM2IOnoQN4lsJ4IQssvA== X-Received: by 10.66.161.195 with SMTP id xu3mr163906414pab.68.1470683207874; Mon, 08 Aug 2016 12:06:47 -0700 (PDT) Received: from wtc005007.corp.onewacom.com (75-164-217-104.ptld.qwest.net. [75.164.217.104]) by smtp.gmail.com with ESMTPSA id h1sm50060075pay.48.2016.08.08.12.06.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Aug 2016 12:06:47 -0700 (PDT) From: Jason Gerecke To: linux-input@vger.kernel.org Cc: Ping Cheng , Aaron Skomra , Benjamin Tissoires , Jiri Kosina , Jason Gerecke , Jason Gerecke Subject: [PATCH v4 2/2] HID: wacom: Augment 'oVid' and 'oPid' with heuristics for HID_GENERIC Date: Mon, 8 Aug 2016 12:06:30 -0700 Message-Id: <20160808190630.7641-2-killertofu@gmail.com> X-Mailer: git-send-email 2.9.2 In-Reply-To: <20160808190630.7641-1-killertofu@gmail.com> References: <20160711180711.17537-1-killertofu@gmail.com> <20160808190630.7641-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 The 'oVid' and 'oPid' variables used by wacom_are_sibling are a hacky solution to the problem of the driver historically having few good heuristics to use in determining if two devices should be considered siblings or not. While it works well enough for explicitly supported devices, it offers no help for HID_GENERIC devices. Now that we have a bit more information (e.g. direct/indirect) available to us though, we should make use of it it to improve the pairing of such devices. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires --- Changes from v3: * No longer remove oVid/oPid checks and variables * Modified oVid/oPid checks to recognize HID_ANY_ID as a wildcard * Moved path check towards beginning of function as it is common between HID_GENERIC and explicitly-supported devices * Removed heuristic which required deviecs with different VID/PIDs to be direct input. drivers/hid/wacom_sys.c | 83 ++++++++++++++++++++++++++++++++++++++++++------- drivers/hid/wacom_wac.c | 2 +- 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index edde881..5e7a564 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -527,36 +527,95 @@ 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) { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_features *features = &wacom->wacom_wac.features; - int vid = features->oVid; - int pid = features->oPid; - int n1,n2; + struct wacom *sibling_wacom = hid_get_drvdata(sibling); + struct wacom_features *sibling_features = &sibling_wacom->wacom_wac.features; + __u32 oVid = features->oVid ? features->oVid : hdev->vendor; + __u32 oPid = features->oPid ? features->oPid : hdev->product; - if (vid == 0 && pid == 0) { - vid = hdev->vendor; - pid = hdev->product; + /* The defined oVid/oPid must match that of the sibling */ + if (features->oVid != HID_ANY_ID && sibling->vendor != oVid) + return false; + if (features->oPid != HID_ANY_ID && sibling->product != oPid) + return false; + + /* + * Devices with the same VID/PID must share the same physical + * device path, while those with different VID/PID must share + * the same physical parent device path. + */ + if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) { + if (!compare_device_paths(hdev, sibling, '/')) + return false; + } else { + if (!compare_device_paths(hdev, sibling, '.')) + return false; } - if (vid != sibling->vendor || pid != sibling->product) + /* Skip the remaining heuristics unless you are a HID_GENERIC device */ + if (features->type != HID_GENERIC) + return true; + + /* + * Direct-input devices may not be siblings of indirect-input + * devices. + */ + if ((features->device_type & WACOM_DEVICETYPE_DIRECT) && + !(sibling_features->device_type & WACOM_DEVICETYPE_DIRECT)) return false; - /* Compare the physical path. */ - n1 = strrchr(hdev->phys, '.') - hdev->phys; - n2 = strrchr(sibling->phys, '.') - sibling->phys; - if (n1 != n2 || n1 <= 0 || n2 <= 0) + /* + * Indirect-input devices may not be siblings of direct-input + * devices. + */ + if (!(features->device_type & WACOM_DEVICETYPE_DIRECT) && + (sibling_features->device_type & WACOM_DEVICETYPE_DIRECT)) + return false; + + /* Pen devices may only be siblings of touch devices */ + if ((features->device_type & WACOM_DEVICETYPE_PEN) && + !(sibling_features->device_type & WACOM_DEVICETYPE_TOUCH)) + return false; + + /* Touch devices may only be siblings of pen devices */ + if ((features->device_type & WACOM_DEVICETYPE_TOUCH) && + !(sibling_features->device_type & WACOM_DEVICETYPE_PEN)) return false; - return !strncmp(hdev->phys, sibling->phys, n1); + /* + * No reason could be found for these two devices to NOT be + * siblings, so there's a good chance they ARE siblings + */ + return true; } static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) { struct wacom_hdev_data *data; + /* 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, '/')) + return data; + } + + /* Fallback to finding devices that appear to be "siblings" */ list_for_each_entry(data, &wacom_udev_list, list) { if (wacom_are_sibling(hdev, data->dev)) { kref_get(&data->kref); diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index cfefed0..1b754b4 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -3521,7 +3521,7 @@ static const struct wacom_features wacom_features_0x343 = WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_HID_ANY_ID = - { "Wacom HID", .type = HID_GENERIC }; + { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; #define USB_DEVICE_WACOM(prod) \ HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\