From patchwork Sun Feb 10 10:13:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nikolai Kondrashov X-Patchwork-Id: 10804681 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9550713B4 for ; Sun, 10 Feb 2019 10:14:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 85DEC29F45 for ; Sun, 10 Feb 2019 10:14:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7A64329F4A; Sun, 10 Feb 2019 10:14:59 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI 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 D38C329F45 for ; Sun, 10 Feb 2019 10:14:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726039AbfBJKO4 (ORCPT ); Sun, 10 Feb 2019 05:14:56 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:45647 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726005AbfBJKO4 (ORCPT ); Sun, 10 Feb 2019 05:14:56 -0500 Received: by mail-lf1-f67.google.com with SMTP id b20so5563476lfa.12 for ; Sun, 10 Feb 2019 02:14:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=uY10ww5hzdghirBbKuQUXgFqVULtl4pVHo9UL7xgc9o=; b=tJaaiarmAwwikvvghzLDABlW9acBRqd4kNZTN59BPMTmsZUoZvjS3eDZxlwe0byYvj l5jPhsfZYKdFtKzGGK0lpmAhTw+y4iLEw9L+gBAZWOEY89eoQgs7sQd64VpEAuBRC0+K h2VfQE/yWLssklCNIgC3oYx9f2yIRkEV6D0nw3qty7ckCmecD65nE1tlGwYDZO/+lpin mrUSiz462O5W4ncv1sImdMHd6rxaYSU2O9jpIQBFoYOAf6daz81QHOO+WqMLaY9ie6nB fAIO1W8ryziC9IfpggRjI6EmkybnuPpIdrLJb5dMRhz403iNbfYr3tI+o8YTPqPGITJW pniQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uY10ww5hzdghirBbKuQUXgFqVULtl4pVHo9UL7xgc9o=; b=ptWx/FWrND8tZaIMTb+2k2/a0TXELOuFw2tjCYK0y0dx2GsMxYZdzj40ukpVifCLPm RtrZKcSpzwg7A6StIqEHmnYkytFq2IujjRlccnyhjXSJDbESI1BzM4SEGrfeDma4j4Ye pS8ltT877n26uFnflT54gPvAcksJFroIejOsFHLIR8vwbKRXN18NtZ08t6ZWekdINm19 mj1J36SHKGtkT5IElsBzGJrVvCShdciAcMz00X2KKpIXJUbWICIwtf63S89QZG2QJmLI 7jRvYHDrC+Rz7dAp3PjAcoC5yVMz8ntAapnxcUeKbO5d0AyiwU4oJl36PiWswOWOIErI Tbsg== X-Gm-Message-State: AHQUAuYYfuRnwiSV+qWLDEQtIgOEAyQXELt8GDlblYIXSK9OmKhsslut kIDRA2ddUxxgXDLHcfrhtho= X-Google-Smtp-Source: AHgI3IbuC72jo0RYi6aaavgqVwuT6LsFZFC1TGJOFNoqzkZgg4P6Hi7nU+gLw6UIvOuwepojXZMAxw== X-Received: by 2002:ac2:520f:: with SMTP id a15mr12930388lfl.110.1549793693114; Sun, 10 Feb 2019 02:14:53 -0800 (PST) Received: from bard.ponomarevs.fi (88-112-122-53.elisa-laajakaista.fi. [88.112.122.53]) by smtp.gmail.com with ESMTPSA id l21-v6sm1472010ljj.48.2019.02.10.02.14.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 10 Feb 2019 02:14:52 -0800 (PST) From: Nikolai Kondrashov To: Benjamin Tissoires Cc: Jiri Kosina , linux-input@vger.kernel.org, Nikolai Kondrashov Subject: [PATCH v2 08/23] HID: uclogic: Support in-range reporting emulation Date: Sun, 10 Feb 2019 12:13:54 +0200 Message-Id: <20190210101409.3511-9-spbnick@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190210101409.3511-1-spbnick@gmail.com> References: <20181227171625.11164-1-spbnick@gmail.com> <20190210101409.3511-1-spbnick@gmail.com> MIME-Version: 1.0 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 Newer UC-Logic tablets, such as ones made by Huion have stopped reporting in-range state, but they're otherwise worthy tablets. The manufacturer was notified of the problem and promised to fix this in the future. Meanwhile, detect pen coming in range, and emulate the reports to the userspace, to make the tablets useable. Signed-off-by: Nikolai Kondrashov --- drivers/hid/hid-uclogic-core.c | 54 ++++++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-params.c | 2 ++ drivers/hid/hid-uclogic-params.h | 2 ++ 3 files changed, 58 insertions(+) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 8f8e445d77aa..206642802ca5 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "usbhid/usbhid.h" #include "hid-uclogic-params.h" @@ -32,8 +33,40 @@ struct uclogic_drvdata { * Only valid if desc_ptr is not NULL */ unsigned int desc_size; + /* Pen input device */ + struct input_dev *pen_input; + /* In-range timer */ + struct timer_list inrange_timer; }; +/** + * uclogic_inrange_timeout - handle pen in-range state timeout. + * Emulate input events normally generated when pen goes out of range for + * tablets which don't report that. + * + * @t: The timer the timeout handler is attached to, stored in a struct + * uclogic_drvdata. + */ +static void uclogic_inrange_timeout(struct timer_list *t) +{ + struct uclogic_drvdata *drvdata = from_timer(drvdata, t, + inrange_timer); + struct input_dev *input = drvdata->pen_input; + + if (input == NULL) + return; + input_report_abs(input, ABS_PRESSURE, 0); + /* If BTN_TOUCH state is changing */ + if (test_bit(BTN_TOUCH, input->key)) { + input_event(input, EV_MSC, MSC_SCAN, + /* Digitizer Tip Switch usage */ + 0xd0042); + input_report_key(input, BTN_TOUCH, 0); + } + input_report_key(input, BTN_TOOL_PEN, 0); + input_sync(input); +} + static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { @@ -67,6 +100,8 @@ static int uclogic_input_mapping(struct hid_device *hdev, static int uclogic_input_configured(struct hid_device *hdev, struct hid_input *hi) { + struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); + struct uclogic_params *params = &drvdata->params; char *name; const char *suffix = NULL; struct hid_field *field; @@ -76,6 +111,15 @@ static int uclogic_input_configured(struct hid_device *hdev, if (!hi->report) return 0; + /* + * If this is the input corresponding to the pen report + * in need of tweaking. + */ + if (hi->report->id == params->pen.id) { + /* Remember the input device so we can simulate events */ + drvdata->pen_input = hi->input; + } + field = hi->report->field[0]; switch (field->application) { @@ -130,6 +174,7 @@ static int uclogic_probe(struct hid_device *hdev, rc = -ENOMEM; goto failure; } + timer_setup(&drvdata->inrange_timer, uclogic_inrange_timeout, 0); hid_set_drvdata(hdev, drvdata); /* Initialize the device and retrieve interface parameters */ @@ -220,6 +265,14 @@ static int uclogic_raw_event(struct hid_device *hdev, /* Invert the in-range bit */ data[1] ^= 0x40; } + /* If we need to emulate in-range detection */ + if (params->pen.inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE) { + /* Set in-range bit */ + data[1] |= 0x40; + /* (Re-)start in-range timeout */ + mod_timer(&drvdata->inrange_timer, + jiffies + msecs_to_jiffies(100)); + } } return 0; @@ -229,6 +282,7 @@ static void uclogic_remove(struct hid_device *hdev) { struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); + del_timer_sync(&drvdata->inrange_timer); hid_hw_stop(hdev); kfree(drvdata->desc_ptr); uclogic_params_cleanup(&drvdata->params); diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index f555db120baa..b5e4d99c6771 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -36,6 +36,8 @@ const char *uclogic_params_pen_inrange_to_str( return "normal"; case UCLOGIC_PARAMS_PEN_INRANGE_INVERTED: return "inverted"; + case UCLOGIC_PARAMS_PEN_INRANGE_NONE: + return "none"; default: return NULL; } diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index 4c78d9dd0576..665954d6ba57 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -25,6 +25,8 @@ enum uclogic_params_pen_inrange { UCLOGIC_PARAMS_PEN_INRANGE_NORMAL = 0, /* Inverted reports: zero - in proximity, one - out of proximity */ UCLOGIC_PARAMS_PEN_INRANGE_INVERTED, + /* No reports */ + UCLOGIC_PARAMS_PEN_INRANGE_NONE, }; /* Convert a pen in-range reporting type to a string */