From 0977fda0587cbc5403651ba169e264aa01e8a026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:26:15 +0200 Subject: [PATCH 01/38] HID: uclogic: Add missing suffix for digitalizers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Pen (0x02) application usage was changed to Digitalizer (0x01) in commit f7d8e387d9ae ("HID: uclogic: Switch to Digitizer usage for styluses"). However, a suffix was not selected for the new usage. Handle the digitalizer application usage in uclogic_input_configured() and add the required suffix. Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index 47a17375c7fce..ff46604ef1d8c 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -153,6 +153,7 @@ static int uclogic_input_configured(struct hid_device *hdev, suffix = "Pad"; break; case HID_DG_PEN: + case HID_DG_DIGITIZER: suffix = "Pen"; break; case HID_CP_CONSUMER_CONTROL: From 609174edeb758d1e2d713e7ab4e09ea8d45aa4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:27:06 +0200 Subject: [PATCH 02/38] HID: uclogic: Fix warning in uclogic_rdesc_template_apply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building with Sparse enabled prints this warning: warning: incorrect type in assignment (different base types) expected signed int x got restricted __le32 [usertype] Cast the return value of cpu_to_le32() to fix the warning. Fixes: 08177f4 ("HID: uclogic: merge hid-huion driver in hid-uclogic") Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-rdesc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 3d68e8b0784d0..81ca22398ed55 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -1113,7 +1113,7 @@ __u8 *uclogic_rdesc_template_apply(const __u8 *template_ptr, 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); + put_unaligned((__force u32)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) { From 08809e482a1c44d95d1322b9fbc94c8e58ae9015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:49 +0200 Subject: [PATCH 03/38] HID: uclogic: KUnit best practices and naming conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The KUnit documentation [1] suggests allowing build tests as a module. In addition, it is recommended [2] to use snake case names for kunit_suite and test cases. Change the Kconfig entry from bool to tristate and stick to the naming conventions to avoid style issues with future tests. Link: https://docs.kernel.org/dev-tools/kunit/style.html#test-kconfig-entries [1] Link: https://www.kernel.org/doc/html/latest/dev-tools/kunit/style.html [2] Acked-by: Daniel Latypov Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 2 +- drivers/hid/Makefile | 3 ++- drivers/hid/hid-uclogic-rdesc-test.c | 22 +++++++++++----------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ce92830b5d1f..36a17958493f7 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1307,7 +1307,7 @@ config HID_MCP2221 will be called hid-mcp2221.ko. config HID_KUNIT_TEST - bool "KUnit tests for HID" if !KUNIT_ALL_TESTS + tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS depends on KUNIT=y depends on HID_UCLOGIC default KUNIT_ALL_TESTS diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b0bef80981394..82d8fd97d96cd 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -144,8 +144,9 @@ obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o -obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-rdesc.o \ +hid-uclogic-test-objs := hid-uclogic-rdesc.o \ hid-uclogic-rdesc-test.o +obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c index ebebffef5f8ae..3971a0854c3e1 100644 --- a/drivers/hid/hid-uclogic-rdesc-test.c +++ b/drivers/hid/hid-uclogic-rdesc-test.c @@ -97,7 +97,7 @@ static const __u8 template_params_none[] = { static struct uclogic_template_case uclogic_template_cases[] = { { - .name = "Empty template", + .name = "empty_template", .template = template_empty, .template_size = sizeof(template_empty), .param_list = params_pen_all, @@ -105,7 +105,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = template_empty, }, { - .name = "Template smaller than the placeholder", + .name = "template_smaller_than_the_placeholder", .template = template_small, .template_size = sizeof(template_small), .param_list = params_pen_all, @@ -113,7 +113,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = template_small, }, { - .name = "No placeholder", + .name = "no_placeholder", .template = template_no_ph, .template_size = sizeof(template_no_ph), .param_list = params_pen_all, @@ -121,7 +121,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = template_no_ph, }, { - .name = "Pen placeholder at the end, without ID", + .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, @@ -129,7 +129,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = template_pen_ph_end, }, { - .name = "Frame button placeholder at the end, without ID", + .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, @@ -137,7 +137,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = template_btn_ph_end, }, { - .name = "All params present in the pen template", + .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, @@ -145,7 +145,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = expected_pen_all_params, }, { - .name = "All params present in the frame template", + .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, @@ -153,7 +153,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = expected_frame_all_params, }, { - .name = "Some params present in the pen template (complete param list)", + .name = "some_params_present_in_the_pen_template_with_complete_param_list", .template = template_pen_some_params, .template_size = sizeof(template_pen_some_params), .param_list = params_pen_all, @@ -161,7 +161,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = expected_pen_some_params, }, { - .name = "Some params present in the pen template (incomplete param list)", + .name = "some_params_present_in_the_pen_template_with_incomplete_param_list", .template = template_pen_some_params, .template_size = sizeof(template_pen_some_params), .param_list = params_pen_some, @@ -169,7 +169,7 @@ static struct uclogic_template_case uclogic_template_cases[] = { .expected = expected_pen_some_params, }, { - .name = "No params present in the template", + .name = "no_params_present_in_the_template", .template = template_params_none, .template_size = sizeof(template_params_none), .param_list = params_pen_some, @@ -208,7 +208,7 @@ static struct kunit_case hid_uclogic_rdesc_test_cases[] = { }; static struct kunit_suite hid_uclogic_rdesc_test_suite = { - .name = "hid-uclogic-rdesc-test", + .name = "hid_uclogic_rdesc_test", .test_cases = hid_uclogic_rdesc_test_cases, }; From a64cbf3ce63122168e1edb3eb1eb1cf7781ae230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:50 +0200 Subject: [PATCH 04/38] HID: uclogic: Refactor UGEE v2 string descriptor parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The UGEE v2 tablets expose a string descriptor with their capabilities. Move the code used to parse the descriptors and generate a parameter list from it to its own function and add KUnit tests to validate the parser. Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/Makefile | 1 + drivers/hid/hid-uclogic-params-test.c | 159 ++++++++++++++++++++++++++ drivers/hid/hid-uclogic-params.c | 86 ++++++++++---- 3 files changed, 226 insertions(+), 20 deletions(-) create mode 100644 drivers/hid/hid-uclogic-params-test.c diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 82d8fd97d96cd..fe69dece2a460 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -145,6 +145,7 @@ obj-$(CONFIG_HID_SENSOR_HUB) += hid-sensor-hub.o obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR) += hid-sensor-custom.o hid-uclogic-test-objs := hid-uclogic-rdesc.o \ + hid-uclogic-params.o \ hid-uclogic-rdesc-test.o obj-$(CONFIG_HID_KUNIT_TEST) += hid-uclogic-test.o diff --git a/drivers/hid/hid-uclogic-params-test.c b/drivers/hid/hid-uclogic-params-test.c new file mode 100644 index 0000000000000..9f043f2ab387c --- /dev/null +++ b/drivers/hid/hid-uclogic-params-test.c @@ -0,0 +1,159 @@ +// 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" + +#define MAX_STR_DESC_SIZE 14 + +struct uclogic_parse_ugee_v2_desc_case { + const char *name; + int res; + const __u8 str_desc[MAX_STR_DESC_SIZE]; + size_t str_desc_size; + const s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; +}; + +static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] = { + { + .name = "invalid_str_desc", + .res = -EINVAL, + .str_desc = {}, + .str_desc_size = 0, + .desc_params = {}, + }, + { + .name = "resolution_with_value_0", + .res = 0, + .str_desc = { + 0x0E, 0x03, + 0x70, 0xB2, + 0x10, 0x77, + 0x08, + 0x00, + 0xFF, 0x1F, + 0x00, 0x00, + }, + .str_desc_size = 12, + .desc_params = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB270, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0, + [UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7710, + [UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0, + [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, + [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08, + }, + }, + /* XP-PEN Deco L str_desc: Frame with 8 buttons */ + { + .name = "frame_type_buttons", + .res = 0, + .str_desc = { + 0x0E, 0x03, + 0x70, 0xB2, + 0x10, 0x77, + 0x08, + 0x00, + 0xFF, 0x1F, + 0xD8, 0x13, + }, + .str_desc_size = 12, + .desc_params = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB270, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2320, + [UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7710, + [UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x1770, + [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, + [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08, + }, + }, + /* PARBLO A610 PRO str_desc: Frame with 9 buttons and dial */ + { + .name = "frame_type_dial", + .res = 0, + .str_desc = { + 0x0E, 0x03, + 0x96, 0xC7, + 0xF9, 0x7C, + 0x09, + 0x01, + 0xFF, 0x1F, + 0xD8, 0x13, + }, + .str_desc_size = 12, + .desc_params = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xC796, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2749, + [UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x7CF9, + [UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x1899, + [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, + [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x09, + }, + }, +}; + +static void uclogic_parse_ugee_v2_desc_case_desc(struct uclogic_parse_ugee_v2_desc_case *t, + char *desc) +{ + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(uclogic_parse_ugee_v2_desc, uclogic_parse_ugee_v2_desc_cases, + uclogic_parse_ugee_v2_desc_case_desc); + +static void uclogic_parse_ugee_v2_desc_test(struct kunit *test) +{ + int res; + s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + const struct uclogic_parse_ugee_v2_desc_case *params = test->param_value; + + res = uclogic_params_parse_ugee_v2_desc(params->str_desc, + params->str_desc_size, + desc_params, + ARRAY_SIZE(desc_params)); + KUNIT_ASSERT_EQ(test, res, params->res); + + if (res) + return; + + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM], + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM]); + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM], + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM]); + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM], + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM]); + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM], + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM]); + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM], + desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM]); + KUNIT_EXPECT_EQ(test, + params->desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM], + desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM]); +} + +static struct kunit_case hid_uclogic_params_test_cases[] = { + KUNIT_CASE_PARAM(uclogic_parse_ugee_v2_desc_test, + uclogic_parse_ugee_v2_desc_gen_params), + {} +}; + +static struct kunit_suite hid_uclogic_params_test_suite = { + .name = "hid_uclogic_params_test", + .test_cases = hid_uclogic_params_test_cases, +}; + +kunit_test_suite(hid_uclogic_params_test_suite); + +MODULE_DESCRIPTION("KUnit tests for the UC-Logic driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("José Expósito "); diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index c11fa239e6a29..07c5a21112cee 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1056,6 +1056,62 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, return rc; } +/** + * uclogic_params_parse_ugee_v2_desc - parse the string descriptor containing + * pen and frame parameters returned by UGEE v2 devices. + * + * @str_desc: String descriptor, cannot be NULL. + * @str_desc_size: Size of the string descriptor. + * @desc_params: Output description params list. + * @desc_params_size: Size of the output description params list. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, + size_t str_desc_size, + s32 *desc_params, + size_t desc_params_size) +{ + s32 pen_x_lm, pen_y_lm; + s32 pen_x_pm, pen_y_pm; + s32 pen_pressure_lm; + s32 frame_num_buttons; + s32 resolution; + + /* Minimum descriptor length required, maximum seen so far is 14 */ + const int min_str_desc_size = 12; + + if (!str_desc || str_desc_size < min_str_desc_size) + return -EINVAL; + + if (desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) + return -EINVAL; + + pen_x_lm = get_unaligned_le16(str_desc + 2); + pen_y_lm = get_unaligned_le16(str_desc + 4); + frame_num_buttons = str_desc[6]; + pen_pressure_lm = get_unaligned_le16(str_desc + 8); + + resolution = get_unaligned_le16(str_desc + 10); + if (resolution == 0) { + pen_x_pm = 0; + pen_y_pm = 0; + } else { + pen_x_pm = pen_x_lm * 1000 / resolution; + pen_y_pm = pen_y_lm * 1000 / resolution; + } + + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_LM] = pen_x_lm; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_X_PM] = pen_x_pm; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = pen_y_lm; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = pen_y_pm; + desc_params[UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = pen_pressure_lm; + desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM] = frame_num_buttons; + + return 0; +} + /** * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * discovering their parameters. @@ -1086,7 +1142,6 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, __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 }; @@ -1128,25 +1183,12 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 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; - } + rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, + desc_params, + ARRAY_SIZE(desc_params)); + if (rc) + goto cleanup; + kfree(str_desc); str_desc = NULL; @@ -1517,3 +1559,7 @@ int uclogic_params_init(struct uclogic_params *params, uclogic_params_cleanup(&p); return rc; } + +#ifdef CONFIG_HID_KUNIT_TEST +#include "hid-uclogic-params-test.c" +#endif From 86402296784f656427245edd0546cac39d410b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:51 +0200 Subject: [PATCH 05/38] HID: uclogic: Refactor UGEE v2 frame initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment, the driver only supports UGEE v2 devices that have buttons in their frames. In order to support other types of frames in the future, move the code used to initialize this kind of frames to its own function. Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params.c | 56 ++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 07c5a21112cee..182e6f8f027a3 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1112,6 +1112,41 @@ static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, return 0; } +/** + * uclogic_params_ugee_v2_init_frame_buttons() - initialize a UGEE v2 frame with + * buttons. + * @p: Parameters to fill in, cannot be NULL. + * @desc_params: Device description params list. + * @desc_params_size: Size of the description params list. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p, + const s32 *desc_params, + size_t desc_params_size) +{ + __u8 *rdesc_frame = NULL; + int rc = 0; + + if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) + return -EINVAL; + + rdesc_frame = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_frame_btn_template_arr, + uclogic_rdesc_ugee_v2_frame_btn_template_size, + desc_params, UCLOGIC_RDESC_PH_ID_NUM); + if (!rdesc_frame) + return -ENOMEM; + + 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); + return rc; +} + /** * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * discovering their parameters. @@ -1140,7 +1175,6 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 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]; __u8 magic_arr[] = { 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -1209,24 +1243,10 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, 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; + rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, + ARRAY_SIZE(desc_params)); + if (rc) 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 */ From a092986fc095b963383b948a5c74dd1d202d21b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:52 +0200 Subject: [PATCH 06/38] HID: uclogic: Parse the UGEE v2 frame type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The string descriptor returned by UGEE v2 devices contains a byte indicating the device frame type. The values discovered so far are: - 0: Frame with buttons, present in the XP-PEN Deco L. - 1: Frame with buttons and dial, present in the PARBLO A610 PRO. - 2: Frame with buttons and a mouse, shaped as a dial + touchpad. Present in the XP-PEN Deco Pro S. Parse the frame type and add KUnit tests. Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params-test.c | 35 ++++++++++++++++++++++++++- drivers/hid/hid-uclogic-params.c | 19 ++++++++++++--- drivers/hid/hid-uclogic-params.h | 10 ++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-uclogic-params-test.c b/drivers/hid/hid-uclogic-params-test.c index 9f043f2ab387c..57ef5d3e4b74c 100644 --- a/drivers/hid/hid-uclogic-params-test.c +++ b/drivers/hid/hid-uclogic-params-test.c @@ -7,6 +7,7 @@ */ #include +#include "./hid-uclogic-params.h" #include "./hid-uclogic-rdesc.h" #define MAX_STR_DESC_SIZE 14 @@ -17,6 +18,7 @@ struct uclogic_parse_ugee_v2_desc_case { const __u8 str_desc[MAX_STR_DESC_SIZE]; size_t str_desc_size; const s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + enum uclogic_params_frame_type frame_type; }; static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] = { @@ -26,6 +28,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] .str_desc = {}, .str_desc_size = 0, .desc_params = {}, + .frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS, }, { .name = "resolution_with_value_0", @@ -48,6 +51,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08, }, + .frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS, }, /* XP-PEN Deco L str_desc: Frame with 8 buttons */ { @@ -71,6 +75,7 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08, }, + .frame_type = UCLOGIC_PARAMS_FRAME_BUTTONS, }, /* PARBLO A610 PRO str_desc: Frame with 9 buttons and dial */ { @@ -94,6 +99,31 @@ static struct uclogic_parse_ugee_v2_desc_case uclogic_parse_ugee_v2_desc_cases[] [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x09, }, + .frame_type = UCLOGIC_PARAMS_FRAME_DIAL, + }, + /* XP-PEN Deco Pro S str_desc: Frame with 8 buttons and mouse */ + { + .name = "frame_type_mouse", + .res = 0, + .str_desc = { + 0x0E, 0x03, + 0xC8, 0xB3, + 0x34, 0x65, + 0x08, + 0x02, + 0xFF, 0x1F, + 0xD8, 0x13, + }, + .str_desc_size = 12, + .desc_params = { + [UCLOGIC_RDESC_PEN_PH_ID_X_LM] = 0xB3C8, + [UCLOGIC_RDESC_PEN_PH_ID_X_PM] = 0x2363, + [UCLOGIC_RDESC_PEN_PH_ID_Y_LM] = 0x6534, + [UCLOGIC_RDESC_PEN_PH_ID_Y_PM] = 0x13EC, + [UCLOGIC_RDESC_PEN_PH_ID_PRESSURE_LM] = 0x1FFF, + [UCLOGIC_RDESC_FRAME_PH_ID_UM] = 0x08, + }, + .frame_type = UCLOGIC_PARAMS_FRAME_MOUSE, }, }; @@ -110,12 +140,14 @@ static void uclogic_parse_ugee_v2_desc_test(struct kunit *test) { int res; s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + enum uclogic_params_frame_type frame_type; const struct uclogic_parse_ugee_v2_desc_case *params = test->param_value; res = uclogic_params_parse_ugee_v2_desc(params->str_desc, params->str_desc_size, desc_params, - ARRAY_SIZE(desc_params)); + ARRAY_SIZE(desc_params), + &frame_type); KUNIT_ASSERT_EQ(test, res, params->res); if (res) @@ -139,6 +171,7 @@ static void uclogic_parse_ugee_v2_desc_test(struct kunit *test) KUNIT_EXPECT_EQ(test, params->desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM], desc_params[UCLOGIC_RDESC_FRAME_PH_ID_UM]); + KUNIT_EXPECT_EQ(test, params->frame_type, frame_type); } static struct kunit_case hid_uclogic_params_test_cases[] = { diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 182e6f8f027a3..7845dd5fb4b15 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1064,6 +1064,7 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, * @str_desc_size: Size of the string descriptor. * @desc_params: Output description params list. * @desc_params_size: Size of the output description params list. + * @frame_type: Output frame type. * * Returns: * Zero, if successful. A negative errno code on error. @@ -1071,7 +1072,8 @@ static int uclogic_probe_interface(struct hid_device *hdev, u8 *magic_arr, static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, size_t str_desc_size, s32 *desc_params, - size_t desc_params_size) + size_t desc_params_size, + enum uclogic_params_frame_type *frame_type) { s32 pen_x_lm, pen_y_lm; s32 pen_x_pm, pen_y_pm; @@ -1091,6 +1093,7 @@ static int uclogic_params_parse_ugee_v2_desc(const __u8 *str_desc, pen_x_lm = get_unaligned_le16(str_desc + 2); pen_y_lm = get_unaligned_le16(str_desc + 4); frame_num_buttons = str_desc[6]; + *frame_type = str_desc[7]; pen_pressure_lm = get_unaligned_le16(str_desc + 8); resolution = get_unaligned_le16(str_desc + 10); @@ -1176,6 +1179,7 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, __u8 *str_desc = NULL; __u8 *rdesc_pen = NULL; s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM]; + enum uclogic_params_frame_type frame_type; __u8 magic_arr[] = { 0x02, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -1219,7 +1223,8 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, rc = uclogic_params_parse_ugee_v2_desc(str_desc, str_desc_len, desc_params, - ARRAY_SIZE(desc_params)); + ARRAY_SIZE(desc_params), + &frame_type); if (rc) goto cleanup; @@ -1243,8 +1248,14 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, p.pen.subreport_list[0].id = UCLOGIC_RDESC_V1_FRAME_ID; /* Initialize the frame interface */ - rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, - ARRAY_SIZE(desc_params)); + switch (frame_type) { + case UCLOGIC_PARAMS_FRAME_BUTTONS: + default: + rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, + ARRAY_SIZE(desc_params)); + break; + } + if (rc) goto cleanup; diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index 5bef8daaa6074..a97477c02ff82 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -29,6 +29,16 @@ enum uclogic_params_pen_inrange { UCLOGIC_PARAMS_PEN_INRANGE_NONE, }; +/* Types of frames */ +enum uclogic_params_frame_type { + /* Frame with buttons */ + UCLOGIC_PARAMS_FRAME_BUTTONS = 0, + /* Frame with buttons and a dial */ + UCLOGIC_PARAMS_FRAME_DIAL, + /* Frame with buttons and a mouse (shaped as a dial + touchpad) */ + UCLOGIC_PARAMS_FRAME_MOUSE, +}; + /* * Pen report's subreport data. */ From b67439d7cd5a8d657bfbfb576dab10b11a492583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:53 +0200 Subject: [PATCH 07/38] HID: uclogic: Add support for UGEE v2 dial frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the required HID descriptors and the initialization function for UGEE v2 frames with a bitmap dial. Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params.c | 44 ++++++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.c | 40 +++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.h | 4 +++ 3 files changed, 88 insertions(+) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 7845dd5fb4b15..950615f95abcc 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1150,6 +1150,45 @@ static int uclogic_params_ugee_v2_init_frame_buttons(struct uclogic_params *p, return rc; } +/** + * uclogic_params_ugee_v2_init_frame_dial() - initialize a UGEE v2 frame with a + * bitmap dial. + * @p: Parameters to fill in, cannot be NULL. + * @desc_params: Device description params list. + * @desc_params_size: Size of the description params list. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p, + const s32 *desc_params, + size_t desc_params_size) +{ + __u8 *rdesc_frame = NULL; + int rc = 0; + + if (!p || desc_params_size != UCLOGIC_RDESC_PH_ID_NUM) + return -EINVAL; + + rdesc_frame = uclogic_rdesc_template_apply( + uclogic_rdesc_ugee_v2_frame_dial_template_arr, + uclogic_rdesc_ugee_v2_frame_dial_template_size, + desc_params, UCLOGIC_RDESC_PH_ID_NUM); + if (!rdesc_frame) + return -ENOMEM; + + rc = uclogic_params_frame_init_with_desc(&p->frame_list[0], + rdesc_frame, + uclogic_rdesc_ugee_v2_frame_dial_template_size, + UCLOGIC_RDESC_V1_FRAME_ID); + kfree(rdesc_frame); + if (rc) + return rc; + + p->frame_list[0].bitmap_dial_byte = 7; + return 0; +} + /** * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * discovering their parameters. @@ -1249,6 +1288,11 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, /* Initialize the frame interface */ switch (frame_type) { + case UCLOGIC_PARAMS_FRAME_DIAL: + case UCLOGIC_PARAMS_FRAME_MOUSE: + rc = uclogic_params_ugee_v2_init_frame_dial(&p, desc_params, + ARRAY_SIZE(desc_params)); + break; case UCLOGIC_PARAMS_FRAME_BUTTONS: default: rc = uclogic_params_ugee_v2_init_frame_buttons(&p, desc_params, diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 81ca22398ed55..56bf984538f6c 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -961,6 +961,46 @@ const __u8 uclogic_rdesc_ugee_v2_frame_btn_template_arr[] = { const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size = sizeof(uclogic_rdesc_ugee_v2_frame_btn_template_arr); +/* Fixed report descriptor template for UGEE v2 frame reports (dial) */ +const __u8 uclogic_rdesc_ugee_v2_frame_dial_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, 0x06, /* Report Count (6), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x38, /* Usage (Wheel), */ + 0x95, 0x01, /* Report Count (1), */ + 0x15, 0xFF, /* Logical Minimum (-1), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x95, 0x02, /* Report Count (2), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size = + sizeof(uclogic_rdesc_ugee_v2_frame_dial_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 86e64a9ee6bd7..1a2d658bad3ab 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -169,6 +169,10 @@ extern const size_t uclogic_rdesc_ugee_v2_pen_template_size; 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 template for UGEE v2 frame reports (dial) */ +extern const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_frame_dial_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; From 387dcab73f10bdc8a1e9b59626d2ccadcfb93f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:54 +0200 Subject: [PATCH 08/38] HID: uclogic: Add support for UGEE v2 mouse frames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the required HID descriptors and the initialization function for UGEE v2 frames with a mouse in the frame. Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-uclogic-params.c | 31 +++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.c | 34 ++++++++++++++++++++++++++++++++ drivers/hid/hid-uclogic-rdesc.h | 4 ++++ 3 files changed, 69 insertions(+) diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 950615f95abcc..648abda13a734 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1189,6 +1189,28 @@ static int uclogic_params_ugee_v2_init_frame_dial(struct uclogic_params *p, return 0; } +/** + * uclogic_params_ugee_v2_init_frame_mouse() - initialize a UGEE v2 frame with a + * mouse. + * @p: Parameters to fill in, cannot be NULL. + * + * Returns: + * Zero, if successful. A negative errno code on error. + */ +static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p) +{ + int rc = 0; + + if (!p) + return -EINVAL; + + rc = uclogic_params_frame_init_with_desc(&p->frame_list[1], + uclogic_rdesc_ugee_v2_frame_mouse_template_arr, + uclogic_rdesc_ugee_v2_frame_mouse_template_size, + UCLOGIC_RDESC_V1_FRAME_ID); + return rc; +} + /** * uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by * discovering their parameters. @@ -1232,6 +1254,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params, iface = to_usb_interface(hdev->dev.parent); bInterfaceNumber = iface->cur_altsetting->desc.bInterfaceNumber; + + if (bInterfaceNumber == 0) { + rc = uclogic_params_ugee_v2_init_frame_mouse(&p); + if (rc) + goto cleanup; + + goto output; + } + if (bInterfaceNumber != 2) { uclogic_params_init_invalid(&p); goto output; diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index 56bf984538f6c..4bd54c4fb5b0b 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -1001,6 +1001,40 @@ const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[] = { const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size = sizeof(uclogic_rdesc_ugee_v2_frame_dial_template_arr); +/* Fixed report descriptor template for UGEE v2 frame reports (mouse) */ +const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x02, /* Usage (Mouse), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x01, /* Report ID (1), */ + 0x05, 0x01, /* Usage Page (Pointer), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x02, /* Report Count (2), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x02, /* Usage Maximum (02h), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x06, /* Report Count (6), */ + 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Generic Desktop), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x02, /* Report Count (2), */ + 0x16, 0x00, 0x80, /* Logical Minimum (-32768), */ + 0x26, 0xFF, 0x7F, /* Logical Maximum (32767), */ + 0x81, 0x06, /* Input (Variable, Relative), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x01, /* Input (Constant), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; +const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size = + sizeof(uclogic_rdesc_ugee_v2_frame_mouse_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 1a2d658bad3ab..0502a06564964 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -173,6 +173,10 @@ extern const size_t uclogic_rdesc_ugee_v2_frame_btn_template_size; extern const __u8 uclogic_rdesc_ugee_v2_frame_dial_template_arr[]; extern const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size; +/* Fixed report descriptor template for UGEE v2 frame reports (mouse) */ +extern const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[]; +extern const size_t uclogic_rdesc_ugee_v2_frame_mouse_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; From 93b40b3ef5e1554e10891491542ef8dce0351af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:55 +0200 Subject: [PATCH 09/38] HID: uclogic: Add support for XP-PEN Deco Pro S MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The XP-PEN Deco Pro S is a UGEE v2 device with a frame with 8 buttons, a bitmap dial and a mouse. Its pen has 2 buttons, supports tilt and pressure. All the pieces to support it are already in place. Add its ID in order to support the device. The required Wireshark traces were captured by Jouke Witteveen. For more information check [1]. Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/738 [1] Tested-by: Jouke Witteveen Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 ++ drivers/hid/hid-uclogic-params.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0fb720a96399a..ecf1468404b3a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1280,6 +1280,7 @@ #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_DECO_PRO_S 0x0909 #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 ff46604ef1d8c..db9dec440018b 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -524,6 +524,8 @@ static const struct hid_device_id uclogic_devices[] = { 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_DECO_PRO_S) }, { 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 648abda13a734..60ed94981a555 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1582,6 +1582,8 @@ int uclogic_params_init(struct uclogic_params *params, break; case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): + case VID_PID(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_S): rc = uclogic_params_ugee_v2_init(&p, hdev); if (rc != 0) goto cleanup; From 7495fb7e74259234ae7054a2727ff4f39a8eb384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 15 Aug 2022 16:29:56 +0200 Subject: [PATCH 10/38] HID: uclogic: Add support for Parblo A610 PRO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Parblo A610 PRO is a UGEE v2 device with a frame with 9 buttons and a bitmap dial. Its pen has 2 buttons, supports tilt and pressure. Add its ID in order to support the device. Signed-off-by: José Expósito Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic-core.c | 2 ++ drivers/hid/hid-uclogic-params.c | 2 ++ 3 files changed, 5 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index ecf1468404b3a..6b4068eecc6f4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1276,6 +1276,7 @@ #define USB_DEVICE_ID_YIYNOVA_TABLET 0x004d #define USB_VENDOR_ID_UGEE 0x28bd +#define USB_DEVICE_ID_UGEE_PARBLO_A610_PRO 0x1903 #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 diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index db9dec440018b..0fbc408c26070 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -510,6 +510,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GT5040) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, + USB_DEVICE_ID_UGEE_PARBLO_A610_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_TABLET_G5) }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 60ed94981a555..34fa991e6267e 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -1580,6 +1580,8 @@ 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_PARBLO_A610_PRO): case VID_PID(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L): case VID_PID(USB_VENDOR_ID_UGEE, From b4a9af9be628e4f9d09997e0bdef30f6718e88ec Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 4 Aug 2022 13:30:52 +0200 Subject: [PATCH 11/38] HID: playstation: convert to use dev_groups There is no need for a driver to individually add/create device groups, the driver core will do it automatically for you. Convert the hid-playstation driver to use the dev_groups pointer instead of manually calling the driver core to create the group and have it be cleaned up later on by the devm core. Cc: Roderick Colenbrander Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: linux-input@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Acked-by: Roderick Colenbrander Signed-off-by: Jiri Kosina --- drivers/hid/hid-playstation.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index b1b5721b5d8f7..40050eb85c0a5 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -692,15 +692,12 @@ static ssize_t hardware_version_show(struct device *dev, static DEVICE_ATTR_RO(hardware_version); -static struct attribute *ps_device_attributes[] = { +static struct attribute *ps_device_attrs[] = { &dev_attr_firmware_version.attr, &dev_attr_hardware_version.attr, NULL }; - -static const struct attribute_group ps_device_attribute_group = { - .attrs = ps_device_attributes, -}; +ATTRIBUTE_GROUPS(ps_device); static int dualsense_get_calibration_data(struct dualsense *ds) { @@ -1448,12 +1445,6 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id) } } - ret = devm_device_add_group(&hdev->dev, &ps_device_attribute_group); - if (ret) { - hid_err(hdev, "Failed to register sysfs nodes.\n"); - goto err_close; - } - return ret; err_close: @@ -1487,6 +1478,9 @@ static struct hid_driver ps_driver = { .probe = ps_probe, .remove = ps_remove, .raw_event = ps_raw_event, + .driver = { + .dev_groups = ps_device_groups, + }, }; static int __init ps_init(void) From 8272a51d82945d63b238b1ad2f38204930c012a4 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 8 Jul 2022 18:57:59 -0700 Subject: [PATCH 12/38] HID: Kconfig: remove redundant "depends on HID" lines Remove all occurrences of "depends on HID" that are inside the "if HID" / "endif" block since they are redundant. Signed-off-by: Randy Dunlap Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: linux-input@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 73 +-------------------------------------------- 1 file changed, 1 insertion(+), 72 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ce92830b5d1f..11a0c7c40c298 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -28,7 +28,6 @@ if HID config HID_BATTERY_STRENGTH bool "Battery level reporting for HID devices" - depends on HID select POWER_SUPPLY default n help @@ -38,7 +37,6 @@ config HID_BATTERY_STRENGTH config HIDRAW bool "/dev/hidraw raw HID device support" - depends on HID help Say Y here if you want to support HID devices (from the USB specification standpoint) that aren't strictly user interface @@ -57,7 +55,6 @@ config HIDRAW config UHID tristate "User-space I/O driver support for HID subsystem" - depends on HID default n help Say Y here if you want to provide HID I/O Drivers from user-space. @@ -78,7 +75,6 @@ config UHID config HID_GENERIC tristate "Generic HID driver" - depends on HID default HID help Support for generic devices on the HID bus. This includes most @@ -90,11 +86,9 @@ config HID_GENERIC If unsure, say Y. menu "Special HID drivers" - depends on HID config HID_A4TECH tristate "A4TECH mice" - depends on HID default !EXPERT help Support for some A4TECH mice with two scroll wheels. @@ -113,7 +107,6 @@ config HID_ACCUTOUCH config HID_ACRUX tristate "ACRUX game controller support" - depends on HID help Say Y here if you want to enable support for ACRUX game controllers. @@ -127,7 +120,6 @@ config HID_ACRUX_FF config HID_APPLE tristate "Apple {i,Power,Mac}Books" - depends on HID depends on LEDS_CLASS depends on NEW_LEDS default !EXPERT @@ -167,13 +159,11 @@ config HID_ASUS config HID_AUREAL tristate "Aureal" - depends on HID help Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes. config HID_BELKIN tristate "Belkin Flip KVM and Wireless keyboard" - depends on HID default !EXPERT help Support for Belkin Flip KVM and Wireless keyboard. @@ -202,7 +192,6 @@ config HID_BIGBEN_FF config HID_CHERRY tristate "Cherry Cymotion keyboard" - depends on HID default !EXPERT help Support for Cherry Cymotion keyboard. @@ -227,7 +216,6 @@ config HID_CORSAIR config HID_COUGAR tristate "Cougar devices" - depends on HID help Support for Cougar devices that are not fully compliant with the HID standard. @@ -237,7 +225,6 @@ config HID_COUGAR config HID_MACALLY tristate "Macally devices" - depends on HID help Support for Macally devices that are not fully compliant with the HID standard. @@ -262,7 +249,6 @@ config HID_PRODIKEYS config HID_CMEDIA tristate "CMedia audio chips" - depends on HID help Support for CMedia CM6533 HID audio jack controls and HS100B mute buttons. @@ -288,14 +274,12 @@ config HID_CREATIVE_SB0540 config HID_CYPRESS tristate "Cypress mouse and barcode readers" - depends on HID default !EXPERT help Support for cypress mouse and barcode readers. config HID_DRAGONRISE tristate "DragonRise Inc. game controller" - depends on HID help Say Y here if you have DragonRise Inc. game controllers. These might be branded as: @@ -314,7 +298,6 @@ config DRAGONRISE_FF config HID_EMS_FF tristate "EMS Production Inc. force feedback support" - depends on HID select INPUT_FF_MEMLESS help Say Y here if you want to enable force feedback support for devices by @@ -332,7 +315,6 @@ config HID_ELAN config HID_ELECOM tristate "ELECOM HID devices" - depends on HID help Support for ELECOM devices: - BM084 Bluetooth Mouse @@ -349,7 +331,6 @@ config HID_ELO config HID_EZKEY tristate "Ezkey BTC 8193 keyboard" - depends on HID default !EXPERT help Support for Ezkey BTC 8193 keyboard. @@ -367,19 +348,16 @@ config HID_FT260 config HID_GEMBIRD tristate "Gembird Joypad" - depends on HID help Support for Gembird JPD-DualForce 2. config HID_GFRM tristate "Google Fiber TV Box remote control support" - depends on HID help Support for Google Fiber TV Box remote controls config HID_GLORIOUS tristate "Glorious PC Gaming Race mice" - depends on HID help Support for Glorious PC Gaming Race mice such as the Glorious Model O, O- and D. @@ -424,7 +402,6 @@ config HID_VIVALDI tristate "Vivaldi Keyboard" select HID_VIVALDI_COMMON select INPUT_VIVALDIFMAP - depends on HID help Say Y here if you want to enable support for Vivaldi keyboards. @@ -447,7 +424,6 @@ config HID_GT683R config HID_KEYTOUCH tristate "Keytouch HID devices" - depends on HID help Support for Keytouch HID devices not fully compliant with the specification. Currently supported: @@ -455,7 +431,6 @@ config HID_KEYTOUCH config HID_KYE tristate "KYE/Genius devices" - depends on HID help Support for KYE/Genius devices not fully compliant with HID standard: - Ergo Mouse @@ -471,32 +446,27 @@ config HID_UCLOGIC config HID_WALTOP tristate "Waltop" - depends on HID help Support for Waltop tablets. config HID_VIEWSONIC tristate "ViewSonic/Signotec" - depends on HID help Support for ViewSonic/Signotec PD1011 signature pad. config HID_XIAOMI tristate "Xiaomi" - depends on HID help Adds support for side buttons of Xiaomi Mi Dual Mode Wireless Mouse Silent Edition. config HID_GYRATION tristate "Gyration remote control" - depends on HID help Support for Gyration remote control. config HID_ICADE tristate "ION iCade arcade controller" - depends on HID help Support for the ION iCade arcade controller to work as a joystick. @@ -505,14 +475,12 @@ config HID_ICADE config HID_ITE tristate "ITE devices" - depends on HID default !EXPERT help Support for ITE devices not fully compliant with HID standard. config HID_JABRA tristate "Jabra USB HID Driver" - depends on HID help Support for Jabra USB HID devices. @@ -523,26 +491,22 @@ config HID_JABRA config HID_TWINHAN tristate "Twinhan IR remote control" - depends on HID help Support for Twinhan IR remote control. config HID_KENSINGTON tristate "Kensington Slimblade Trackball" - depends on HID default !EXPERT help Support for Kensington Slimblade Trackball. config HID_LCPOWER tristate "LC-Power" - depends on HID help Support for LC-Power RC1000MCE RF remote control. config HID_LED tristate "Simple RGB LED support" - depends on HID depends on LEDS_CLASS help Support for simple RGB LED devices. Currently supported are: @@ -557,7 +521,6 @@ config HID_LED config HID_LENOVO tristate "Lenovo / Thinkpad devices" - depends on HID select NEW_LEDS select LEDS_CLASS help @@ -675,7 +638,6 @@ config LOGIWHEELS_FF config HID_MAGICMOUSE tristate "Apple Magic Mouse/Trackpad multi-touch support" - depends on HID help Support for the Apple Magic Mouse/Trackpad multi-touch. @@ -684,14 +646,12 @@ config HID_MAGICMOUSE config HID_MALTRON tristate "Maltron L90 keyboard" - depends on HID help Adds support for the volume up, volume down, mute, and play/pause buttons of the Maltron L90 keyboard. config HID_MAYFLASH tristate "Mayflash game controller adapter force feedback" - depends on HID select INPUT_FF_MEMLESS help Say Y here if you have HJZ Mayflash PS3 game controller adapters @@ -707,14 +667,12 @@ config HID_MEGAWORLD_FF config HID_REDRAGON tristate "Redragon keyboards" - depends on HID default !EXPERT help Support for Redragon keyboards that need fix-ups to work properly. config HID_MICROSOFT tristate "Microsoft non-fully HID-compliant devices" - depends on HID default !EXPERT select INPUT_FF_MEMLESS help @@ -722,14 +680,12 @@ config HID_MICROSOFT config HID_MONTEREY tristate "Monterey Genius KB29E keyboard" - depends on HID default !EXPERT help Support for Monterey Genius KB29E. config HID_MULTITOUCH tristate "HID Multitouch panels" - depends on HID help Generic support for HID multitouch panels. @@ -775,7 +731,6 @@ config HID_MULTITOUCH config HID_NINTENDO tristate "Nintendo Joy-Con and Pro Controller support" - depends on HID depends on NEW_LEDS depends on LEDS_CLASS select POWER_SUPPLY @@ -811,7 +766,6 @@ config HID_NTRIG config HID_ORTEK tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad" - depends on HID help There are certain devices which have LogicalMaximum wrong in the keyboard usage page of their report descriptor. The most prevailing ones so far @@ -824,7 +778,6 @@ config HID_ORTEK config HID_PANTHERLORD tristate "Pantherlord/GreenAsia game controller" - depends on HID help Say Y here if you have a PantherLord/GreenAsia based game controller or adapter. @@ -850,13 +803,11 @@ config HID_PENMOUNT config HID_PETALYNX tristate "Petalynx Maxter remote control" - depends on HID help Support for Petalynx Maxter remote control. config HID_PICOLCD tristate "PicoLCD (graphic version)" - depends on HID help This provides support for Minibox PicoLCD devices, currently only the graphical ones are supported. @@ -922,7 +873,6 @@ config HID_PICOLCD_CIR config HID_PLANTRONICS tristate "Plantronics USB HID Driver" - depends on HID help Provides HID support for Plantronics USB audio devices. Correctly maps vendor unique volume up/down HID usages to @@ -933,7 +883,6 @@ config HID_PLANTRONICS config HID_PLAYSTATION tristate "PlayStation HID Driver" - depends on HID depends on LEDS_CLASS_MULTICOLOR select CRC32 select POWER_SUPPLY @@ -952,14 +901,12 @@ config PLAYSTATION_FF config HID_RAZER tristate "Razer non-fully HID-compliant devices" - depends on HID help Support for Razer devices that are not fully compliant with the HID standard. config HID_PRIMAX tristate "Primax non-fully HID-compliant devices" - depends on HID help Support for Primax devices that are not fully compliant with the HID standard. @@ -981,7 +928,6 @@ config HID_ROCCAT config HID_SAITEK tristate "Saitek (Mad Catz) non-fully HID-compliant devices" - depends on HID help Support for Saitek devices that are not fully compliant with the HID standard. @@ -999,7 +945,6 @@ config HID_SAMSUNG config HID_SEMITEK tristate "Semitek USB keyboards" - depends on HID help Support for Semitek USB keyboards that are not fully compliant with the HID standard. @@ -1050,13 +995,11 @@ config SONY_FF config HID_SPEEDLINK tristate "Speedlink VAD Cezanne mouse support" - depends on HID help Support for Speedlink Vicious and Divine Cezanne mouse. config HID_STEAM tristate "Steam Controller support" - depends on HID select POWER_SUPPLY help Say Y here if you have a Steam Controller if you want to use it @@ -1065,19 +1008,16 @@ config HID_STEAM config HID_STEELSERIES tristate "Steelseries SRW-S1 steering wheel support" - depends on HID help Support for Steelseries SRW-S1 steering wheel config HID_SUNPLUS tristate "Sunplus wireless desktop" - depends on HID help Support for Sunplus wireless desktop. config HID_RMI tristate "Synaptics RMI4 device support" - depends on HID select RMI4_CORE select RMI4_F03 select RMI4_F11 @@ -1090,7 +1030,6 @@ config HID_RMI config HID_GREENASIA tristate "GreenAsia (Product ID 0x12) game controller support" - depends on HID help Say Y here if you have a GreenAsia (Product ID 0x12) based game controller or adapter. @@ -1112,7 +1051,6 @@ config HID_HYPERV_MOUSE config HID_SMARTJOYPLUS tristate "SmartJoy PLUS PS2/USB adapter support" - depends on HID help Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box, Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro. @@ -1130,20 +1068,17 @@ config SMARTJOYPLUS_FF config HID_TIVO tristate "TiVo Slide Bluetooth remote control support" - depends on HID help Say Y if you have a TiVo Slide Bluetooth remote control. config HID_TOPSEED tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support" - depends on HID help Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic CLLRCMCE remote control. config HID_THINGM tristate "ThingM blink(1) USB RGB LED" - depends on HID depends on LEDS_CLASS select HID_LED help @@ -1170,7 +1105,6 @@ config THRUSTMASTER_FF config HID_UDRAW_PS3 tristate "THQ PS3 uDraw tablet" - depends on HID help Say Y here if you want to use the THQ uDraw gaming tablet for the PS3. @@ -1207,7 +1141,6 @@ config HID_WACOM config HID_WIIMOTE tristate "Nintendo Wii / Wii U peripherals" - depends on HID depends on LEDS_CLASS select POWER_SUPPLY select INPUT_FF_MEMLESS @@ -1232,7 +1165,6 @@ config HID_WIIMOTE config HID_XINMO tristate "Xin-Mo non-fully compliant devices" - depends on HID help Support for Xin-Mo devices that are not fully compliant with the HID standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here @@ -1240,7 +1172,6 @@ config HID_XINMO config HID_ZEROPLUS tristate "Zeroplus based game controller support" - depends on HID help Say Y here if you have a Zeroplus based game controller. @@ -1254,13 +1185,12 @@ config ZEROPLUS_FF config HID_ZYDACRON tristate "Zydacron remote control support" - depends on HID help Support for Zydacron remote control. config HID_SENSOR_HUB tristate "HID Sensors framework support" - depends on HID && HAS_IOMEM + depends on HAS_IOMEM select MFD_CORE default n help @@ -1289,7 +1219,6 @@ config HID_SENSOR_CUSTOM_SENSOR config HID_ALPS tristate "Alps HID device support" - depends on HID help Support for Alps I2C HID touchpads and StickPointer. Say Y here if you have a Alps touchpads over i2c-hid or usbhid From 486da113c698a748bd8d75a0d10a2eee8ef8d416 Mon Sep 17 00:00:00 2001 From: Jiangshan Yi Date: Wed, 13 Jul 2022 11:20:47 +0800 Subject: [PATCH 13/38] HID: rmi: replace ternary operator with min() Fix the following coccicheck warning: drivers/hid/hid-rmi.c:240: WARNING opportunity for min(). drivers/hid/hid-rmi.c:350: WARNING opportunity for min(). min() macro is defined in include/linux/minmax.h. It avoids multiple evaluations of the arguments when non-constant and performs strict type-checking. Signed-off-by: Jiangshan Yi Signed-off-by: Jiri Kosina --- drivers/hid/hid-rmi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 311eee599ce97..bb1f423f4ace3 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -237,8 +237,7 @@ static int rmi_hid_read_block(struct rmi_transport_dev *xport, u16 addr, read_input_count = data->readReport[1]; memcpy(buf + bytes_read, &data->readReport[2], - read_input_count < bytes_needed ? - read_input_count : bytes_needed); + min(read_input_count, bytes_needed)); bytes_read += read_input_count; bytes_needed -= read_input_count; @@ -347,8 +346,7 @@ static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size) return 0; } - memcpy(hdata->readReport, data, size < hdata->input_report_size ? - size : hdata->input_report_size); + memcpy(hdata->readReport, data, min((u32)size, hdata->input_report_size)); set_bit(RMI_READ_DATA_PENDING, &hdata->flags); wake_up(&hdata->wait); From 35f473864f1dcfdd04a247fb2b2f7e44449102d4 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 2 Aug 2022 21:35:57 +0200 Subject: [PATCH 14/38] HID: wacom: Simplify comments Remove a left-over from commit 2874c5fd2842 ("treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152"). An empty comment block can be removed. While at it remove, also remove what is supposed to be the path/filename of the file. This is really low value... and wrong since commit 471d17148c8b ("Input: wacom - move the USB (now hid) Wacom driver in drivers/hid") Signed-off-by: Christophe JAILLET Reviewed-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom.h | 5 +---- drivers/hid/wacom_sys.c | 5 ----- drivers/hid/wacom_wac.c | 5 ----- drivers/hid/wacom_wac.h | 4 +--- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 3f8b24a57014b..4da50e19808ef 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * drivers/input/tablet/wacom.h - * * USB Wacom tablet support * * Copyright (c) 2000-2004 Vojtech Pavlik @@ -78,10 +76,9 @@ * - integration of the Bluetooth devices */ -/* - */ #ifndef WACOM_H #define WACOM_H + #include #include #include diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 194a2e3275914..21612fdae9c35 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1,13 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * drivers/input/tablet/wacom_sys.c - * * USB Wacom tablet support - system specific code */ -/* - */ - #include "wacom_wac.h" #include "wacom.h" #include diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d049239256a26..1bbd24ebacad4 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1,13 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * drivers/input/tablet/wacom_wac.c - * * USB Wacom tablet support - Wacom specific code */ -/* - */ - #include "wacom_wac.h" #include "wacom.h" #include diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index fef1538005b5d..5ca6c06d143be 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -1,7 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * drivers/input/tablet/wacom_wac.h - */ + #ifndef WACOM_WAC_H #define WACOM_WAC_H From 9f4441fcbb7219b4e6ea4554f404209a433d4f52 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 4 Aug 2022 13:31:16 +0200 Subject: [PATCH 15/38] HID: vivaldi: convert to use dev_groups There is no need for a driver to individually add/create device groups, the driver core will do it automatically for you. Convert the hid-vivaldi core driver to use the dev_groups pointer instead of manually calling the driver core to create the group and have it be cleaned up later on by the devm core. Cc: Jiri Kosina Cc: Benjamin Tissoires Cc: linux-input@vger.kernel.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jiri Kosina --- drivers/hid/hid-google-hammer.c | 4 +++- drivers/hid/hid-vivaldi-common.c | 29 +++++++++++++++-------------- drivers/hid/hid-vivaldi-common.h | 4 +--- drivers/hid/hid-vivaldi.c | 4 +++- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index ff40f1e55c217..7ae5f27df54dd 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -608,9 +608,11 @@ static struct hid_driver hammer_driver = { .probe = hammer_probe, .remove = hammer_remove, .feature_mapping = vivaldi_feature_mapping, - .input_configured = vivaldi_input_configured, .input_mapping = hammer_input_mapping, .event = hammer_event, + .driver = { + .dev_groups = vivaldi_attribute_groups, + }, }; static int __init hammer_init(void) diff --git a/drivers/hid/hid-vivaldi-common.c b/drivers/hid/hid-vivaldi-common.c index 8b3e515d0f06d..b0af2be948952 100644 --- a/drivers/hid/hid-vivaldi-common.c +++ b/drivers/hid/hid-vivaldi-common.c @@ -116,25 +116,26 @@ static struct attribute *vivaldi_sysfs_attrs[] = { NULL }; -static const struct attribute_group vivaldi_attribute_group = { - .attrs = vivaldi_sysfs_attrs, -}; - -/** - * vivaldi_input_configured - Complete initialization of device using vivaldi map - * @hdev: HID device to which vivaldi attributes should be attached - * @hidinput: HID input device (unused) - */ -int vivaldi_input_configured(struct hid_device *hdev, - struct hid_input *hidinput) +static umode_t vivaldi_is_visible(struct kobject *kobj, struct attribute *attr, + int n) { + struct hid_device *hdev = to_hid_device(kobj_to_dev(kobj)); struct vivaldi_data *data = hid_get_drvdata(hdev); if (!data->num_function_row_keys) return 0; - - return devm_device_add_group(&hdev->dev, &vivaldi_attribute_group); + return attr->mode; } -EXPORT_SYMBOL_GPL(vivaldi_input_configured); + +static const struct attribute_group vivaldi_attribute_group = { + .attrs = vivaldi_sysfs_attrs, + .is_visible = vivaldi_is_visible, +}; + +const struct attribute_group *vivaldi_attribute_groups[] = { + &vivaldi_attribute_group, + NULL, +}; +EXPORT_SYMBOL_GPL(vivaldi_attribute_groups); MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-vivaldi-common.h b/drivers/hid/hid-vivaldi-common.h index d42e82d77825b..ba9adfa08a2d7 100644 --- a/drivers/hid/hid-vivaldi-common.h +++ b/drivers/hid/hid-vivaldi-common.h @@ -4,13 +4,11 @@ struct hid_device; struct hid_field; -struct hid_input; struct hid_usage; void vivaldi_feature_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage); -int vivaldi_input_configured(struct hid_device *hdev, - struct hid_input *hidinput); +extern const struct attribute_group *vivaldi_attribute_groups[]; #endif /* _HID_VIVALDI_COMMON_H */ diff --git a/drivers/hid/hid-vivaldi.c b/drivers/hid/hid-vivaldi.c index 3a979123e7d33..cda5938fb0706 100644 --- a/drivers/hid/hid-vivaldi.c +++ b/drivers/hid/hid-vivaldi.c @@ -45,7 +45,9 @@ static struct hid_driver hid_vivaldi = { .id_table = vivaldi_table, .probe = vivaldi_probe, .feature_mapping = vivaldi_feature_mapping, - .input_configured = vivaldi_input_configured, + .driver = { + .dev_groups = vivaldi_attribute_groups, + }, }; module_hid_driver(hid_vivaldi); From eeeec27d68204701cc5d49d79f7ba811e8438109 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 23:00:09 +0200 Subject: [PATCH 16/38] HID: move from strlcpy with unused retval to strscpy Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Signed-off-by: Jiri Kosina --- drivers/hid/hid-steam.c | 8 ++++---- drivers/hid/i2c-hid/i2c-hid-core.c | 2 +- drivers/hid/usbhid/hid-core.c | 2 +- drivers/hid/usbhid/usbkbd.c | 2 +- drivers/hid/usbhid/usbmouse.c | 2 +- drivers/hid/wacom_sys.c | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index a3b151b29bd71..f675e1aa08c96 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -246,7 +246,7 @@ static int steam_get_serial(struct steam_device *steam) if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) return -EIO; reply[3 + STEAM_SERIAL_LEN] = 0; - strlcpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); + strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); return 0; } @@ -514,7 +514,7 @@ static int steam_register(struct steam_device *steam) */ mutex_lock(&steam->mutex); if (steam_get_serial(steam) < 0) - strlcpy(steam->serial_no, "XXXXXXXXXX", + strscpy(steam->serial_no, "XXXXXXXXXX", sizeof(steam->serial_no)); mutex_unlock(&steam->mutex); @@ -689,9 +689,9 @@ static struct hid_device *steam_create_client_hid(struct hid_device *hdev) client_hdev->version = hdev->version; client_hdev->type = hdev->type; client_hdev->country = hdev->country; - strlcpy(client_hdev->name, hdev->name, + strscpy(client_hdev->name, hdev->name, sizeof(client_hdev->name)); - strlcpy(client_hdev->phys, hdev->phys, + strscpy(client_hdev->phys, hdev->phys, sizeof(client_hdev->phys)); /* * Since we use the same device info than the real interface to diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index c078f09a2318a..347c80ec6fff2 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -1036,7 +1036,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", client->name, (u16)hid->vendor, (u16)hid->product); - strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); + strscpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 4490e2f7252ac..be4c731aaa65d 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1381,7 +1381,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * hid->type = HID_TYPE_USBNONE; if (dev->manufacturer) - strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); + strscpy(hid->name, dev->manufacturer, sizeof(hid->name)); if (dev->product) { if (dev->manufacturer) diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index b4b007c4beb6e..c439ed2f16dbc 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -294,7 +294,7 @@ static int usb_kbd_probe(struct usb_interface *iface, spin_lock_init(&kbd->leds_lock); if (dev->manufacturer) - strlcpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); + strscpy(kbd->name, dev->manufacturer, sizeof(kbd->name)); if (dev->product) { if (dev->manufacturer) diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c index fb1d7d1f69994..3fd93c2e4f4ad 100644 --- a/drivers/hid/usbhid/usbmouse.c +++ b/drivers/hid/usbhid/usbmouse.c @@ -142,7 +142,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i mouse->dev = input_dev; if (dev->manufacturer) - strlcpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); + strscpy(mouse->name, dev->manufacturer, sizeof(mouse->name)); if (dev->product) { if (dev->manufacturer) diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 194a2e3275914..102302e9afd99 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2226,7 +2226,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) } else if (strstr(product_name, "Wacom") || strstr(product_name, "wacom") || strstr(product_name, "WACOM")) { - strlcpy(name, product_name, sizeof(name)); + strscpy(name, product_name, sizeof(name)); } else { snprintf(name, sizeof(name), "Wacom %s", product_name); } @@ -2244,7 +2244,7 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) if (name[strlen(name)-1] == ' ') name[strlen(name)-1] = '\0'; } else { - strlcpy(name, features->name, sizeof(name)); + strscpy(name, features->name, sizeof(name)); } snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s", @@ -2509,7 +2509,7 @@ static void wacom_wireless_work(struct work_struct *work) goto fail; } - strlcpy(wacom_wac->name, wacom_wac1->name, + strscpy(wacom_wac->name, wacom_wac1->name, sizeof(wacom_wac->name)); error = wacom_initialize_battery(wacom); if (error) From 0627f3df95e1609693f89e7ceb4156ac5db6e358 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 26 Aug 2022 14:34:02 -0700 Subject: [PATCH 17/38] HID: wacom: Add new Intuos Pro Small (PTH-460) device IDs Add the new PIDs to wacom_wac.c to support the new model in the Intuos Pro series. Signed-off-by: Ping Cheng Tested-by: Aaron Armstrong Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index d049239256a26..e4ae7fafe359c 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -4875,6 +4875,10 @@ static const struct wacom_features wacom_features_0x3c6 = static const struct wacom_features wacom_features_0x3c8 = { "Wacom Intuos BT M", 21600, 13500, 4095, 63, INTUOSHT3_BT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, 4 }; +static const struct wacom_features wacom_features_0x3dd = + { "Wacom Intuos Pro S", 31920, 19950, 8191, 63, + INTUOSP2S_BT, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 7, + .touch_max = 10 }; static const struct wacom_features wacom_features_HID_ANY_ID = { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; @@ -5050,6 +5054,7 @@ const struct hid_device_id wacom_ids[] = { { BT_DEVICE_WACOM(0x393) }, { BT_DEVICE_WACOM(0x3c6) }, { BT_DEVICE_WACOM(0x3c8) }, + { BT_DEVICE_WACOM(0x3dd) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, From 80305f97c3a46f8e01c9974b8efc7619a422251c Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 30 Aug 2022 15:25:45 +0200 Subject: [PATCH 18/38] HID: core: Export hid_match_id() Export hid_match_id() so it can be used in device-specific drivers to implement their own matching with open-coding a match function. Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b7f5566e338d7..72f8d8835b34c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2088,6 +2088,7 @@ const struct hid_device_id *hid_match_id(const struct hid_device *hdev, return NULL; } +EXPORT_SYMBOL_GPL(hid_match_id); static const struct hid_device_id hid_hiddev_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS) }, From 532223c8ac57605a10e46dc0ab23dcf01c9acb43 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 30 Aug 2022 15:25:46 +0200 Subject: [PATCH 19/38] HID: logitech-hidpp: Enable HID++ for all the Logitech Bluetooth devices Probe for HID++ support over Bluetooth for all the Logitech Bluetooth devices. As Logitech doesn't have a list of Bluetooth devices that support HID++ over Bluetooth, probe every device. The HID++ driver will fall back to plain HID if the device does not support HID++, or to a another device-specific driver if it is part of the unhandled_hidpp_devices array, used in the match function. Note that this change might cause upower to export 2 batteries for certain Bluetooth LE devices which export their battery information through the Bluetooth BATT profile. This particular bug is tracked at: https://gitlab.freedesktop.org/upower/upower/-/issues/166 Tested with a Logitech Signature M650 mouse, over Bluetooth Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 68f9e9d207f42..641c897bf714a 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4219,6 +4219,21 @@ static void hidpp_remove(struct hid_device *hdev) mutex_destroy(&hidpp->send_mutex); } +static const struct hid_device_id unhandled_hidpp_devices[] = { + /* Logitech Harmony Adapter for PS3, handled in hid-sony */ + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3) }, + /* Handled in hid-generic */ + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD) }, + {} +}; + +static bool hidpp_match(struct hid_device *hdev, + bool ignore_special_driver) +{ + /* Refuse to handle devices handled by other HID drivers */ + return !hid_match_id(hdev, unhandled_hidpp_devices); +} + #define LDJ_DEVICE(product) \ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \ USB_VENDOR_ID_LOGITECH, (product)) @@ -4347,6 +4362,9 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX Master 3 mouse over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, + + { /* And try to enable HID++ for all the Logitech Bluetooth devices */ + HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) }, {} }; @@ -4360,6 +4378,7 @@ static const struct hid_usage_id hidpp_usages[] = { static struct hid_driver hidpp_driver = { .name = "logitech-hidpp-device", .id_table = hidpp_devices, + .match = hidpp_match, .report_fixup = hidpp_report_fixup, .probe = hidpp_probe, .remove = hidpp_remove, From 8544c812e43ab7bdf40458411b83987b8cba924d Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 30 Aug 2022 15:25:47 +0200 Subject: [PATCH 20/38] HID: logitech-hidpp: Remove special-casing of Bluetooth devices Now that all the Logitech Bluetooth devices are probed for HID++ support, remove the handling of those 2 devices without any quirks, as they're duplicates. Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 641c897bf714a..98ebedb73d980 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4350,13 +4350,9 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX5500 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, - { /* M-RCQ142 V470 Cordless Laser Mouse over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb008) }, { /* MX Master mouse over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* MX Ergo trackball over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01d) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, { /* MX Master 3 mouse over Bluetooth */ From f7b7393cc3b04e288de85790b1c8e62af99799c2 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 30 Aug 2022 15:25:48 +0200 Subject: [PATCH 21/38] HID: logitech-hidpp: Fix "Sw. Id." for HID++ 2.0 commands Always set a non-zero "Sw. Id." in the lower nibble of the Function/ASE and Software Identifier byte in HID++ 2.0 commands. As per the "Protocol HID++2.0 essential features" section in https://lekensteyn.nl/files/logitech/logitech_hidpp_2.0_specification_draft_2012-06-04.pdf " Software identifier (4 bits, unsigned) A number uniquely defining the software that sends a request. The firmware must copy the software identifier in the response but does not use it in any other ways. 0 Do not use (allows to distinguish a notification from a response). " Link: https://bugzilla.kernel.org/show_bug.cgi?id=215699 Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 98ebedb73d980..e51ccf2c04e3a 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -41,6 +41,9 @@ module_param(disable_tap_to_click, bool, 0644); MODULE_PARM_DESC(disable_tap_to_click, "Disable Tap-To-Click mode reporting for touchpads (only on the K400 currently)."); +/* Define a non-zero software ID to identify our own requests */ +#define LINUX_KERNEL_SW_ID 0x01 + #define REPORT_ID_HIDPP_SHORT 0x10 #define REPORT_ID_HIDPP_LONG 0x11 #define REPORT_ID_HIDPP_VERY_LONG 0x12 @@ -343,7 +346,7 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp, else message->report_id = REPORT_ID_HIDPP_LONG; message->fap.feature_index = feat_index; - message->fap.funcindex_clientid = funcindex_clientid; + message->fap.funcindex_clientid = funcindex_clientid | LINUX_KERNEL_SW_ID; memcpy(&message->fap.params, params, param_count); ret = hidpp_send_message_sync(hidpp, message, response); From 0799617f3809d9f096fa18942391ef98ebb023b7 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Tue, 30 Aug 2022 15:25:49 +0200 Subject: [PATCH 22/38] HID: logitech-hidpp: Remove hard-coded "Sw. Id." for HID++ 2.0 commands Some HID++ 2.0 commands had correctly set a non-zero software identifier directly as part of their function identifiers, but it's more correct to define the function identifier and the software identifier separately before combined them when the command is sent. As this is now done in the previous commit, remove the hard-coded 0x1 software identifiers in the function definitions. Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-hidpp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index e51ccf2c04e3a..74013d0e0a243 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -859,8 +859,8 @@ static int hidpp_unifying_init(struct hidpp_device *hidpp) #define HIDPP_PAGE_ROOT 0x0000 #define HIDPP_PAGE_ROOT_IDX 0x00 -#define CMD_ROOT_GET_FEATURE 0x01 -#define CMD_ROOT_GET_PROTOCOL_VERSION 0x11 +#define CMD_ROOT_GET_FEATURE 0x00 +#define CMD_ROOT_GET_PROTOCOL_VERSION 0x10 static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, u8 *feature_index, u8 *feature_type) @@ -937,9 +937,9 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) #define HIDPP_PAGE_GET_DEVICE_NAME_TYPE 0x0005 -#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x01 -#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11 -#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x21 +#define CMD_GET_DEVICE_NAME_TYPE_GET_COUNT 0x00 +#define CMD_GET_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x10 +#define CMD_GET_DEVICE_NAME_TYPE_GET_TYPE 0x20 static int hidpp_devicenametype_get_count(struct hidpp_device *hidpp, u8 feature_index, u8 *nameLength) @@ -1969,8 +1969,8 @@ static int hidpp_touchpad_fw_items_set(struct hidpp_device *hidpp, #define HIDPP_PAGE_TOUCHPAD_RAW_XY 0x6100 -#define CMD_TOUCHPAD_GET_RAW_INFO 0x01 -#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x21 +#define CMD_TOUCHPAD_GET_RAW_INFO 0x00 +#define CMD_TOUCHPAD_SET_RAW_REPORT_STATE 0x20 #define EVENT_TOUCHPAD_RAW_XY 0x00 From 908d325e1665b2781085580070554cbbe5fc3c89 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 14 Sep 2022 15:21:46 +0200 Subject: [PATCH 23/38] HID: logitech-hidpp: Detect hi-res scrolling support Rather than relying on a never-ending stream of patches for quirks. This change will detect whether HID++ 1.0 hi-res scroll, HID++ 2.0 hi-res scroll or HID++ 2.0 hi-res scroll wheel is supported, and enable the feature without the need for quirks. Tested on a Logitech M705 mouse that was unsupported before this change. [ 9.365324] logitech-hidpp-device 0003:046D:406D.0006: input,hidraw3: USB HID v1.11 Mouse [Logitech M705] on usb-0000:00:14.0-4/input2:3 [ 57.472434] logitech-hidpp-device 0003:046D:406D.0006: HID++ 4.5 device connected. [ 57.616429] logitech-hidpp-device 0003:046D:406D.0006: Detected HID++ 2.0 hi-res scroll wheel [ 57.712424] logitech-hidpp-device 0003:046D:406D.0006: wheel multiplier = 8 Link: https://bugzilla.kernel.org/show_bug.cgi?id=216480 Signed-off-by: Bastien Nocera Reviewed-by: Harry Cutts Tested-by: Peter F. Patel-Schneider Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220914132146.6435-1-hadess@hadess.net --- drivers/hid/hid-logitech-hidpp.c | 118 ++++++++++++++++--------------- 1 file changed, 61 insertions(+), 57 deletions(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 74013d0e0a243..5f8261c7b74cd 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -74,21 +74,18 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_QUIRK_NO_HIDINPUT BIT(23) #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24) #define HIDPP_QUIRK_UNIFYING BIT(25) -#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(26) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2120 BIT(27) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2121 BIT(28) -#define HIDPP_QUIRK_HIDPP_WHEELS BIT(29) -#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(30) -#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(31) +#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26) +#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27) +#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28) /* These are just aliases for now */ #define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS #define HIDPP_QUIRK_KBD_ZOOM_WHEEL HIDPP_QUIRK_HIDPP_WHEELS /* Convenience constant to check for any high-res support. */ -#define HIDPP_QUIRK_HI_RES_SCROLL (HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ - HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \ - HIDPP_QUIRK_HI_RES_SCROLL_X2121) +#define HIDPP_CAPABILITY_HI_RES_SCROLL (HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL | \ + HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL | \ + HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) #define HIDPP_QUIRK_DELAYED_INIT HIDPP_QUIRK_NO_HIDINPUT @@ -99,6 +96,9 @@ MODULE_PARM_DESC(disable_tap_to_click, #define HIDPP_CAPABILITY_BATTERY_VOLTAGE BIT(4) #define HIDPP_CAPABILITY_BATTERY_PERCENTAGE BIT(5) #define HIDPP_CAPABILITY_UNIFIED_BATTERY BIT(6) +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL BIT(7) +#define HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL BIT(8) +#define HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL BIT(9) #define lg_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) @@ -3418,14 +3418,14 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) int ret; u8 multiplier = 1; - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) { + if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL) { ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false); if (ret == 0) ret = hidpp_hrw_get_wheel_capability(hidpp, &multiplier); - } else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) { + } else if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL) { ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true, &multiplier); - } else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */ { + } else /* if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL) */ { ret = hidpp10_enable_scrolling_acceleration(hidpp); multiplier = 8; } @@ -3440,6 +3440,49 @@ static int hi_res_scroll_enable(struct hidpp_device *hidpp) return 0; } +static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) +{ + int ret; + unsigned long capabilities; + + capabilities = hidpp->capabilities; + + if (hidpp->protocol_major >= 2) { + u8 feature_index; + u8 feature_type; + + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL, + &feature_index, &feature_type); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_WHEEL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scroll wheel\n"); + return 0; + } + ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HI_RESOLUTION_SCROLLING, + &feature_index, &feature_type); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP20_HI_RES_SCROLL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 2.0 hi-res scrolling\n"); + } + } else { + struct hidpp_report response; + + ret = hidpp_send_rap_command_sync(hidpp, + REPORT_ID_HIDPP_SHORT, + HIDPP_GET_REGISTER, + HIDPP_ENABLE_FAST_SCROLL, + NULL, 0, &response); + if (!ret) { + hidpp->capabilities |= HIDPP_CAPABILITY_HIDPP10_FAST_SCROLL; + hid_dbg(hidpp->hid_dev, "Detected HID++ 1.0 fast scroll\n"); + } + } + + if (hidpp->capabilities == capabilities) + hid_dbg(hidpp->hid_dev, "Did not detect HID++ hi-res scrolling hardware support\n"); + return 0; +} + /* -------------------------------------------------------------------------- */ /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ @@ -3694,8 +3737,9 @@ static int hidpp_event(struct hid_device *hdev, struct hid_field *field, * cases we must return early (falling back to default behaviour) to * avoid a crash in hidpp_scroll_counter_handle_scroll. */ - if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 - || hidpp->input == NULL || counter->wheel_multiplier == 0) + if (!(hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) + || value == 0 || hidpp->input == NULL + || counter->wheel_multiplier == 0) return 0; hidpp_scroll_counter_handle_scroll(hidpp->input, counter, value); @@ -3927,6 +3971,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) } hidpp_initialize_battery(hidpp); + hidpp_initialize_hires_scroll(hidpp); /* forward current battery state */ if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP10_BATTERY) { @@ -3946,7 +3991,7 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) if (hidpp->battery.ps) power_supply_changed(hidpp->battery.ps); - if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) + if (hidpp->capabilities & HIDPP_CAPABILITY_HI_RES_SCROLL) hi_res_scroll_enable(hidpp); if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input) @@ -4257,42 +4302,9 @@ static const struct hid_device_id hidpp_devices[] = { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_T651), .driver_data = HIDPP_QUIRK_CLASS_WTP }, - { /* Mouse Logitech Anywhere MX */ - LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, - { /* Mouse Logitech Cube */ - LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, - { /* Mouse Logitech M335 */ - LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech M515 */ - LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, { /* Mouse logitech M560 */ LDJ_DEVICE(0x402d), - .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 - | HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, - { /* Mouse Logitech M705 (firmware RQM17) */ - LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, - { /* Mouse Logitech M705 (firmware RQM67) */ - LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech M720 */ - LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Anywhere 2 */ - LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4072), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Anywhere 2S */ - LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master */ - LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master 2S */ - LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech MX Master 3 */ - LDJ_DEVICE(0x4082), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* Mouse Logitech Performance MX */ - LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, + .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, { /* Keyboard logitech K400 */ LDJ_DEVICE(0x4024), .driver_data = HIDPP_QUIRK_CLASS_K400 }, @@ -4353,14 +4365,6 @@ static const struct hid_device_id hidpp_devices[] = { { /* MX5500 keyboard over Bluetooth */ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb30b), .driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS }, - { /* MX Master mouse over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb012), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb01e), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, - { /* MX Master 3 mouse over Bluetooth */ - HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, 0xb023), - .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, { /* And try to enable HID++ for all the Logitech Bluetooth devices */ HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_ANY, USB_VENDOR_ID_LOGITECH, HID_ANY_ID) }, From 98d67f250472cdd0f8d083830be3ec9dbb0c65a8 Mon Sep 17 00:00:00 2001 From: Hangyu Hua Date: Fri, 12 Aug 2022 10:55:15 +0800 Subject: [PATCH 24/38] hid: hid-logitech-hidpp: avoid unnecessary assignments in hidpp_connect_event hidpp->delayed_input can't be assigned to an object that already call input_free_device when input_register_device fails. Fixes: c39e3d5fc9dd ("HID: logitech-hidpp: late bind the input device on wireless connection") Signed-off-by: Hangyu Hua Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220812025515.19467-1-hbh25y@gmail.com --- drivers/hid/hid-logitech-hidpp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 5f8261c7b74cd..71a9c258a20bc 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -4007,8 +4007,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) hidpp_populate_input(hidpp, input); ret = input_register_device(input); - if (ret) + if (ret) { input_free_device(input); + return; + } hidpp->delayed_input = input; } From 454d243a00f50c2bd5ffb69a5ae16c462929d52f Mon Sep 17 00:00:00 2001 From: Shaomin Deng Date: Sun, 4 Sep 2022 11:45:15 -0400 Subject: [PATCH 25/38] HID: sony: Fix double word in comments Remove the repeated word "not" in comments. Signed-off-by: Shaomin Deng Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220904154515.25143-1-dengshaomin@cdjrlc.com --- drivers/hid/hid-sony.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 60ec2b29d54de..03691cdcfb8e1 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -368,7 +368,7 @@ static const unsigned int buzz_keymap[] = { }; /* The Navigation controller is a partial DS3 and uses the same HID report - * and hence the same keymap indices, however not not all axes/buttons + * and hence the same keymap indices, however not all axes/buttons * are physically present. We use the same axis and button mapping as * the DS3, which uses the Linux gamepad spec. */ From 2c5e8e61402557119a086a994d2be06a535f5f30 Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Fri, 2 Sep 2022 10:25:52 +0200 Subject: [PATCH 26/38] HID: Add driver for VRC-2 Car Controller VRC-2 is 2-axis controller often used in car simulators. Signed-off-by: Marcus Folkesson Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220902082552.2433744-2-marcus.folkesson@gmail.com --- MAINTAINERS | 6 +++ drivers/hid/Kconfig | 10 +++++ drivers/hid/Makefile | 1 + drivers/hid/hid-vrc2.c | 91 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 drivers/hid/hid-vrc2.c diff --git a/MAINTAINERS b/MAINTAINERS index 589517372408c..40aae61d73a99 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9065,6 +9065,12 @@ F: drivers/hid/hid-sensor-* F: drivers/iio/*/hid-* F: include/linux/hid-sensor-* +HID VRC-2 CAR CONTROLLER DRIVER +M: Marcus Folkesson +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-vrc2.c + HID WACOM DRIVER M: Ping Cheng M: Jason Gerecke diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ce92830b5d1f..f051d29ae4f83 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -481,6 +481,16 @@ config HID_VIEWSONIC help Support for ViewSonic/Signotec PD1011 signature pad. +config HID_VRC2 + tristate "VRC-2 Car Controller" + depends on HID + help + Support for VRC-2 which is a 2-axis controller often used in + car simulators. + + To compile this driver as a module, choose M here: the + module will be called hid-vrc2. + config HID_XIAOMI tristate "Xiaomi" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b0bef80981394..be4f78d6482f1 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -136,6 +136,7 @@ obj-$(CONFIG_HID_XINMO) += hid-xinmo.o obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o +obj-$(CONFIG_HID_VRC2) += hid-vrc2.o wacom-objs := wacom_wac.o wacom_sys.o obj-$(CONFIG_HID_WACOM) += wacom.o diff --git a/drivers/hid/hid-vrc2.c b/drivers/hid/hid-vrc2.c new file mode 100644 index 0000000000000..80a2b7ef5e66a --- /dev/null +++ b/drivers/hid/hid-vrc2.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID driver for VRC-2 2-axis Car controller + * + * Copyright (C) 2022 Marcus Folkesson + */ + +#include +#include +#include + +/* + * VID/PID are probably "borrowed", so keep them locally and + * do not populate hid-ids.h with those. + */ +#define USB_VENDOR_ID_VRC2 (0x07c0) +#define USB_DEVICE_ID_VRC2 (0x1125) + +static __u8 vrc2_rdesc_fixed[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x04, // Usage (Joystick) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x07, // Logical Maximum (2047) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0xFF, 0x00, // Physical Maximum (255) + 0x75, 0x10, // Report Size (16) + 0x95, 0x02, // Report Count (2) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection + 0x75, 0x08, // Report Size (8) + 0x95, 0x03, // Report Count (3) + 0x81, 0x03, // Input (Cnst,Var,Abs) + 0xC0, // End Collection +}; + +static __u8 *vrc2_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + hid_info(hdev, "fixing up VRC-2 report descriptor\n"); + *rsize = sizeof(vrc2_rdesc_fixed); + return vrc2_rdesc_fixed; +} + +static int vrc2_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + + /* + * The device gives us 2 separate USB endpoints. + * One of those (the one with report descriptor size of 23) is just bogus so ignore it + */ + if (hdev->dev_rsize == 23) + return -ENODEV; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + return ret; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); + return ret; + } + + return 0; +} + +static const struct hid_device_id vrc2_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_VRC2, USB_DEVICE_ID_VRC2) }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(hid, vrc2_devices); + +static struct hid_driver vrc2_driver = { + .name = "vrc2", + .id_table = vrc2_devices, + .report_fixup = vrc2_report_fixup, + .probe = vrc2_probe, +}; +module_hid_driver(vrc2_driver); + +MODULE_AUTHOR("Marcus Folkesson "); +MODULE_DESCRIPTION("HID driver for VRC-2 2-axis Car controller"); +MODULE_LICENSE("GPL"); From acc3e34613da139643af2ce4ca7e7dadf07478d6 Mon Sep 17 00:00:00 2001 From: Marcus Folkesson Date: Wed, 14 Sep 2022 20:43:45 +0200 Subject: [PATCH 27/38] HID: Add driver for PhoenixRC Flight Controller The PhoenixRC is a controller with 8 channels for use in flight simulators. Signed-off-by: Marcus Folkesson Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220914184345.270456-1-marcus.folkesson@gmail.com --- MAINTAINERS | 6 +++ drivers/hid/Kconfig | 9 ++++ drivers/hid/Makefile | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-pxrc.c | 112 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 drivers/hid/hid-pxrc.c diff --git a/MAINTAINERS b/MAINTAINERS index 40aae61d73a99..8a7b24622b988 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9053,6 +9053,12 @@ L: linux-input@vger.kernel.org S: Supported F: drivers/hid/hid-playstation.c +HID PHOENIX RC FLIGHT CONTROLLER +M: Marcus Folkesson +L: linux-input@vger.kernel.org +S: Maintained +F: drivers/hid/hid-pxrc.c + HID SENSOR HUB DRIVERS M: Jiri Kosina M: Jonathan Cameron diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index f051d29ae4f83..4cdc44da2abf1 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -960,6 +960,15 @@ config PLAYSTATION_FF Say Y here if you would like to enable force feedback support for PlayStation game controllers. +config HID_PXRC + tristate "PhoenixRC HID Flight Controller" + depends on HID + help + Support for PhoenixRC HID Flight Controller, a 8-axis flight controller. + + To compile this driver as a module, choose M here: the + module will be called hid-pxrc. + config HID_RAZER tristate "Razer non-fully HID-compliant devices" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index be4f78d6482f1..ad2cdaefb4bd7 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -101,6 +101,7 @@ hid-picolcd-$(CONFIG_DEBUG_FS) += hid-picolcd_debugfs.o obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o obj-$(CONFIG_HID_PLAYSTATION) += hid-playstation.o obj-$(CONFIG_HID_PRIMAX) += hid-primax.o +obj-$(CONFIG_HID_PXRC) += hid-pxrc.o obj-$(CONFIG_HID_RAZER) += hid-razer.o obj-$(CONFIG_HID_REDRAGON) += hid-redragon.o obj-$(CONFIG_HID_RETRODE) += hid-retrode.o diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f80d6193fca6e..b22b2f80e30c8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1386,6 +1386,7 @@ #define USB_VENDOR_ID_MULTIPLE_1781 0x1781 #define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a9d +#define USB_DEVICE_ID_PHOENIXRC 0x0898 #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 diff --git a/drivers/hid/hid-pxrc.c b/drivers/hid/hid-pxrc.c new file mode 100644 index 0000000000000..b0e517f9cde7b --- /dev/null +++ b/drivers/hid/hid-pxrc.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID driver for PhoenixRC 8-axis flight controller + * + * Copyright (C) 2022 Marcus Folkesson + */ + +#include +#include +#include + +#include "hid-ids.h" + +struct pxrc_priv { + u8 slider; + u8 dial; + bool alternate; +}; + +static __u8 pxrc_rdesc_fixed[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x04, // Usage (Joystick) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x30, // Usage (X) + 0x09, 0x36, // Usage (Slider) + 0x09, 0x31, // Usage (Y) + 0x09, 0x32, // Usage (Z) + 0x09, 0x33, // Usage (Rx) + 0x09, 0x34, // Usage (Ry) + 0x09, 0x35, // Usage (Rz) + 0x09, 0x37, // Usage (Dial) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0xFF, 0x00, // Physical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x08, // Report Count (8) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection + 0xC0, // End Collection +}; + +static __u8 *pxrc_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + hid_info(hdev, "fixing up PXRC report descriptor\n"); + *rsize = sizeof(pxrc_rdesc_fixed); + return pxrc_rdesc_fixed; +} + +static int pxrc_raw_event(struct hid_device *hdev, struct hid_report *report, + u8 *data, int size) +{ + struct pxrc_priv *priv = hid_get_drvdata(hdev); + + if (priv->alternate) + priv->slider = data[7]; + else + priv->dial = data[7]; + + data[1] = priv->slider; + data[7] = priv->dial; + + priv->alternate = !priv->alternate; + return 0; +} + +static int pxrc_probe(struct hid_device *hdev, const struct hid_device_id *id) +{ + int ret; + struct pxrc_priv *priv; + + priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + hid_set_drvdata(hdev, priv); + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + return ret; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); + return ret; + } + + return 0; +} + +static const struct hid_device_id pxrc_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_PHOENIXRC) }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(hid, pxrc_devices); + +static struct hid_driver pxrc_driver = { + .name = "hid-pxrc", + .id_table = pxrc_devices, + .report_fixup = pxrc_report_fixup, + .probe = pxrc_probe, + .raw_event = pxrc_raw_event, +}; +module_hid_driver(pxrc_driver); + +MODULE_AUTHOR("Marcus Folkesson "); +MODULE_DESCRIPTION("HID driver for PXRC 8-axis flight controller"); +MODULE_LICENSE("GPL"); From 1e839143d674603b0bbbc4c513bca35404967dbc Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 2 Sep 2022 15:29:23 +0200 Subject: [PATCH 28/38] HID: core: store the unique system identifier in hid_device This unique identifier is currently used only for ensuring uniqueness in sysfs. However, this could be handful for userspace to refer to a specific hid_device by this id. 2 use cases are in my mind: LEDs (and their naming convention), and HID-BPF. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220902132938.2409206-9-benjamin.tissoires@redhat.com --- drivers/hid/hid-core.c | 4 +++- include/linux/hid.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index b7f5566e338d7..a00dd43db8bff 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2739,10 +2739,12 @@ int hid_add_device(struct hid_device *hdev) hid_warn(hdev, "bad device descriptor (%d)\n", ret); } + hdev->id = atomic_inc_return(&id); + /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, - hdev->vendor, hdev->product, atomic_inc_return(&id)); + hdev->vendor, hdev->product, hdev->id); hid_debug_register(hdev, dev_name(&hdev->dev)); ret = device_add(&hdev->dev); diff --git a/include/linux/hid.h b/include/linux/hid.h index 4363a63b9775e..a43dd17bc78fd 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -658,6 +658,8 @@ struct hid_device { /* device report descriptor */ struct list_head debug_list; spinlock_t debug_list_lock; wait_queue_head_t debug_wait; + + unsigned int id; /* system unique id */ }; #define to_hid_device(pdev) \ From ead77b65aef430d3bfe63524c243a60a29eb8d90 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 2 Sep 2022 15:29:24 +0200 Subject: [PATCH 29/38] HID: export hid_report_type to uapi When we are dealing with eBPF, we need to have access to the report type. Currently our implementation differs from the USB standard, making it impossible for users to know the exact value besides hardcoding it themselves. And instead of a blank define, convert it as an enum. Note that we need to also do change in the ll_driver API, but given that this will have a wider impact outside of this tree, we leave this as a TODO for the future. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220902132938.2409206-10-benjamin.tissoires@redhat.com --- drivers/hid/hid-core.c | 13 +++++++------ include/linux/hid.h | 24 ++++++++---------------- include/uapi/linux/hid.h | 12 ++++++++++++ 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index a00dd43db8bff..ab98754522d9f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -55,7 +55,7 @@ MODULE_PARM_DESC(ignore_special_drivers, "Ignore any special drivers and handle */ struct hid_report *hid_register_report(struct hid_device *device, - unsigned int type, unsigned int id, + enum hid_report_type type, unsigned int id, unsigned int application) { struct hid_report_enum *report_enum = device->report_enum + type; @@ -967,7 +967,7 @@ static const char * const hid_report_names[] = { * parsing. */ struct hid_report *hid_validate_values(struct hid_device *hid, - unsigned int type, unsigned int id, + enum hid_report_type type, unsigned int id, unsigned int field_index, unsigned int report_counts) { @@ -1954,8 +1954,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, } EXPORT_SYMBOL_GPL(__hid_request); -int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, - int interrupt) +int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, + int interrupt) { struct hid_report_enum *report_enum = hid->report_enum + type; struct hid_report *report; @@ -2019,7 +2019,8 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event); * * This is data entry for lower layers. */ -int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int interrupt) +int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, + int interrupt) { struct hid_report_enum *report_enum; struct hid_driver *hdrv; @@ -2377,7 +2378,7 @@ EXPORT_SYMBOL_GPL(hid_hw_request); */ int hid_hw_raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, - size_t len, unsigned char rtype, int reqtype) + size_t len, enum hid_report_type rtype, int reqtype) { if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) return -EINVAL; diff --git a/include/linux/hid.h b/include/linux/hid.h index a43dd17bc78fd..b1a33dbbc78e9 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -314,15 +314,6 @@ struct hid_item { #define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065 #define HID_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 -/* - * HID report types --- Ouch! HID spec says 1 2 3! - */ - -#define HID_INPUT_REPORT 0 -#define HID_OUTPUT_REPORT 1 -#define HID_FEATURE_REPORT 2 - -#define HID_REPORT_TYPES 3 /* * HID connect requests @@ -509,7 +500,7 @@ struct hid_report { struct list_head hidinput_list; struct list_head field_entry_list; /* ordered list of input fields */ unsigned int id; /* id of this report */ - unsigned int type; /* report type */ + enum hid_report_type type; /* report type */ unsigned int application; /* application usage for this report */ struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ struct hid_field_entry *field_entries; /* allocated memory of input field_entry */ @@ -926,7 +917,8 @@ extern int hidinput_connect(struct hid_device *hid, unsigned int force); extern void hidinput_disconnect(struct hid_device *); int hid_set_field(struct hid_field *, unsigned, __s32); -int hid_input_report(struct hid_device *, int type, u8 *, u32, int); +int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, + int interrupt); struct hid_field *hidinput_get_led_field(struct hid_device *hid); unsigned int hidinput_count_leds(struct hid_device *hid); __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); @@ -935,11 +927,11 @@ int __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, - unsigned int type, unsigned int id, + enum hid_report_type type, unsigned int id, unsigned int application); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); struct hid_report *hid_validate_values(struct hid_device *hid, - unsigned int type, unsigned int id, + enum hid_report_type type, unsigned int id, unsigned int field_index, unsigned int report_counts); @@ -1111,7 +1103,7 @@ void hid_hw_request(struct hid_device *hdev, struct hid_report *report, int reqtype); int hid_hw_raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, - size_t len, unsigned char rtype, int reqtype); + size_t len, enum hid_report_type rtype, int reqtype); int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len); /** @@ -1184,8 +1176,8 @@ static inline u32 hid_report_len(struct hid_report *report) return DIV_ROUND_UP(report->size, 8) + (report->id > 0); } -int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, - int interrupt); +int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, + int interrupt); /* HID quirks API */ unsigned long hid_lookup_quirk(const struct hid_device *hdev); diff --git a/include/uapi/linux/hid.h b/include/uapi/linux/hid.h index b34492a87a8a4..b25b0bacaff27 100644 --- a/include/uapi/linux/hid.h +++ b/include/uapi/linux/hid.h @@ -42,6 +42,18 @@ #define USB_INTERFACE_PROTOCOL_KEYBOARD 1 #define USB_INTERFACE_PROTOCOL_MOUSE 2 +/* + * HID report types --- Ouch! HID spec says 1 2 3! + */ + +enum hid_report_type { + HID_INPUT_REPORT = 0, + HID_OUTPUT_REPORT = 1, + HID_FEATURE_REPORT = 2, + + HID_REPORT_TYPES, +}; + /* * HID class requests */ From 735e1bb1b8067e209941a6bdfde23214696ff47e Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 2 Sep 2022 15:29:25 +0200 Subject: [PATCH 30/38] HID: convert defines of HID class requests into a proper enum This allows to export the type in BTF and so in the automatically generated vmlinux.h. It will also add some static checks on the users when we change the ll driver API (see not below). Note that we need to also do change in the ll_driver API, but given that this will have a wider impact outside of this tree, we leave this as a TODO for the future. Reviewed-by: Greg Kroah-Hartman Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220902132938.2409206-11-benjamin.tissoires@redhat.com --- drivers/hid/hid-core.c | 6 +++--- include/linux/hid.h | 9 +++++---- include/uapi/linux/hid.h | 14 ++++++++------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ab98754522d9f..aff37d6f587cb 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1921,7 +1921,7 @@ static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, * DO NOT USE in hid drivers directly, but through hid_hw_request instead. */ int __hid_request(struct hid_device *hid, struct hid_report *report, - int reqtype) + enum hid_class_request reqtype) { char *buf; int ret; @@ -2353,7 +2353,7 @@ EXPORT_SYMBOL_GPL(hid_hw_close); * @reqtype: hid request type */ void hid_hw_request(struct hid_device *hdev, - struct hid_report *report, int reqtype) + struct hid_report *report, enum hid_class_request reqtype) { if (hdev->ll_driver->request) return hdev->ll_driver->request(hdev, report, reqtype); @@ -2378,7 +2378,7 @@ EXPORT_SYMBOL_GPL(hid_hw_request); */ int hid_hw_raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, - size_t len, enum hid_report_type rtype, int reqtype) + size_t len, enum hid_report_type rtype, enum hid_class_request reqtype) { if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) return -EINVAL; diff --git a/include/linux/hid.h b/include/linux/hid.h index b1a33dbbc78e9..8677ae38599e4 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -923,7 +923,7 @@ struct hid_field *hidinput_get_led_field(struct hid_device *hid); unsigned int hidinput_count_leds(struct hid_device *hid); __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); void hid_output_report(struct hid_report *report, __u8 *data); -int __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); +int __hid_request(struct hid_device *hid, struct hid_report *rep, enum hid_class_request reqtype); u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, @@ -1100,10 +1100,11 @@ void hid_hw_stop(struct hid_device *hdev); int __must_check hid_hw_open(struct hid_device *hdev); void hid_hw_close(struct hid_device *hdev); void hid_hw_request(struct hid_device *hdev, - struct hid_report *report, int reqtype); + struct hid_report *report, enum hid_class_request reqtype); int hid_hw_raw_request(struct hid_device *hdev, unsigned char reportnum, __u8 *buf, - size_t len, enum hid_report_type rtype, int reqtype); + size_t len, enum hid_report_type rtype, + enum hid_class_request reqtype); int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, size_t len); /** @@ -1131,7 +1132,7 @@ static inline int hid_hw_power(struct hid_device *hdev, int level) * @reqtype: hid request type */ static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle, - int reqtype) + enum hid_class_request reqtype) { if (hdev->ll_driver->idle) return hdev->ll_driver->idle(hdev, report, idle, reqtype); diff --git a/include/uapi/linux/hid.h b/include/uapi/linux/hid.h index b25b0bacaff27..a4dcb34386e39 100644 --- a/include/uapi/linux/hid.h +++ b/include/uapi/linux/hid.h @@ -58,12 +58,14 @@ enum hid_report_type { * HID class requests */ -#define HID_REQ_GET_REPORT 0x01 -#define HID_REQ_GET_IDLE 0x02 -#define HID_REQ_GET_PROTOCOL 0x03 -#define HID_REQ_SET_REPORT 0x09 -#define HID_REQ_SET_IDLE 0x0A -#define HID_REQ_SET_PROTOCOL 0x0B +enum hid_class_request { + HID_REQ_GET_REPORT = 0x01, + HID_REQ_GET_IDLE = 0x02, + HID_REQ_GET_PROTOCOL = 0x03, + HID_REQ_SET_REPORT = 0x09, + HID_REQ_SET_IDLE = 0x0A, + HID_REQ_SET_PROTOCOL = 0x0B, +}; /* * HID class descriptor types From be6e2b5734a425941fcdcdbd2a9337be498ce2cf Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Wed, 7 Sep 2022 15:01:59 +0000 Subject: [PATCH 31/38] HID: multitouch: Add memory barriers This fixes broken atomic checks which cause a race between the release-timer and processing of hid input. I noticed that contacts were sometimes sticking, even with the "sticky fingers" quirk enabled. This fixes that problem. Cc: stable@vger.kernel.org Fixes: 9609827458c3 ("HID: multitouch: optimize the sticky fingers timer") Signed-off-by: Andri Yngvason Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220907150159.2285460-1-andri@yngvason.is --- drivers/hid/hid-multitouch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 2e72922e36f56..91a4d3fc30e08 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1186,7 +1186,7 @@ static void mt_touch_report(struct hid_device *hid, int contact_count = -1; /* sticky fingers release in progress, abort */ - if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) + if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) return; scantime = *app->scantime; @@ -1267,7 +1267,7 @@ static void mt_touch_report(struct hid_device *hid, del_timer(&td->release_timer); } - clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); + clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); } static int mt_touch_input_configured(struct hid_device *hdev, @@ -1699,11 +1699,11 @@ static void mt_expired_timeout(struct timer_list *t) * An input report came in just before we release the sticky fingers, * it will take care of the sticky fingers. */ - if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) + if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) return; if (test_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags)) mt_release_contacts(hdev); - clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); + clear_bit_unlock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags); } static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) From a109d5c45b3d6728b9430716b915afbe16eef27c Mon Sep 17 00:00:00 2001 From: Harry Stern Date: Sat, 10 Sep 2022 20:36:13 -0400 Subject: [PATCH 32/38] hid: topre: Add driver fixing report descriptor The Topre REALFORCE R2 firmware incorrectly reports that interface descriptor number 1, input report descriptor 2's events are array events rather than variable events. That particular report descriptor is used to report keypresses when there are more than 6 keys held at a time. This bug prevents events from this interface from being registered properly, so only 6 keypresses (from a different interface) can be registered at once, rather than full n-key rollover. This commit fixes the bug by setting the correct value in a report_fixup function. The original bug report can be found here: Link: https://gitlab.freedesktop.org/libinput/libinput/-/issues/804 Thanks to Benjamin Tissoires for diagnosing the issue with the report descriptor. Signed-off-by: Harry Stern Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220911003614.297613-1-harry@harrystern.net --- drivers/hid/Kconfig | 6 +++++ drivers/hid/Makefile | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-topre.c | 49 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 drivers/hid/hid-topre.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ce92830b5d1f..c4308d4988dc0 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1141,6 +1141,12 @@ config HID_TOPSEED Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic CLLRCMCE remote control. +config HID_TOPRE + tristate "Topre REALFORCE keyboards" + depends on HID + help + Say Y for N-key rollover support on Topre REALFORCE R2 108 key keyboards. + config HID_THINGM tristate "ThingM blink(1) USB RGB LED" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b0bef80981394..bccaec0d77d36 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -123,6 +123,7 @@ obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o hid-thrustmaster.o obj-$(CONFIG_HID_TIVO) += hid-tivo.o obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o +obj-$(CONFIG_HID_TOPRE) += hid-topre.o obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o obj-$(CONFIG_HID_U2FZERO) += hid-u2fzero.o hid-uclogic-objs := hid-uclogic-core.o \ diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f80d6193fca6e..50bab12d9476f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1231,6 +1231,9 @@ #define USB_DEVICE_ID_TIVO_SLIDE 0x1201 #define USB_DEVICE_ID_TIVO_SLIDE_PRO 0x1203 +#define USB_VENDOR_ID_TOPRE 0x0853 +#define USB_DEVICE_ID_TOPRE_REALFORCE_R2_108 0x0148 + #define USB_VENDOR_ID_TOPSEED 0x0766 #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 diff --git a/drivers/hid/hid-topre.c b/drivers/hid/hid-topre.c new file mode 100644 index 0000000000000..88a91cdad5f80 --- /dev/null +++ b/drivers/hid/hid-topre.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * HID driver for Topre REALFORCE Keyboards + * + * Copyright (c) 2022 Harry Stern + * + * Based on the hid-macally driver + */ + +#include +#include + +#include "hid-ids.h" + +MODULE_AUTHOR("Harry Stern "); +MODULE_DESCRIPTION("REALFORCE R2 Keyboard driver"); +MODULE_LICENSE("GPL"); + +/* + * Fix the REALFORCE R2's non-boot interface's report descriptor to match the + * events it's actually sending. It claims to send array events but is instead + * sending variable events. + */ +static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 && + rdesc[71] == 0x81 && rdesc[72] == 0x00) { + hid_info(hdev, + "fixing up Topre REALFORCE keyboard report descriptor\n"); + rdesc[72] = 0x02; + } + return rdesc; +} + +static const struct hid_device_id topre_id_table[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_TOPRE, + USB_DEVICE_ID_TOPRE_REALFORCE_R2_108) }, + { } +}; +MODULE_DEVICE_TABLE(hid, topre_id_table); + +static struct hid_driver topre_driver = { + .name = "topre", + .id_table = topre_id_table, + .report_fixup = topre_report_fixup, +}; + +module_hid_driver(topre_driver); From cacdb14b1c8d3804a3a7d31773bc7569837b71a4 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Sun, 4 Sep 2022 12:31:15 -0700 Subject: [PATCH 33/38] HID: roccat: Fix use-after-free in roccat_read() roccat_report_event() is responsible for registering roccat-related reports in struct roccat_device. int roccat_report_event(int minor, u8 const *data) { struct roccat_device *device; struct roccat_reader *reader; struct roccat_report *report; uint8_t *new_value; device = devices[minor]; new_value = kmemdup(data, device->report_size, GFP_ATOMIC); if (!new_value) return -ENOMEM; report = &device->cbuf[device->cbuf_end]; /* passing NULL is safe */ kfree(report->value); ... The registered report is stored in the struct roccat_device member "struct roccat_report cbuf[ROCCAT_CBUF_SIZE];". If more reports are received than the "ROCCAT_CBUF_SIZE" value, kfree() the saved report from cbuf[0] and allocates a new reprot. Since there is no lock when this kfree() is performed, kfree() can be performed even while reading the saved report. static ssize_t roccat_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct roccat_reader *reader = file->private_data; struct roccat_device *device = reader->device; struct roccat_report *report; ssize_t retval = 0, len; DECLARE_WAITQUEUE(wait, current); mutex_lock(&device->cbuf_lock); ... report = &device->cbuf[reader->cbuf_start]; /* * If report is larger than requested amount of data, rest of report * is lost! */ len = device->report_size > count ? count : device->report_size; if (copy_to_user(buffer, report->value, len)) { retval = -EFAULT; goto exit_unlock; } ... The roccat_read() function receives the device->cbuf report and delivers it to the user through copy_to_user(). If the N+ROCCAT_CBUF_SIZE th report is received while copying of the Nth report->value is in progress, the pointer that copy_to_user() is working on is kfree()ed and UAF read may occur. (race condition) Since the device node of this driver does not set separate permissions, this is not a security vulnerability, but because it is used for requesting screen display of profile or dpi settings, a user using the roccat device can apply udev to this device node or There is a possibility to use it by giving. Signed-off-by: Hyunwoo Kim Signed-off-by: Jiri Kosina --- drivers/hid/hid-roccat.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c index 26373b82fe812..6da80e442fdd1 100644 --- a/drivers/hid/hid-roccat.c +++ b/drivers/hid/hid-roccat.c @@ -257,6 +257,8 @@ int roccat_report_event(int minor, u8 const *data) if (!new_value) return -ENOMEM; + mutex_lock(&device->cbuf_lock); + report = &device->cbuf[device->cbuf_end]; /* passing NULL is safe */ @@ -276,6 +278,8 @@ int roccat_report_event(int minor, u8 const *data) reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; } + mutex_unlock(&device->cbuf_lock); + wake_up_interruptible(&device->wait); return 0; } From 8b30fb40f8f2c5e56b7af553a398340f92d17aae Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Fri, 15 Apr 2022 18:04:32 +0800 Subject: [PATCH 34/38] HID: nintendo: deregister home LED when it fails Some Pro Controller compatible controllers do not support home LED, and will fail when setting it. Currently this leads to probe failure. Change the code that fails probing to deregistering home LED. Signed-off-by: Icenowy Zheng Reviewed-by: Daniel J. Ogorchock Reviewed-by: Silvan Jegen [bentiss: changed "dflt" to "default"] Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/20220415100432.23453-1-icenowy@aosc.io --- drivers/hid/hid-nintendo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c index 6028af3c3aae5..5cb5a1d53b710 100644 --- a/drivers/hid/hid-nintendo.c +++ b/drivers/hid/hid-nintendo.c @@ -1904,9 +1904,8 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr) /* Set the home LED to 0 as default state */ ret = joycon_home_led_brightness_set(led, 0); if (ret) { - hid_err(hdev, "Failed to set home LED dflt; ret=%d\n", - ret); - return ret; + hid_warn(hdev, "Failed to set home LED default, unregistering home LED"); + devm_led_classdev_unregister(&hdev->dev, led); } } From 50503e360eeb968a3d00234c9cc4057d774c3e9a Mon Sep 17 00:00:00 2001 From: Johnothan King Date: Wed, 21 Sep 2022 10:55:57 +0000 Subject: [PATCH 35/38] HID: nintendo: check analog user calibration for plausibility Arne Wendt writes: Cheap clone controllers may (falsely) report as having a user calibration for the analog sticks in place, but return wrong/impossible values for the actual calibration data. In the present case at mine, the controller reports having a user calibration in place and successfully executes the read commands. The reported user calibration however is min = center = max = 0. This pull request addresses problems of this kind by checking the provided user calibration-data for plausibility (min < center < max) and falling back to the default values if implausible. I'll note that I was experiencing a crash because of this bug when using the GuliKit KingKong 2 controller. The crash manifests as a divide by zero error in the kernel logs: kernel: divide error: 0000 [#1] PREEMPT SMP NOPTI Link: https://github.com/nicman23/dkms-hid-nintendo/pull/25 Link: https://github.com/DanielOgorchock/linux/issues/36 Co-authored-by: Arne Wendt Signed-off-by: Johnothan King Signed-off-by: Benjamin Tissoires Link: https://lore.kernel.org/r/gvpL2G6VwXGJPvxX5KRiu9pVjvTivgayug_jdKDY6zfuAaAqncP9BkKLosjwUXNlgVVTMfJSKfwPF1K79cKAkwGComyC21vCV3q9B3EXNkE=@protonmail.com --- drivers/hid/hid-nintendo.c | 55 +++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c index 5cb5a1d53b710..5bfc0c4504608 100644 --- a/drivers/hid/hid-nintendo.c +++ b/drivers/hid/hid-nintendo.c @@ -760,12 +760,31 @@ static int joycon_read_stick_calibration(struct joycon_ctlr *ctlr, u16 cal_addr, cal_y->max = cal_y->center + y_max_above; cal_y->min = cal_y->center - y_min_below; - return 0; + /* check if calibration values are plausible */ + if (cal_x->min >= cal_x->center || cal_x->center >= cal_x->max || + cal_y->min >= cal_y->center || cal_y->center >= cal_y->max) + ret = -EINVAL; + + return ret; } static const u16 DFLT_STICK_CAL_CEN = 2000; static const u16 DFLT_STICK_CAL_MAX = 3500; static const u16 DFLT_STICK_CAL_MIN = 500; +static void joycon_use_default_calibration(struct hid_device *hdev, + struct joycon_stick_cal *cal_x, + struct joycon_stick_cal *cal_y, + const char *stick, int ret) +{ + hid_warn(hdev, + "Failed to read %s stick cal, using defaults; e=%d\n", + stick, ret); + + cal_x->center = cal_y->center = DFLT_STICK_CAL_CEN; + cal_x->max = cal_y->max = DFLT_STICK_CAL_MAX; + cal_x->min = cal_y->min = DFLT_STICK_CAL_MIN; +} + static int joycon_request_calibration(struct joycon_ctlr *ctlr) { u16 left_stick_addr = JC_CAL_FCT_DATA_LEFT_ADDR; @@ -793,38 +812,24 @@ static int joycon_request_calibration(struct joycon_ctlr *ctlr) &ctlr->left_stick_cal_x, &ctlr->left_stick_cal_y, true); - if (ret) { - hid_warn(ctlr->hdev, - "Failed to read left stick cal, using dflts; e=%d\n", - ret); - - ctlr->left_stick_cal_x.center = DFLT_STICK_CAL_CEN; - ctlr->left_stick_cal_x.max = DFLT_STICK_CAL_MAX; - ctlr->left_stick_cal_x.min = DFLT_STICK_CAL_MIN; - ctlr->left_stick_cal_y.center = DFLT_STICK_CAL_CEN; - ctlr->left_stick_cal_y.max = DFLT_STICK_CAL_MAX; - ctlr->left_stick_cal_y.min = DFLT_STICK_CAL_MIN; - } + if (ret) + joycon_use_default_calibration(ctlr->hdev, + &ctlr->left_stick_cal_x, + &ctlr->left_stick_cal_y, + "left", ret); /* read the right stick calibration data */ ret = joycon_read_stick_calibration(ctlr, right_stick_addr, &ctlr->right_stick_cal_x, &ctlr->right_stick_cal_y, false); - if (ret) { - hid_warn(ctlr->hdev, - "Failed to read right stick cal, using dflts; e=%d\n", - ret); - - ctlr->right_stick_cal_x.center = DFLT_STICK_CAL_CEN; - ctlr->right_stick_cal_x.max = DFLT_STICK_CAL_MAX; - ctlr->right_stick_cal_x.min = DFLT_STICK_CAL_MIN; - ctlr->right_stick_cal_y.center = DFLT_STICK_CAL_CEN; - ctlr->right_stick_cal_y.max = DFLT_STICK_CAL_MAX; - ctlr->right_stick_cal_y.min = DFLT_STICK_CAL_MIN; - } + if (ret) + joycon_use_default_calibration(ctlr->hdev, + &ctlr->right_stick_cal_x, + &ctlr->right_stick_cal_y, + "right", ret); hid_dbg(ctlr->hdev, "calibration:\n" "l_x_c=%d l_x_max=%d l_x_min=%d\n" From beb18bb22cd4fb88648bb2925d56f36131c1ac21 Mon Sep 17 00:00:00 2001 From: Basavaraj Natikar Date: Tue, 27 Sep 2022 15:57:25 +0530 Subject: [PATCH 36/38] HID: amd_sfh: Change dev_err to dev_dbg for additional debug info Users should only be notified at most one time on systems doesn't have any sensors connected or non-supported systems. Check the return code and don't display error messages in those conditions. Signed-off-by: Basavaraj Natikar Signed-off-by: Jiri Kosina --- drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index 70436f9fad2f2..d840efb4a2e28 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -286,13 +286,13 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) phy_base <<= 21; if (!devm_request_mem_region(dev, phy_base, 128 * 1024, "amd_sfh")) { - dev_err(dev, "can't reserve mmio registers\n"); + dev_dbg(dev, "can't reserve mmio registers\n"); return -ENOMEM; } mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024); if (!mp2->vsbase) { - dev_err(dev, "failed to remap vsbase\n"); + dev_dbg(dev, "failed to remap vsbase\n"); return -ENOMEM; } @@ -301,7 +301,7 @@ int amd_sfh1_1_init(struct amd_mp2_dev *mp2) memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info)); if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) { - dev_err(dev, "failed to get sensors\n"); + dev_dbg(dev, "failed to get sensors\n"); return -EOPNOTSUPP; } dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver); From 68266bdcceec10ea364e62c63732cd6fe5a256a8 Mon Sep 17 00:00:00 2001 From: Basavaraj Natikar Date: Tue, 27 Sep 2022 15:57:26 +0530 Subject: [PATCH 37/38] HID: amd_sfh: Handle condition of "no sensors" for SFH1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on num_hid_devices, each sensor device registers to HID. If "no sensors" then amd_sfh work initialization and scheduling doesn’t make sense and return ENODEV to stop driver probe. Hence add a check for num_hid_devices to handle special case in the situation of "no sensors" for SFH1.1. Fixes: 93ce5e0231d7 ("HID: amd_sfh: Implement SFH1.1 functionality") Signed-off-by: Basavaraj Natikar Signed-off-by: Jiri Kosina --- drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index d840efb4a2e28..4da2f9f62aba3 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -110,6 +110,8 @@ static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata) amd_sfh1_1_set_desc_ops(mp2_ops); cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]); + if (cl_data->num_hid_devices == 0) + return -ENODEV; INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work); INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer); From bfdc750c4cb2f3461b9b00a2755e2145ac195c9a Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 28 Sep 2022 13:49:29 -0700 Subject: [PATCH 38/38] HID: wacom: add three styli to wacom_intuos_get_tool_type We forgot to add the 3D pen ID a year ago. There are two new pro pen IDs to be added. Signed-off-by: Ping Cheng Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index e4ae7fafe359c..9fc080e4e66f9 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -713,11 +713,14 @@ static int wacom_intuos_get_tool_type(int tool_id) case 0x802: /* Intuos4/5 13HD/24HD General Pen */ case 0x8e2: /* IntuosHT2 pen */ case 0x022: + case 0x200: /* Pro Pen 3 */ + case 0x04200: /* Pro Pen 3 */ case 0x10842: /* MobileStudio Pro Pro Pen slim */ case 0x14802: /* Intuos4/5 13HD/24HD Classic Pen */ case 0x16802: /* Cintiq 13HD Pro Pen */ case 0x18802: /* DTH2242 Pen */ case 0x10802: /* Intuos4/5 13HD/24HD General Pen */ + case 0x80842: /* Intuos Pro and Cintiq Pro 3D Pen */ tool_type = BTN_TOOL_PEN; break;