From patchwork Mon Apr 4 18:26:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gerecke, Jason" X-Patchwork-Id: 8743601 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 619C4C0553 for ; Mon, 4 Apr 2016 18:27:20 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4F4FE2024F for ; Mon, 4 Apr 2016 18:27:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id EE04D20263 for ; Mon, 4 Apr 2016 18:27:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755584AbcDDS1Q (ORCPT ); Mon, 4 Apr 2016 14:27:16 -0400 Received: from mail-pa0-f65.google.com ([209.85.220.65]:35164 "EHLO mail-pa0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755557AbcDDS1Q (ORCPT ); Mon, 4 Apr 2016 14:27:16 -0400 Received: by mail-pa0-f65.google.com with SMTP id zy2so4292669pac.2 for ; Mon, 04 Apr 2016 11:27:15 -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=ErLBn3xh/0ZpTX8K9Eq/km7q6HTPbf0ed/7cT9e//p8=; b=ugLJDrv7U/mKWJKfHAHiloqXeRfo4+9d1OZNFTjIVb6m/WDuw51Gp4rxXfQKxbk8e6 dh6VTLcF65pJv5tADf1GeZYgQeGqhgXf4izQ0G/YzCYjvM+rdWZw4M1UOb4R42YBhFnL Yv+CAsg9G99oioj5hkn+IqZuNvaQm5QqFlH1bMpj7OMgCchf4CuoSleGZikl9AgYNtuK oif3XHiQ5AadTSxbjWL+BhwamDdBTOLrIlfIQZzst2elvguCxRRdTOzugPWGKkg0uhiX A0Ig1lkn7j+Dqj5dnJ8eqXXU/SPIJFOwW5wmO2x/1FVHtJ521zW1WpgRup7OuhL3L7jy CZsQ== 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=ErLBn3xh/0ZpTX8K9Eq/km7q6HTPbf0ed/7cT9e//p8=; b=flC5A47FFQ2UgJru1WPxKjKdzIco0GMV/MmjmmJYc3Pg6g5M1bDa1lyhtx/3WgvrWp 8gIM9yrcjAQ7vP1w7YnF9fUy2Crgubde1BdGYXGDRmEImRg8ChxCL52/CNaoTykv/AzH p4vrbqVjhBGmybIxN8dHSWvYxmqyEfUhMzdSRqemz4HckCbeMvoS/PLcrI/OnjfipbSc 6+fgHiaMDmXOHiuYQyuE4xxexfpZgDhDcJH87GvXhxZWQZgP5eDoNq62HFzJFJFl92dg aa+K9U8GunJ1ewaFPAHuVCIEb6bgmewteD/I003RV8do63ZPG0SzWMpdOtdVXR7nIKBA S/8Q== X-Gm-Message-State: AD7BkJIB05uEI1Zr25a4ty/vfo3JiOOrMtdFHhGsbrASm4HFjYmmNoFe7vijK6Scr1TUnw== X-Received: by 10.66.124.226 with SMTP id ml2mr54919280pab.90.1459794435170; Mon, 04 Apr 2016 11:27:15 -0700 (PDT) Received: from wacom-arch2.corp.onewacom.com ([67.51.163.2]) by smtp.gmail.com with ESMTPSA id q4sm41094424pfi.94.2016.04.04.11.27.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 04 Apr 2016 11:27:14 -0700 (PDT) From: Jason Gerecke To: linux-input@vger.kernel.org Cc: Benjamin Tissoires , Ping Cheng , Jiri Kosina , Jason Gerecke , Jason Gerecke Subject: [PATCH v2 2/2] HID: wacom: Support switching from vendor-defined device mode on G9 and G11 Date: Mon, 4 Apr 2016 11:26:52 -0700 Message-Id: <1459794412-10306-2-git-send-email-killertofu@gmail.com> X-Mailer: git-send-email 2.7.3 In-Reply-To: <1459794412-10306-1-git-send-email-killertofu@gmail.com> References: <56FD84F4.6060707@gmail.com> <1459794412-10306-1-git-send-email-killertofu@gmail.com> Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP A tablet PC booted into Windows may have its pen/touch hardware switched into "Wacom mode" similar to what we do with explicitly-supported hardware. Some devices appear to maintain this state across reboots, preventing their use with the generic HID driver. This patch adds support for detecting the presence of the mode switch feature report used by devices based on the G9 and G11 chips and has the HID codepath always attempt to reset the device back to sending standard HID reports. Fixes: https://sourceforge.net/p/linuxwacom/bugs/307/ Fixes: https://sourceforge.net/p/linuxwacom/bugs/310/ Fixes: https://github.com/linuxwacom/input-wacom/issues/15 Co-authored-by: Benjamin Tissoires Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires --- Changes from v1: * Incorporate Benjamin's feedback & suggested wacom_set_device_mode code drivers/hid/wacom_sys.c | 100 ++++++++++++++++++++++++++++++++++-------------- drivers/hid/wacom_wac.h | 8 ++++ 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index b338bbf..ccf1883 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -152,6 +152,25 @@ static void wacom_feature_mapping(struct hid_device *hdev, hid_data->inputmode = field->report->id; hid_data->inputmode_index = usage->usage_index; break; + + case HID_UP_DIGITIZER: + if (field->report->id == 0x0B && + (field->application == WACOM_G9_DIGITIZER || + field->application == WACOM_G11_DIGITIZER)) { + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value = 0; + } + break; + + case WACOM_G9_PAGE: + case WACOM_G11_PAGE: + if (field->report->id == 0x03 && + (field->application == WACOM_G9_TOUCHSCREEN || + field->application == WACOM_G11_TOUCHSCREEN)) { + wacom->wacom_wac.mode_report = field->report->id; + wacom->wacom_wac.mode_value = 0; + } + break; } } @@ -322,26 +341,41 @@ static int wacom_hid_set_device_mode(struct hid_device *hdev) return 0; } -static int wacom_set_device_mode(struct hid_device *hdev, int report_id, - int length, int mode) +static int wacom_set_device_mode(struct hid_device *hdev, + struct wacom_wac *wacom_wac) { - unsigned char *rep_data; + u8 *rep_data; + struct hid_report *r; + struct hid_report_enum *re; + int length; int error = -ENOMEM, limit = 0; - rep_data = kzalloc(length, GFP_KERNEL); + if (wacom_wac->mode_report < 0) + return 0; + + re = &(hdev->report_enum[HID_FEATURE_REPORT]); + r = re->report_id_hash[wacom_wac->mode_report]; + if (!r) + return -EINVAL; + + rep_data = hid_alloc_report_buf(r, GFP_KERNEL); if (!rep_data) - return error; + return -ENOMEM; + + length = hid_report_len(r); do { - rep_data[0] = report_id; - rep_data[1] = mode; + rep_data[0] = wacom_wac->mode_report; + rep_data[1] = wacom_wac->mode_value; error = wacom_set_report(hdev, HID_FEATURE_REPORT, rep_data, length, 1); if (error >= 0) error = wacom_get_report(hdev, HID_FEATURE_REPORT, rep_data, length, 1); - } while (error >= 0 && rep_data[1] != mode && limit++ < WAC_MSG_RETRIES); + } while (error >= 0 && + rep_data[1] != wacom_wac->mode_report && + limit++ < WAC_MSG_RETRIES); kfree(rep_data); @@ -411,32 +445,41 @@ static int wacom_bt_query_tablet_data(struct hid_device *hdev, u8 speed, static int wacom_query_tablet_data(struct hid_device *hdev, struct wacom_features *features) { + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + if (hdev->bus == BUS_BLUETOOTH) return wacom_bt_query_tablet_data(hdev, 1, features); - if (features->type == HID_GENERIC) - return wacom_hid_set_device_mode(hdev); - - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - if (features->type > TABLETPC) { - /* MT Tablet PC touch */ - return wacom_set_device_mode(hdev, 3, 4, 4); - } - else if (features->type == WACOM_24HDT) { - return wacom_set_device_mode(hdev, 18, 3, 2); - } - else if (features->type == WACOM_27QHDT) { - return wacom_set_device_mode(hdev, 131, 3, 2); - } - else if (features->type == BAMBOO_PAD) { - return wacom_set_device_mode(hdev, 2, 2, 2); - } - } else if (features->device_type & WACOM_DEVICETYPE_PEN) { - if (features->type <= BAMBOO_PT) { - return wacom_set_device_mode(hdev, 2, 2, 2); + if (features->type != HID_GENERIC) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { + if (features->type > TABLETPC) { + /* MT Tablet PC touch */ + wacom_wac->mode_report = 3; + wacom_wac->mode_value = 4; + } else if (features->type == WACOM_24HDT) { + wacom_wac->mode_report = 18; + wacom_wac->mode_value = 2; + } else if (features->type == WACOM_27QHDT) { + wacom_wac->mode_report = 131; + wacom_wac->mode_value = 2; + } else if (features->type == BAMBOO_PAD) { + wacom_wac->mode_report = 2; + wacom_wac->mode_value = 2; + } + } else if (features->device_type & WACOM_DEVICETYPE_PEN) { + if (features->type <= BAMBOO_PT) { + wacom_wac->mode_report = 2; + wacom_wac->mode_value = 2; + } } } + wacom_set_device_mode(hdev, wacom_wac); + + if (features->type == HID_GENERIC) + return wacom_hid_set_device_mode(hdev); + return 0; } @@ -1818,6 +1861,7 @@ static int wacom_probe(struct hid_device *hdev, } wacom_wac->hid_data.inputmode = -1; + wacom_wac->mode_report = -1; wacom->usbdev = dev; wacom->intf = intf; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 25baa7f..e2084d9 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -84,6 +84,12 @@ #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 #define WACOM_VENDORDEFINED_PEN 0xff0d0001 +#define WACOM_G9_PAGE 0xff090000 +#define WACOM_G9_DIGITIZER (WACOM_G9_PAGE | 0x02) +#define WACOM_G9_TOUCHSCREEN (WACOM_G9_PAGE | 0x11) +#define WACOM_G11_PAGE 0xff110000 +#define WACOM_G11_DIGITIZER (WACOM_G11_PAGE | 0x02) +#define WACOM_G11_TOUCHSCREEN (WACOM_G11_PAGE | 0x11) #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ @@ -238,6 +244,8 @@ struct wacom_wac { int ps_connected; u8 bt_features; u8 bt_high_speed; + int mode_report; + int mode_value; struct hid_data hid_data; };