From patchwork Tue May 31 18:12:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= X-Patchwork-Id: 12865992 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2241CC433F5 for ; Tue, 31 May 2022 18:13:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346862AbiEaSNM (ORCPT ); Tue, 31 May 2022 14:13:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234110AbiEaSNK (ORCPT ); Tue, 31 May 2022 14:13:10 -0400 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F92F6D4FC; Tue, 31 May 2022 11:13:09 -0700 (PDT) Received: by mail-wr1-x42d.google.com with SMTP id t13so19754821wrg.9; Tue, 31 May 2022 11:13:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=3PjQuKMkTY1kyPsdXkRWcy11RqWiSJraBoDtsiZIFcs=; b=TKyPtDeTNDurvg6aa1W85kmFpngzEdU4lo1HJ1xnsO8V9Y4nVQr99wwUIvwJKqmcF/ egGtXPscHlKo678BdGi5dE6FICZUCtapVWvPqjkIxk4+8E7zX8Bmk4+qE7WXmPgxkzsd wYWgMlu2re1N9yn7Niwnel4ejQNjP/X6Lsf1GWNszLYsNaij40yxvu2SX4YxbnEjEOfW ZZfLdALG/lwctZtt5W3+LG9gbfaOXVRGv1TK7NEIzv3fQ38OhSOmF5ataM3R7MrUtIj1 WRH34Q+MTwvLVtlHce1NJGcSaka9NdbpfBu1M98DZ1nIMAIsVuNL6PrKeGASJjGRsQoP xoug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=3PjQuKMkTY1kyPsdXkRWcy11RqWiSJraBoDtsiZIFcs=; b=WKZtlAH/v+VjJsiFQ7h8mgoWWTzDzsGZohOOEnzyDCMtzw12T0y1vEGJns9ZtNLtoe dvFojj+rAjQ6R+pkqnDb75WMpixe3Bk/lkx4eBKXlNO8M1ee2t/nWww9Ee89upkjBA+f bE5/8dlOIBQSIHgmXeLgnbW4vZzzj9G5ZWvusFhV0j2xCQk6OWF5gtlnDzi7jsKq94PP 5FNYAKnLVjGvPjTWjR2ImC27pYZeVIxl2WVfgnbLfJryasEF6/y1V0R4RNf+R5m9R3i6 6N3NKZCxF31PmzWvtuGz/sLA11YqHDSEpym4DJVP1vnA8uqCtqnD65p5D6wwWyVz06do 6VzA== X-Gm-Message-State: AOAM530lMH+F/8l097XUA1+CVm/xUlRZBMkYYJSb0RdzzuD9BM9lf6N9 CFQEaPnjh8TKYZlagzqO5qU= X-Google-Smtp-Source: ABdhPJxdndH3g1I3JVpMpNaVItag00WHsCBZzod+SM9b7iUFSGAFzAVd2WEA2TZ9m+wkCXI+1GhlTw== X-Received: by 2002:a5d:6845:0:b0:210:635:9c1b with SMTP id o5-20020a5d6845000000b0021006359c1bmr24650856wrw.551.1654020787914; Tue, 31 May 2022 11:13:07 -0700 (PDT) Received: from localhost.localdomain ([94.73.36.128]) by smtp.gmail.com with ESMTPSA id i12-20020a05600c354c00b0039765a7add4sm3099597wmq.29.2022.05.31.11.13.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 11:13:07 -0700 (PDT) From: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= To: jikos@kernel.org Cc: benjamin.tissoires@redhat.com, spbnick@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, stefanberzl@gmail.com, dlatypov@google.com, kunit-dev@googlegroups.com, =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= Subject: [PATCH v3 1/4] HID: uclogic: Make template placeholder IDs generic Date: Tue, 31 May 2022 20:12:43 +0200 Message-Id: <20220531181246.190729-2-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220531181246.190729-1-jose.exposito89@gmail.com> References: <20220531181246.190729-1-jose.exposito89@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Up until now, the report descriptor template parameter IDs were only used with pen report descriptors and they were named accordingly. Rename the enum and the total number of IDs to make them interface agnostic. Refactor, no functional changes. Signed-off-by: José Expósito --- drivers/hid/hid-uclogic-params.c | 4 ++-- drivers/hid/hid-uclogic-rdesc.c | 14 +++++++------- drivers/hid/hid-uclogic-rdesc.h | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index db838f16282d..b43142f98a8b 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -234,7 +234,7 @@ static int uclogic_params_pen_init_v1(struct uclogic_params_pen *pen, const int len = 12; s32 resolution; /* Pen report descriptor template parameters */ - s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; __u8 *desc_ptr = NULL; /* Check arguments */ @@ -379,7 +379,7 @@ static int uclogic_params_pen_init_v2(struct uclogic_params_pen *pen, size_t i; s32 resolution; /* Pen report descriptor template parameters */ - s32 desc_params[UCLOGIC_RDESC_PEN_PH_ID_NUM]; + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; __u8 *desc_ptr = NULL; /* Check arguments */ diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 13f9ce73f1b1..7126fba80968 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -979,7 +979,7 @@ const size_t uclogic_rdesc_xppen_deco01_frame_size = * uclogic_rdesc_template_apply() - apply report descriptor parameters to a * report descriptor template, creating a report descriptor. Copies the * template over to the new report descriptor and replaces every occurrence of - * UCLOGIC_RDESC_PH_HEAD, followed by an index byte, with the value from the + * UCLOGIC_RDESC_PEN_PH_HEAD, followed by an index byte, with the value from the * parameter list at that index. * * @template_ptr: Pointer to the template buffer. @@ -996,7 +996,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, const s32 *param_list, size_t param_num) { - static const __u8 head[] = {UCLOGIC_RDESC_PH_HEAD}; + static const __u8 pen_head[] = {UCLOGIC_RDESC_PEN_PH_HEAD}; __u8 *rdesc_ptr; __u8 *p; s32 v; @@ -1005,12 +1005,12 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, if (rdesc_ptr == NULL) return NULL; - for (p = rdesc_ptr; p + sizeof(head) < rdesc_ptr + template_size;) { - if (memcmp(p, head, sizeof(head)) == 0 && - p[sizeof(head)] < param_num) { - v = param_list[p[sizeof(head)]]; + for (p = rdesc_ptr; p + sizeof(pen_head) < rdesc_ptr + template_size;) { + if (memcmp(p, pen_head, sizeof(pen_head)) == 0 && + p[sizeof(pen_head)] < param_num) { + v = param_list[p[sizeof(pen_head)]]; put_unaligned(cpu_to_le32(v), (s32 *)p); - p += sizeof(head) + 1; + p += sizeof(pen_head) + 1; } else { p++; } diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 0c6e95e8bde7..9d37090c39d1 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -81,7 +81,7 @@ extern __u8 uclogic_rdesc_twha60_fixed1_arr[]; extern const size_t uclogic_rdesc_twha60_fixed1_size; /* Report descriptor template placeholder head */ -#define UCLOGIC_RDESC_PH_HEAD 0xFE, 0xED, 0x1D +#define UCLOGIC_RDESC_PEN_PH_HEAD 0xFE, 0xED, 0x1D /* Apply report descriptor parameters to a report descriptor template */ extern __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, @@ -89,19 +89,19 @@ extern __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, const s32 *param_list, size_t param_num); -/* Pen report descriptor template placeholder IDs */ -enum uclogic_rdesc_pen_ph_id { +/* Report descriptor template placeholder IDs */ +enum uclogic_rdesc_ph_id { UCLOGIC_RDESC_PEN_PH_ID_X_LM, UCLOGIC_RDESC_PEN_PH_ID_X_PM, UCLOGIC_RDESC_PEN_PH_ID_Y_LM, UCLOGIC_RDESC_PEN_PH_ID_Y_PM, UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM, - UCLOGIC_RDESC_PEN_PH_ID_NUM + UCLOGIC_RDESC_PH_ID_NUM }; /* Report descriptor pen template placeholder */ #define UCLOGIC_RDESC_PEN_PH(_ID) \ - UCLOGIC_RDESC_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID + UCLOGIC_RDESC_PEN_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID /* Report ID for v1 pen reports */ #define UCLOGIC_RDESC_V1_PEN_ID 0x07 From patchwork Tue May 31 18:12:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= X-Patchwork-Id: 12865993 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E1FBC433EF for ; Tue, 31 May 2022 18:13:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234110AbiEaSNU (ORCPT ); Tue, 31 May 2022 14:13:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58244 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241608AbiEaSNT (ORCPT ); Tue, 31 May 2022 14:13:19 -0400 Received: from mail-wm1-x336.google.com (mail-wm1-x336.google.com [IPv6:2a00:1450:4864:20::336]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D09C67C158; Tue, 31 May 2022 11:13:17 -0700 (PDT) Received: by mail-wm1-x336.google.com with SMTP id o9so8490936wmd.0; Tue, 31 May 2022 11:13:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jtmTcBRIdpzV+swCaGH4uSR7xbbrrtdxOoQw4wh/s5o=; b=JnLx5hXoybRyGwZh/FmTB1kIoiXatFYlMvvFK9Mb0iAmeFOpMj+Qeuj6JutfoUUfAS Wul32wB1jx00PpiPVutJ2BvIAGrIS2kdTGO23mWCs0OU7QKNicaXCQffNGMrrPNYgdzp OWmcwQzprW4HvoZa5dMD2XjamgMT00mt6MYS7l+TC/ISUXsp6bhv7pQtcBq8UReFvyil kdk8bxywq+mQdmjwOXZvNOvwTNEYXzZY8PupDuUwOMZS+upCdTwpycpiiBqAJbEC3by/ R6HWRZtxxQtlFJo2B2bR7kM7zSTGnj6dQ7V0gkZrn0f5iMe8s9qtRxRC4KMRlta/OjKB TeUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jtmTcBRIdpzV+swCaGH4uSR7xbbrrtdxOoQw4wh/s5o=; b=lFB1gFyeVwOr9EH28w/6my2oBxRPTIfLArBqj8PtYlx9RIFXpQZDPYmqUY0J05alBy CeNqgqZk0MNJtfB7cWL6YKMIOtQ2zmfQH1Hc0TPf86VG55XEgaPdjAPpdAtLyFCqL49E JnktTIyVrX3Z2S75Z35ZNtp+mjOUsPUu0sZFuGQ8HbBXjfkOS6g28C6VsnfQdm4zHG9/ rTjJhs0AoQEperSawtT7l6BGqjH07DBUg3T+zDE32uK6YKparPeT/vr/I3ElOnnCu5PX BwUgqU37pVcx9XsvrDKDDJXO40tI95y0WjWhEFga9ISNWcbfr+LCSzeUD31Hk5tkjFvU k2BA== X-Gm-Message-State: AOAM531N/v1ZXVvLvIf60IDB8xbqVJ5yUrW+pSJ8tUBmjbdN435W/ecx dBbvD796vLy2AIS2p7aMJX4= X-Google-Smtp-Source: ABdhPJw10l+rIlAxGR3tTNBMwgesrlo3aPXEOMuMJO7CwVhCVHETuY5rheByaOaEZFVHERu/jhe2Kw== X-Received: by 2002:a05:600c:190d:b0:394:8241:6454 with SMTP id j13-20020a05600c190d00b0039482416454mr25168195wmq.198.1654020796403; Tue, 31 May 2022 11:13:16 -0700 (PDT) Received: from localhost.localdomain ([94.73.36.128]) by smtp.gmail.com with ESMTPSA id i12-20020a05600c354c00b0039765a7add4sm3099597wmq.29.2022.05.31.11.13.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 11:13:16 -0700 (PDT) From: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= To: jikos@kernel.org Cc: benjamin.tissoires@redhat.com, spbnick@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, stefanberzl@gmail.com, dlatypov@google.com, kunit-dev@googlegroups.com, =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= Subject: [PATCH v3 2/4] HID: uclogic: Add KUnit tests for uclogic_rdesc_template_apply() Date: Tue, 31 May 2022 20:12:44 +0200 Message-Id: <20220531181246.190729-3-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220531181246.190729-1-jose.exposito89@gmail.com> References: <20220531181246.190729-1-jose.exposito89@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org The uclogic_rdesc_template_apply() function is used by the driver to generate HID descriptors from templates. In order to avoid regressions in future patches, add KUnit tests to test the function. Signed-off-by: José Expósito --- drivers/hid/.kunitconfig | 2 + drivers/hid/Kconfig | 11 ++ drivers/hid/Makefile | 3 + drivers/hid/hid-uclogic-rdesc-test.c | 183 +++++++++++++++++++++++++++ 4 files changed, 199 insertions(+) create mode 100644 drivers/hid/.kunitconfig create mode 100644 drivers/hid/hid-uclogic-rdesc-test.c diff --git a/drivers/hid/.kunitconfig b/drivers/hid/.kunitconfig new file mode 100644 index 000000000000..c784d098aba9 --- /dev/null +++ b/drivers/hid/.kunitconfig @@ -0,0 +1,2 @@ +CONFIG_KUNIT=y +CONFIG_HID_UCLOGIC_KUNIT_TEST=y diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 70da5931082f..d7229ad7d0d4 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -469,6 +469,17 @@ config HID_UCLOGIC help Support for UC-Logic and Huion tablets. +config HID_UCLOGIC_KUNIT_TEST + bool "UC-Logic tests" if !KUNIT_ALL_TESTS + depends on KUNIT=y + default KUNIT_ALL_TESTS + help + KUnit tests for the UC-Logic driver. This option is not + useful for distributions or general kernels, recommended + for driver developers only. + + If in doubt, say "N". + config HID_WALTOP tristate "Waltop" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index cac2cbe26d11..76d7ff89a26c 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -129,6 +129,9 @@ hid-uclogic-objs := hid-uclogic-core.o \ hid-uclogic-rdesc.o \ hid-uclogic-params.o obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o +obj-$(CONFIG_HID_UCLOGIC_KUNIT_TEST) += hid-uclogic-rdesc.o \ + hid-uclogic-rdesc-test.o +CFLAGS_hid-uclogic-rdesc-test.o += $(DISABLE_STRUCTLEAK_PLUGIN) obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o obj-$(CONFIG_HID_LED) += hid-led.o obj-$(CONFIG_HID_XIAOMI) += hid-xiaomi.o diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c new file mode 100644 index 000000000000..ded59e226230 --- /dev/null +++ b/drivers/hid/hid-uclogic-rdesc-test.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/* + * HID driver for UC-Logic devices not fully compliant with HID standard + * + * Copyright (c) 2022 José Expósito + */ + +#include +#include "./hid-uclogic-rdesc.h" + +struct uclogic_template_case { + const char *name; + const __u8 *template; + size_t template_size; + const s32 *param_list; + size_t param_num; + const __u8 *expected; +}; + +static const s32 params_pen_all[UCLOGIC_RDESC_PH_ID_NUM] = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xAA, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0xBB, + [UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0xCC, + [UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0xDD, + [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0xEE, +}; + +static const s32 params_pen_some[] = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xAA, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0xBB, +}; + +static const __u8 template_empty[] = { }; +static const __u8 template_small[] = { 0x00 }; +static const __u8 template_no_ph[] = { 0xAA, 0xFE, 0xAA, 0xED, 0x1D }; + +static const __u8 template_pen_ph_end[] = { + 0xAA, 0xBB, UCLOGIC_RDESC_PEN_PH_HEAD +}; + +static const __u8 template_pen_all_params[] = { + UCLOGIC_RDESC_PEN_PH(X_LM), + 0x47, UCLOGIC_RDESC_PEN_PH(X_PM), + 0x27, UCLOGIC_RDESC_PEN_PH(Y_LM), + UCLOGIC_RDESC_PEN_PH(Y_PM), + 0x00, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM), +}; + +static const __u8 expected_pen_all_params[] = { + 0xAA, 0x00, 0x00, 0x00, + 0x47, 0xBB, 0x00, 0x00, 0x00, + 0x27, 0xCC, 0x00, 0x00, 0x00, + 0xDD, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, +}; + +static const __u8 template_pen_some_params[] = { + 0x01, 0x02, + UCLOGIC_RDESC_PEN_PH(X_LM), + 0x03, UCLOGIC_RDESC_PEN_PH(X_PM), + 0x04, 0x05, +}; + +static const __u8 expected_pen_some_params[] = { + 0x01, 0x02, + 0xAA, 0x00, 0x00, 0x00, + 0x03, 0xBB, 0x00, 0x00, 0x00, + 0x04, 0x05, +}; + +static const __u8 template_params_none[] = { + 0x27, UCLOGIC_RDESC_PEN_PH(Y_LM), + UCLOGIC_RDESC_PEN_PH(Y_PM), + 0x00, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM), +}; + +static struct uclogic_template_case uclogic_template_cases[] = { + { + .name = "Empty template", + .template = template_empty, + .template_size = sizeof(template_empty), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = template_empty, + }, + { + .name = "Template smaller than the placeholder", + .template = template_small, + .template_size = sizeof(template_small), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = template_small, + }, + { + .name = "No placeholder", + .template = template_no_ph, + .template_size = sizeof(template_no_ph), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = template_no_ph, + }, + { + .name = "Pen placeholder at the end, without ID", + .template = template_pen_ph_end, + .template_size = sizeof(template_pen_ph_end), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = template_pen_ph_end, + }, + { + .name = "All params present in the pen template", + .template = template_pen_all_params, + .template_size = sizeof(template_pen_all_params), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = expected_pen_all_params, + }, + { + .name = "Some params present in the pen template (complete param list)", + .template = template_pen_some_params, + .template_size = sizeof(template_pen_some_params), + .param_list = params_pen_all, + .param_num = ARRAY_SIZE(params_pen_all), + .expected = expected_pen_some_params, + }, + { + .name = "Some params present in the pen template (incomplete param list)", + .template = template_pen_some_params, + .template_size = sizeof(template_pen_some_params), + .param_list = params_pen_some, + .param_num = ARRAY_SIZE(params_pen_some), + .expected = expected_pen_some_params, + }, + { + .name = "No params present in the template", + .template = template_params_none, + .template_size = sizeof(template_params_none), + .param_list = params_pen_some, + .param_num = ARRAY_SIZE(params_pen_some), + .expected = template_params_none, + }, +}; + +static void uclogic_template_case_desc(struct uclogic_template_case *t, + char *desc) +{ + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(uclogic_template, uclogic_template_cases, + uclogic_template_case_desc); + +static void uclogic_template_test(struct kunit *test) +{ + __u8 *res; + const struct uclogic_template_case *params = test->param_value; + + res = uclogic_rdesc_template_apply(params->template, + params->template_size, + params->param_list, + params->param_num); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res); + KUNIT_EXPECT_EQ(test, 0, + memcmp(res, params->expected, params->template_size)); + kfree(res); +} + +static struct kunit_case hid_uclogic_rdesc_test_cases[] = { + KUNIT_CASE_PARAM(uclogic_template_test, uclogic_template_gen_params), + {} +}; + +static struct kunit_suite hid_uclogic_rdesc_test_suite = { + .name = "hid-uclogic-rdesc-test", + .test_cases = hid_uclogic_rdesc_test_cases, +}; + +kunit_test_suite(hid_uclogic_rdesc_test_suite); + +MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("José Expósito "); From patchwork Tue May 31 18:12:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= X-Patchwork-Id: 12865994 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D192C433F5 for ; Tue, 31 May 2022 18:13:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346887AbiEaSN2 (ORCPT ); Tue, 31 May 2022 14:13:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58624 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241608AbiEaSNY (ORCPT ); Tue, 31 May 2022 14:13:24 -0400 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 36B147E1F7; Tue, 31 May 2022 11:13:19 -0700 (PDT) Received: by mail-wm1-x331.google.com with SMTP id n124-20020a1c2782000000b003972dfca96cso1647903wmn.4; Tue, 31 May 2022 11:13:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aAr8shjvKRcCfv7HNBBK8SL5xstDJCBPnCo1qU9xjjY=; b=CD3nqGmpYhCWGbRlxJKXtwhrevKBn43+OH2gSK/HC2Dma2Mm818kiFBwgrkFKFDnJu K8KsA36cFbAmwQFHLPrhmnX0NGBMvxKHQSITHNQ2jp0GcDfOg1cwhbnu3ots4Cu4C9Vm 2Hdjfhxh4IOFqt90CaJ5o+LN/XMNDlOXHkj3iCDP24zWMNX2qfynocBKj0gC2wq+w0Mg sHu/Xsn1Uq8iVQB54lD4l0eMhPtQwZM+0SyqIIxe4uqF9Moc1OWN2VyWE9ThlNGAYZTE oWKlwfH/7kHXe1pesmYrPsqBdn7VhS4naZ/MyEqPgjxsGr1R/SzqMHG6CtIPbTTwYFkW tr2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aAr8shjvKRcCfv7HNBBK8SL5xstDJCBPnCo1qU9xjjY=; b=l18RcnxuPBnGxDKfsEoJ46+ILlUdf3UAWqE1492lE+H1zV9XbJCdUlJoorlUlbWFCd +Jw5fT9Y7hEBdtP9R9yJ4RyxhRnpgOteIBDOIsw9u8mBtO/6+J2izrr+wLSodjU+ocqE fpBa8Slds0b72E1lnGKstTkqbG1o5qFDp6UpoRoKzo78RqN6t7mm9yYjw+9Ppy1ugJzo h6MBp8i1z4qRmS1J8zxOB4Rssf4L5nRqZjJnY5h9DK9KIypdtM9gOABF29ygtzpoLlEI YLHLsZiS8Owr9fRrFFj7j/p1oBgaIPuPMV8W/Cy838O70cFhouXpLrQPU4K2eCA5uCuL v54Q== X-Gm-Message-State: AOAM530eXB88V2JVeROFq9XHsLIUeYfNUe1QtF5YWUeLJHLGVKhnstHT HbGARC7lNiR9GdFUZXIjxQY= X-Google-Smtp-Source: ABdhPJyg+lvntDq9wQYXblT8ZildvAM3vqQDVl8yG4X25FykKXXjJyuMY1t1UHi4kc52GDF3LEELbQ== X-Received: by 2002:a05:600c:4618:b0:397:84aa:5585 with SMTP id m24-20020a05600c461800b0039784aa5585mr22708298wmo.21.1654020797746; Tue, 31 May 2022 11:13:17 -0700 (PDT) Received: from localhost.localdomain ([94.73.36.128]) by smtp.gmail.com with ESMTPSA id i12-20020a05600c354c00b0039765a7add4sm3099597wmq.29.2022.05.31.11.13.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 11:13:17 -0700 (PDT) From: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= To: jikos@kernel.org Cc: benjamin.tissoires@redhat.com, spbnick@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, stefanberzl@gmail.com, dlatypov@google.com, kunit-dev@googlegroups.com, =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= Subject: [PATCH v3 3/4] HID: uclogic: Allow to generate frame templates Date: Tue, 31 May 2022 20:12:45 +0200 Message-Id: <20220531181246.190729-4-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220531181246.190729-1-jose.exposito89@gmail.com> References: <20220531181246.190729-1-jose.exposito89@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add a new template placeholder to allow configuring the number of buttons in the drawing tablet frame and update the KUnit tests to cover the new case. Signed-off-by: José Expósito --- drivers/hid/hid-uclogic-rdesc-test.c | 36 ++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.c | 14 ++++++++--- drivers/hid/hid-uclogic-rdesc.h | 6 +++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c index ded59e226230..ebebffef5f8a 100644 --- a/drivers/hid/hid-uclogic-rdesc-test.c +++ b/drivers/hid/hid-uclogic-rdesc-test.c @@ -31,6 +31,10 @@ static const s32 params_pen_some[] = { [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0xBB, }; +static const s32 params_frame_all[UCLOGIC_RDESC_PH_ID_NUM] = { + [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0xFF, +}; + static const __u8 template_empty[] = { }; static const __u8 template_small[] = { 0x00 }; static const __u8 template_no_ph[] = { 0xAA, 0xFE, 0xAA, 0xED, 0x1D }; @@ -39,6 +43,10 @@ static const __u8 template_pen_ph_end[] = { 0xAA, 0xBB, UCLOGIC_RDESC_PEN_PH_HEAD }; +static const __u8 template_btn_ph_end[] = { + 0xAA, 0xBB, UCLOGIC_RDESC_FRAME_PH_BTN_HEAD +}; + static const __u8 template_pen_all_params[] = { UCLOGIC_RDESC_PEN_PH(X_LM), 0x47, UCLOGIC_RDESC_PEN_PH(X_PM), @@ -55,6 +63,18 @@ static const __u8 expected_pen_all_params[] = { 0x00, 0xEE, 0x00, 0x00, 0x00, }; +static const __u8 template_frame_all_params[] = { + 0x01, 0x02, + UCLOGIC_RDESC_FRAME_PH_BTN, + 0x99, +}; + +static const __u8 expected_frame_all_params[] = { + 0x01, 0x02, + 0x2A, 0xFF, 0x00, + 0x99, +}; + static const __u8 template_pen_some_params[] = { 0x01, 0x02, UCLOGIC_RDESC_PEN_PH(X_LM), @@ -108,6 +128,14 @@ static struct uclogic_template_case uclogic_template_cases[] = { .param_num = ARRAY_SIZE(params_pen_all), .expected = template_pen_ph_end, }, + { + .name = "Frame button placeholder at the end, without ID", + .template = template_btn_ph_end, + .template_size = sizeof(template_btn_ph_end), + .param_list = params_frame_all, + .param_num = ARRAY_SIZE(params_frame_all), + .expected = template_btn_ph_end, + }, { .name = "All params present in the pen template", .template = template_pen_all_params, @@ -116,6 +144,14 @@ static struct uclogic_template_case uclogic_template_cases[] = { .param_num = ARRAY_SIZE(params_pen_all), .expected = expected_pen_all_params, }, + { + .name = "All params present in the frame template", + .template = template_frame_all_params, + .template_size = sizeof(template_frame_all_params), + .param_list = params_frame_all, + .param_num = ARRAY_SIZE(params_frame_all), + .expected = expected_frame_all_params, + }, { .name = "Some params present in the pen template (complete param list)", .template = template_pen_some_params, diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 7126fba80968..3fb84ac492b4 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -979,7 +979,7 @@ const size_t uclogic_rdesc_xppen_deco01_frame_size = * uclogic_rdesc_template_apply() - apply report descriptor parameters to a * report descriptor template, creating a report descriptor. Copies the * template over to the new report descriptor and replaces every occurrence of - * UCLOGIC_RDESC_PEN_PH_HEAD, followed by an index byte, with the value from the + * the template placeholders, followed by an index byte, with the value from the * parameter list at that index. * * @template_ptr: Pointer to the template buffer. @@ -996,6 +996,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, const s32 *param_list, size_t param_num) { + static const __u8 btn_head[] = {UCLOGIC_RDESC_FRAME_PH_BTN_HEAD}; static const __u8 pen_head[] = {UCLOGIC_RDESC_PEN_PH_HEAD}; __u8 *rdesc_ptr; __u8 *p; @@ -1005,12 +1006,19 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, if (rdesc_ptr == NULL) return NULL; - for (p = rdesc_ptr; p + sizeof(pen_head) < rdesc_ptr + template_size;) { - if (memcmp(p, pen_head, sizeof(pen_head)) == 0 && + for (p = rdesc_ptr; p + sizeof(btn_head) < rdesc_ptr + template_size;) { + if (p + sizeof(pen_head) < rdesc_ptr + template_size && + memcmp(p, pen_head, sizeof(pen_head)) == 0 && p[sizeof(pen_head)] < param_num) { v = param_list[p[sizeof(pen_head)]]; put_unaligned(cpu_to_le32(v), (s32 *)p); p += sizeof(pen_head) + 1; + } else if (memcmp(p, btn_head, sizeof(btn_head)) == 0 && + p[sizeof(btn_head)] < param_num) { + v = param_list[p[sizeof(btn_head)]]; + put_unaligned((__u8)0x2A, p); /* Usage Maximum */ + put_unaligned_le16((__force u16)cpu_to_le16(v), p + 1); + p += sizeof(btn_head) + 1; } else { p++; } diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 9d37090c39d1..3d78299f082d 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -82,6 +82,7 @@ extern const size_t uclogic_rdesc_twha60_fixed1_size; /* Report descriptor template placeholder head */ #define UCLOGIC_RDESC_PEN_PH_HEAD 0xFE, 0xED, 0x1D +#define UCLOGIC_RDESC_FRAME_PH_BTN_HEAD 0xFE, 0xED /* Apply report descriptor parameters to a report descriptor template */ extern __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, @@ -96,6 +97,7 @@ enum uclogic_rdesc_ph_id { UCLOGIC_RDESC_PEN_PH_ID_Y_LM, UCLOGIC_RDESC_PEN_PH_ID_Y_PM, UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM, + UCLOGIC_RDESC_FRAME_PH_ID_UM, UCLOGIC_RDESC_PH_ID_NUM }; @@ -103,6 +105,10 @@ enum uclogic_rdesc_ph_id { #define UCLOGIC_RDESC_PEN_PH(_ID) \ UCLOGIC_RDESC_PEN_PH_HEAD, UCLOGIC_RDESC_PEN_PH_ID_##_ID +/* Report descriptor frame buttons template placeholder */ +#define UCLOGIC_RDESC_FRAME_PH_BTN \ + UCLOGIC_RDESC_FRAME_PH_BTN_HEAD, UCLOGIC_RDESC_FRAME_PH_ID_UM + /* Report ID for v1 pen reports */ #define UCLOGIC_RDESC_V1_PEN_ID 0x07 From patchwork Tue May 31 18:12:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= X-Patchwork-Id: 12865995 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8D383C433F5 for ; Tue, 31 May 2022 18:13:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346877AbiEaSN2 (ORCPT ); Tue, 31 May 2022 14:13:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58764 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346876AbiEaSNZ (ORCPT ); Tue, 31 May 2022 14:13:25 -0400 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ED2A7813EE; Tue, 31 May 2022 11:13:20 -0700 (PDT) Received: by mail-wm1-x32b.google.com with SMTP id v4-20020a1cac04000000b00397001398c0so1686813wme.5; Tue, 31 May 2022 11:13:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=E6LUcOWx1z2poXLh/BFADj8qF2w3QGSPYJH8IboePfI=; b=Uih3jCKGLWN1fSb5wieUNYdEMIvUyZpyGCeAkx9bEjjol9+JYWPIpcqSNUC2+fgThD O0NSlbczHIn7othhumtLa9yQwD7v8OD2PyrB/Um1j0btix4/9aiqAqgjIVAuDcR1McRj xJkqzuziyKsyBADQKI+S2ky943oqIGALwJ2CT/osS5xQctZJRZySqwPuJJjcvYcXjeTu UJ5vk+DUxzRqiq3OteAyK5zubNOpC/Zu4Tx2jimz/uqrqkjX4wUOfJ3GB6EyiVA1UV5k bdhzElPEf1ab/ZkxuWZHIGxqI8m6jXOvV6dWsr6RkWlnFlJcTG1TqGthY1sB8bCWfz8X GfSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=E6LUcOWx1z2poXLh/BFADj8qF2w3QGSPYJH8IboePfI=; b=uAKgQKQy8TwPUlc13Zr+Ws+CyCLxNKhYObf7EuimI7WPzPcXWLG4cF2nH42FJQm20C 6+2iClVo1jFuzrQZNU9cKZrb+7kjc05TJjXLU/kdGcj11A6ctF3zqeTjflQxlEQpZwt4 u+XvocBjmnzlSqxJNkSwruybni2YuWdMsJtLtds4vrNi/B25IOer1pnuUQ0cTpvR6/qA qdPemfKv1R1NKx3ovfw36ihxBUaDfJRV3ifbYxkha/klbawjGyV0CtoTgy3SKh7ZNDq3 5SfzUSS19YDigjJrQcv+N1OfyY4XE1VSVFIHnXdEl0DR+zt/U7yoj81AuotXrVzy9cQF tKaA== X-Gm-Message-State: AOAM531+gbdn0B8HYE84bvy7ramTD63ARyOAv6qNdpw/yya/EaUrWFTb HP7ifKQhOjMsI1U0qT+ZjDI= X-Google-Smtp-Source: ABdhPJwZWoInYxIUFR+TheZF98kOVg/RWwAM9J1CC/XSZSY0AXz5wh7it0Bn1MG6BT36Od043ul6CA== X-Received: by 2002:a05:600c:3c8f:b0:39b:808c:b5cb with SMTP id bg15-20020a05600c3c8f00b0039b808cb5cbmr12558048wmb.11.1654020799369; Tue, 31 May 2022 11:13:19 -0700 (PDT) Received: from localhost.localdomain ([94.73.36.128]) by smtp.gmail.com with ESMTPSA id i12-20020a05600c354c00b0039765a7add4sm3099597wmq.29.2022.05.31.11.13.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 May 2022 11:13:19 -0700 (PDT) From: =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= To: jikos@kernel.org Cc: benjamin.tissoires@redhat.com, spbnick@gmail.com, linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, stefanberzl@gmail.com, dlatypov@google.com, kunit-dev@googlegroups.com, =?utf-8?b?Sm9zw6kgRXhww7NzaXRv?= Subject: [PATCH v3 4/4] HID: uclogic: Add support for XP-PEN Deco L Date: Tue, 31 May 2022 20:12:46 +0200 Message-Id: <20220531181246.190729-5-jose.exposito89@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220531181246.190729-1-jose.exposito89@gmail.com> References: <20220531181246.190729-1-jose.exposito89@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org The XP-PEN Deco L (UGEE) needs to be initialized by sending a buffer of magic data, discovered by sniffing the Windows driver traffic. In order to differentiate UGEE tablets that need this kind of initialization from the previous ones, name them v2 internally and create an entry point for them. After initialization, the template report descriptors can be discovered by parsing a string descriptor, similar to the one exposed by HUION v1 devices. Add all the required elements to support the device. Signed-off-by: José Expósito --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 + drivers/hid/hid-uclogic-params.c | 197 +++++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.c | 102 ++++++++++++++++ drivers/hid/hid-uclogic-rdesc.h | 8 ++ 5 files changed, 310 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index d9eb676abe96..139910034c17 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1278,6 +1278,7 @@ #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G540 0x0075 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640 0x0094 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01 0x0042 +#define USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L 0x0935 #define USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06 0x0078 #define USB_DEVICE_ID_UGEE_TABLET_G5 0x0074 #define USB_DEVICE_ID_UGEE_TABLET_EX07S 0x0071 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index c0fe66e50c58..47a17375c7fc 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -521,6 +521,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UGEE_XPPEN_TABLET_G640) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO01) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_STAR06) }, { } diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index b43142f98a8b..f24a4aca7920 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1002,6 +1002,197 @@ static int uclogic_params_huion_init(struct uclogic_params *params, return rc; } +/** + * uclogic_probe_interface() - some tablets, like the Parblo A610 PLUS V2 or + * the XP-PEN Deco Mini 7, need to be initialized by sending them magic data. + * + * @hdev: The HID device of the tablet interface to initialize and get + * parameters from. Cannot be NULL. + * @magic_arr: The magic data that should be sent to probe the interface. + * Cannot be NULL. + * @magic_size: Size of the magic data. + * @endpoint: Endpoint where the magic data should be sent. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, + int magic_size, int endpoint) +{ + struct usb_device *udev; + unsigned int pipe = 0; + int sent; + u8 *buf = NULL; + int rc = 0; + + if (!hdev || !magic_arr) { + rc = -EINVAL; + goto cleanup; + } + + buf = kmemdup(magic_arr, magic_size, GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; + goto cleanup; + } + + udev = hid_to_usb_dev(hdev); + pipe = usb_sndintpipe(udev, endpoint); + + rc = usb_interrupt_msg(udev, pipe, buf, magic_size, &sent, 1000); + if (rc || sent != magic_size) { + hid_err(hdev, "Interface probing failed: %d\n", rc); + rc = -1; + goto cleanup; + } + + rc = 0; +cleanup: + kfree(buf); + return rc; +} + +/** + * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by + * discovering their parameters. + * + * These tables, internally designed as v2 to differentiate them from older + * models, expect a payload of magic data in orther to be switched to the fully + * functional mode and expose their parameters in a similar way to the + * information present in uclogic_params_pen_init_v1() but with some + * differences. + * + * @params: Parameters to fill in (to be cleaned with + * uclogic_params_cleanup()). Not modified in case of error. + * Cannot be NULL. + * @hdev: The HID device of the tablet interface to initialize and get + * parameters from. Cannot be NULL. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init(struct uclogic_params *params, + struct hid_device *hdev) +{ + int rc = 0; + struct usb_interface *iface; + __u8 bInterfaceNumber; + const int str_desc_len = 12; + __u8 *str_desc = NULL; + __u8 *rdesc_pen = NULL; + __u8 *rdesc_frame = NULL; + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + s32 resolution; + __u8 magic_arr[] = { + 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + /* The resulting parameters (noop) */ + struct uclogic_params p = {0, }; + + if (!params || !hdev) { + rc = -EINVAL; + goto cleanup; + } + + iface = to_usb_interface(hdev->dev.parent); + bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + if (bInterfaceNumber != 2) { + uclogic_params_init_invalid(&p); + goto output; + } + + /* + * Initialize the interface by sending magic data. + * The specific data was discovered by sniffing the Windows driver + * traffic. + */ + rc = uclogic_probe_interface(hdev, magic_arr, sizeof(magic_arr), 0x03); + if (rc) { + uclogic_params_init_invalid(&p); + goto output; + } + + /* + * Read the string descriptor containing pen and frame parameters. + * The specific string descriptor and data were discovered by sniffing + * the Windows driver traffic. + */ + rc = uclogic_params_get_str_desc(&str_desc, hdev, 100, str_desc_len); + if (rc != str_desc_len) { + hid_err(hdev, "failed retrieving pen and frame parameters: %d\n", rc); + uclogic_params_init_invalid(&p); + goto output; + } + + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = + get_unaligned_le16(str_desc + 2); + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = + get_unaligned_le16(str_desc + 4); + desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = str_desc[6]; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = + get_unaligned_le16(str_desc + 8); + resolution = get_unaligned_le16(str_desc + 10); + if (resolution == 0) { + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0; + } else { + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] * 1000 / + resolution; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] * 1000 / + resolution; + } + kfree(str_desc); + str_desc = NULL; + + /* Initialize the pen interface */ + rdesc_pen = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_pen_template_arr, + uclogic_rdesc_ugee_v2_pen_template_size, + desc_params, ARRAY_SIZE(desc_params)); + if (!rdesc_pen) { + rc = -ENOMEM; + goto cleanup; + } + + p.pen.desc_ptr = rdesc_pen; + p.pen.desc_size = uclogic_rdesc_ugee_v2_pen_template_size; + p.pen.id = 0x02; + p.pen.subreport_list[0].value = 0xf0; + p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; + + /* Initialize the frame interface */ + rdesc_frame = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_frame_btn_template_arr, + uclogic_rdesc_ugee_v2_frame_btn_template_size, + desc_params, ARRAY_SIZE(desc_params)); + if (!rdesc_frame) { + rc = -ENOMEM; + goto cleanup; + } + + rc = uclogic_params_frame_init_with_desc(&p.frame_list[0], + rdesc_frame, + uclogic_rdesc_ugee_v2_frame_btn_template_size, + UCLOGIC_RDESC_V1_FRAME_ID); + kfree(rdesc_frame); + if (rc) { + uclogic_params_init_invalid(&p); + goto output; + } + +output: + /* Output parameters */ + memcpy(params, &p, sizeof(*params)); + memset(&p, 0, sizeof(p)); + rc = 0; +cleanup: + kfree(str_desc); + uclogic_params_cleanup(&p); + return rc; +} + /** * uclogic_params_init() - initialize a tablet interface and discover its * parameters. @@ -1237,6 +1428,12 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_init_invalid(&p); } break; + case VID_PID(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): + rc = uclogic_params_ugee_v2_init(&p, hdev); + if (rc != 0) + goto cleanup; + break; case VID_PID(USB_VENDOR_ID_TRUST, USB_DEVICE_ID_TRUST_PANORA_TABLET): case VID_PID(USB_VENDOR_ID_UGEE, diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 3fb84ac492b4..3d68e8b0784d 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -859,6 +859,108 @@ const __u8 uclogic_rdesc_v2_frame_dial_arr[] = { const size_t uclogic_rdesc_v2_frame_dial_size = sizeof(uclogic_rdesc_v2_frame_dial_arr); +/* Fixed report descriptor template for UGEE v2 pen reports */ +const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[] = { + 0x05, 0x0d, /* Usage Page (Digitizers), */ + 0x09, 0x01, /* Usage (Digitizer), */ + 0xa1, 0x01, /* Collection (Application), */ + 0x85, 0x02, /* Report ID (2), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xa1, 0x00, /* Collection (Physical), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x09, 0x32, /* Usage (In Range), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0xa4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x30, /* Usage (X), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x55, 0x0d, /* Unit Exponent (-3), */ + 0x27, UCLOGIC_RDESC_PEN_PH(X_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x47, UCLOGIC_RDESC_PEN_PH(X_PM), + /* Physical Maximum (PLACEHOLDER), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x27, UCLOGIC_RDESC_PEN_PH(Y_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x47, UCLOGIC_RDESC_PEN_PH(Y_PM), + /* Physical Maximum (PLACEHOLDER), */ + 0x81, 0x02, /* Input (Variable), */ + 0xb4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x45, 0x00, /* Physical Maximum (0), */ + 0x27, UCLOGIC_RDESC_PEN_PH(PRESSURE_LM), + /* Logical Maximum (PLACEHOLDER), */ + 0x75, 0x0D, /* Report Size (13), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x01, /* Input (Constant), */ + 0x09, 0x3d, /* Usage (X Tilt), */ + 0x35, 0xC3, /* Physical Minimum (-61), */ + 0x45, 0x3C, /* Physical Maximum (60), */ + 0x15, 0xC3, /* Logical Minimum (-61), */ + 0x25, 0x3C, /* Logical Maximum (60), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x3e, /* Usage (Y Tilt), */ + 0x35, 0xC3, /* Physical Minimum (-61), */ + 0x45, 0x3C, /* Physical Maximum (60), */ + 0x15, 0xC3, /* Logical Minimum (-61), */ + 0x25, 0x3C, /* Logical Maximum (60), */ + 0x81, 0x02, /* Input (Variable), */ + 0xc0, /* End Collection, */ + 0xc0, /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_pen_template_size = + sizeof(uclogic_rdesc_ugee_v2_pen_template_arr); + +/* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */ +const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x07, /* Usage (Keypad), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, UCLOGIC_RDESC_V1_FRAME_ID, + /* Report ID, */ + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x39, /* Usage (Tablet Function Keys), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x08, /* Report Count (8), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + UCLOGIC_RDESC_FRAME_PH_BTN, + /* Usage Maximum (PLACEHOLDER), */ + 0x95, 0x0A, /* Report Count (10), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x46, /* Report Count (70), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size = + sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr); + /* Fixed report descriptor for Ugee EX07 frame */ const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 3d78299f082d..86e64a9ee6bd 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -161,6 +161,14 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size; /* Device ID byte offset in v2 frame dial reports */ #define UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE 0x4 +/* Fixed report descriptor template for UGEE v2 pen reports */ +extern const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_pen_template_size; + +/* Fixed report descriptor template for UGEE v2 frame reports (buttons only) */ +extern const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size; + /* Fixed report descriptor for Ugee EX07 frame */ extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[]; extern const size_t uclogic_rdesc_ugee_ex07_frame_size;