From: Siarhei Vishniakou <svv@google.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>,
Jiri Kosina <jikos@kernel.org>,
Benjamin Tissoires <bentiss@kernel.org>,
Ping Cheng <ping.cheng@wacom.com>,
Jason Gerecke <jason.gerecke@wacom.com>
Cc: Jonathan Corbet <corbet@lwn.net>,
Henrik Rydberg <rydberg@bitmath.org>,
linux-input@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org,
Siarhei Vishniakou <svv@google.com>
Subject: [PATCH 2/3] HID: input: map Digitizers Twist usage to ABS_TWIST
Date: Mon, 9 Nov 2026 18:06:31 -0800 [thread overview]
Message-ID: <20261110020632.4003499-3-svv@google.com> (raw)
In-Reply-To: <20261110020632.4003499-1-svv@google.com>
The axis ABS_TWIST is used to report the "twist" (or barrel) rotation
of a stylus.
Map the HID Digitizers Twist usage (0x000d0041) to ABS_TWIST
in hid-input, and calculate its axis resolution in units/radian.
Signed-off-by: Siarhei Vishniakou <svv@google.com>
---
drivers/hid/hid-input-test.c | 87 ++++++++++++++++++++++++++++++++++++
drivers/hid/hid-input.c | 5 +++
2 files changed, 92 insertions(+)
diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c
index 6f5c71660d82..6f1717c0cbe0 100644
--- a/drivers/hid/hid-input-test.c
+++ b/drivers/hid/hid-input-test.c
@@ -62,9 +62,96 @@ static void hid_test_input_get_battery_property(struct kunit *test)
KUNIT_EXPECT_EQ(test, val.intval, POWER_SUPPLY_STATUS_DISCHARGING);
}
+static void hid_test_input_calc_abs_res_twist(struct kunit *test)
+{
+ struct hid_field field = {
+ .logical_minimum = 0,
+ .logical_maximum = 3599,
+ .physical_minimum = 0,
+ .physical_maximum = 3599,
+ .unit = 0x14, /* Degrees */
+ .unit_exponent = -1,
+ };
+
+ /* 0..3599 over 0..359.9 degrees -> ~573 units/radian */
+ KUNIT_EXPECT_EQ(test, hidinput_calc_abs_res(&field, ABS_TWIST), 573);
+
+ /* 0..359 over 0..359 degrees -> ~57 units/radian */
+ field.logical_maximum = 359;
+ field.physical_maximum = 359;
+ field.unit_exponent = 0;
+ KUNIT_EXPECT_EQ(test, hidinput_calc_abs_res(&field, ABS_TWIST), 57);
+
+ /* 0..628 over 0..6.28 radians -> 100 units/radian */
+ field.logical_maximum = 628;
+ field.physical_maximum = 628;
+ field.unit = 0x12; /* Radians */
+ field.unit_exponent = -2;
+ KUNIT_EXPECT_EQ(test, hidinput_calc_abs_res(&field, ABS_TWIST), 100);
+
+ /* Linear unit (centimeters) is invalid for ABS_TWIST */
+ field.unit = 0x11;
+ KUNIT_EXPECT_EQ(test, hidinput_calc_abs_res(&field, ABS_TWIST), 0);
+}
+
+static void hid_test_input_configure_twist_usage(struct kunit *test)
+{
+ struct hid_device *dev;
+ struct hid_driver *drv;
+ struct hid_input *hidinput;
+ struct input_dev *input;
+ struct hid_field *field;
+ struct hid_usage *usage;
+
+ dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+
+ drv = kunit_kzalloc(test, sizeof(*drv), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drv);
+ dev->driver = drv;
+
+ input = kunit_kzalloc(test, sizeof(*input), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input);
+ input->absinfo = kunit_kcalloc(test, ABS_CNT, sizeof(*input->absinfo), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, input->absinfo);
+ input_set_drvdata(input, dev);
+
+ hidinput = kunit_kzalloc(test, sizeof(*hidinput), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hidinput);
+ hidinput->input = input;
+
+ field = kunit_kzalloc(test, sizeof(*field), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, field);
+ field->report_count = 1;
+ field->logical_minimum = 0;
+ field->logical_maximum = 3599;
+ field->physical_minimum = 0;
+ field->physical_maximum = 3599;
+ field->unit = 0x14; /* Degrees */
+ field->unit_exponent = -1;
+ field->usages_priorities = kunit_kzalloc(test, sizeof(int), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, field->usages_priorities);
+
+ usage = kunit_kzalloc(test, sizeof(*usage), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, usage);
+ usage->hid = HID_DG_TWIST;
+
+ hidinput_configure_usage(hidinput, field, usage, 0);
+
+ KUNIT_EXPECT_EQ(test, usage->type, EV_ABS);
+ KUNIT_EXPECT_EQ(test, usage->code, ABS_TWIST);
+ KUNIT_EXPECT_TRUE(test, test_bit(EV_ABS, input->evbit));
+ KUNIT_EXPECT_TRUE(test, test_bit(ABS_TWIST, input->absbit));
+ KUNIT_EXPECT_EQ(test, input_abs_get_min(input, ABS_TWIST), 0);
+ KUNIT_EXPECT_EQ(test, input_abs_get_max(input, ABS_TWIST), 3599);
+ KUNIT_EXPECT_EQ(test, input_abs_get_res(input, ABS_TWIST), 573);
+}
+
static struct kunit_case hid_input_tests[] = {
KUNIT_CASE(hid_test_input_update_battery_charge_status),
KUNIT_CASE(hid_test_input_get_battery_property),
+ KUNIT_CASE(hid_test_input_calc_abs_res_twist),
+ KUNIT_CASE(hid_test_input_configure_twist_usage),
{ }
};
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6a1651f572e2..dc4bd2a579d2 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -291,6 +291,7 @@ __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
case ABS_WHEEL:
case ABS_TILT_X:
case ABS_TILT_Y:
+ case ABS_TWIST:
if (field->unit == 0x14) { /* If degrees */
/* Convert to radians */
prev = logical_extents;
@@ -1018,6 +1019,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
map_abs_clear(ABS_TILT_Y);
break;
+ case 0x41: /* Twist */
+ map_abs_clear(ABS_TWIST);
+ break;
+
case 0x33: /* Touch */
case 0x42: /* TipSwitch */
case 0x43: /* TipSwitch2 */
--
2.56.0.455.g6c5a503b38-goog
next prev parent reply other threads:[~2026-11-10 2:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-10 2:06 [PATCH 0/3] Input: add ABS_TWIST and support it in HID and Wacom Siarhei Vishniakou
2026-11-10 2:06 ` [PATCH 1/3] Input: add ABS_TWIST event code Siarhei Vishniakou
2026-11-10 2:06 ` Siarhei Vishniakou [this message]
2026-11-10 2:06 ` [PATCH 3/3] HID: wacom: report ABS_TWIST alongside ABS_Z for pen twist Siarhei Vishniakou
2026-11-10 2:25 ` [PATCH 0/3] Input: add ABS_TWIST and support it in HID and Wacom Dmitry Torokhov
2026-11-10 18:57 ` Siarhei Vishniakou
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110020632.4003499-3-svv@google.com \
--to=svv@google.com \
--cc=bentiss@kernel.org \
--cc=corbet@lwn.net \
--cc=dmitry.torokhov@gmail.com \
--cc=jason.gerecke@wacom.com \
--cc=jikos@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ping.cheng@wacom.com \
--cc=rydberg@bitmath.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.