* [PATCH v2 2/4] selftests/hid: require hidtools 0.12
From: Peter Hutterer via B4 Relay @ 2025-12-21 23:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Shuah Khan
Cc: Dmitry Torokhov, linux-input, linux-kselftest, linux-kernel,
Vadim Klishko, Peter Hutterer
In-Reply-To: <20251222-wip-hid-pressurepad-v2-0-054ac9689bb7@who-t.net>
From: Peter Hutterer <peter.hutterer@who-t.net>
Not all our tests really require it but since it's likely pip-installed
anyway it's trivial to require the new version, just in case we want to
start cleaning up other bits.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
tools/testing/selftests/hid/tests/conftest.py | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tools/testing/selftests/hid/tests/conftest.py b/tools/testing/selftests/hid/tests/conftest.py
index 1361ec981db6f79a58cf91e8732dcd7c05c47d38..985a535324b2fbe322e754e561d7af6898345b27 100644
--- a/tools/testing/selftests/hid/tests/conftest.py
+++ b/tools/testing/selftests/hid/tests/conftest.py
@@ -5,6 +5,7 @@
# Copyright (c) 2017 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2017 Red Hat, Inc.
+from packaging.version import Version
import platform
import pytest
import re
@@ -14,6 +15,19 @@ from .base import HIDTestUdevRule
from pathlib import Path
+@pytest.fixture(autouse=True)
+def hidtools_version_check():
+ HIDTOOLS_VERSION = "0.12"
+ try:
+ import hidtools
+
+ version = hidtools.__version__ # type: ignore
+ if Version(version) < Version(HIDTOOLS_VERSION):
+ pytest.skip(reason=f"have hidtools {version}, require >={HIDTOOLS_VERSION}")
+ except Exception:
+ pytest.skip(reason=f"hidtools >={HIDTOOLS_VERSION} required")
+
+
# See the comment in HIDTestUdevRule, this doesn't set up but it will clean
# up once the last test exited.
@pytest.fixture(autouse=True, scope="session")
--
2.51.1
^ permalink raw reply related
* [PATCH v2 3/4] selftests/hid: use a enum class for the different button types
From: Peter Hutterer via B4 Relay @ 2025-12-21 23:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Shuah Khan
Cc: Dmitry Torokhov, linux-input, linux-kselftest, linux-kernel,
Vadim Klishko, Peter Hutterer
In-Reply-To: <20251222-wip-hid-pressurepad-v2-0-054ac9689bb7@who-t.net>
From: Peter Hutterer <peter.hutterer@who-t.net>
Instead of multiple spellings of a string-provided argument, let's make
this a tad more type-safe and use an enum here.
And while we do this fix the two wrong devices:
- elan_04f3_313a (HP ZBook Fury 15) is discrete button pad
- dell_044e_1220 (Dell Precision 7740) is a discrete button pad
Equivalent hid-tools commit
https://gitlab.freedesktop.org/libevdev/hid-tools/-/commit/8300a55bf4213c6a252cab8cb5b34c9ddb191625
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
.../testing/selftests/hid/tests/test_multitouch.py | 24 +++++++++++++---------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/tools/testing/selftests/hid/tests/test_multitouch.py b/tools/testing/selftests/hid/tests/test_multitouch.py
index ece0ba8e7d34b75d42245e5936ecf804c46b0846..a06a087f00b6991f7514adf7f8c713bef1a43563 100644
--- a/tools/testing/selftests/hid/tests/test_multitouch.py
+++ b/tools/testing/selftests/hid/tests/test_multitouch.py
@@ -9,6 +9,7 @@
from . import base
from hidtools.hut import HUT
from hidtools.util import BusType
+import enum
import libevdev
import logging
import pytest
@@ -232,11 +233,17 @@ class Digitizer(base.UHIDTestDevice):
return 0
+class HIDButtonType(enum.IntEnum):
+ CLICKPAD = 0
+ PRESSUREPAD = 1
+ DISCRETE_BUTTONS = 2
+
+
class PTP(Digitizer):
def __init__(
self,
name,
- type="Click Pad",
+ buttontype=HIDButtonType.CLICKPAD,
rdesc_str=None,
rdesc=None,
application="Touch Pad",
@@ -244,11 +251,8 @@ class PTP(Digitizer):
max_contacts=None,
input_info=None,
):
- self.type = type.lower().replace(" ", "")
- if self.type == "clickpad":
- self.buttontype = 0
- else: # pressurepad
- self.buttontype = 1
+ self.buttontype = buttontype
+
self.clickpad_state = False
self.left_state = False
self.right_state = False
@@ -983,7 +987,7 @@ class BaseTest:
uhdev = self.uhdev
evdev = uhdev.get_evdev()
- if uhdev.type == "clickpad":
+ if uhdev.buttontype == HIDButtonType.CLICKPAD:
r = uhdev.event(click=True)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
@@ -1918,7 +1922,7 @@ class Testdell_044e_1220(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test dell_044e_1220",
- type="pressurepad",
+ buttontype=HIDButtonType.DISCRETE_BUTTONS,
rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 01 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 09 38 95 01 81 06 05 0c 0a 38 02 81 06 c0 c0 05 0d 09 05 a1 01 85 08 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 af 04 75 10 55 0e 65 11 09 30 35 00 46 e8 03 95 01 81 02 26 7b 02 46 12 02 09 31 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 19 01 29 03 25 01 75 01 95 03 81 02 95 05 81 03 05 0d 85 09 09 55 75 08 95 01 25 05 b1 02 06 00 ff 85 0a 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 01 ff 09 01 a1 01 85 03 09 01 15 00 26 ff 00 95 1b 81 02 85 04 09 02 95 50 81 02 85 05 09 03 95 07 b1 02 85 06 09 04 81 02 c0 06 02 ff 09 01 a1 01 85 07 09 02 95 86 75 08 b1 02 c0 05 0d 09 0e a1 01 85 0b 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 0c 09 57 09 58 75 01 95
02 25 01 b1 02 95 06 b1 03 c0 c0",
)
@@ -2018,7 +2022,7 @@ class Testelan_04f3_313a(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test elan_04f3_313a",
- type="touchpad",
+ buttontype=HIDButtonType.DISCRETE_BUTTONS,
input_info=(BusType.I2C, 0x04F3, 0x313A),
rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 75 08 95 02 81 06 75 08 95 05 81 03 c0 06 00 ff 09 01 85 0e 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0a 09 c6 15 00 26 ff 00 75 08 95 04 b1 02 c0 06 00 ff 09 01 a1 01 85 5c 09 01 95 0b 75 08 81 06 85 0d 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 80 03 75 08 b1 02 85 0b 09 c7 95 82 75 08 b1 02 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 05 09 09 02 09 03 15 00 25 01 75 01 95 02 81 02 05 0d 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 d7 0e 75 10 55 0d 65 11 09 30 35 00 46 44 2f 95 01 81 02 46 12 16 26 eb 06 26 eb 06 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 25 01 75 01 95 08 81 03 09 c5 75 08 95 02 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f
b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 10 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 0e b1 03 c0 c0 05 01 09 02 a1 01 85 2a 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 35 81 45 7f 55 00 65 13 75 08 95 02 81 06 75 08 95 05 81 03 c0 c0",
)
@@ -2110,7 +2114,7 @@ class Testsipodev_0603_0002(BaseTest.TestPTP):
def create_device(self):
return PTP(
"uhid test sipodev_0603_0002",
- type="clickpad",
+ buttontype=HIDButtonType.CLICKPAD,
rdesc="05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29 02 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 80 25 7f 75 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 05 09 51 81 02 05 01 15 00 26 44 0a 75 0c 55 0e 65 11 09 30 35 00 46 ac 03 95 01 81 02 46 fe 01 26 34 05 75 0c 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 0a 95 01 75 04 81 02 75 01 95 03 81 03 05 09 09 01 25 01 75 01 95 01 81 02 05 0d 85 0a 09 55 09 59 75 04 95 02 25 0f b1 02 85 0b 09 60 75 01 95 01 15 00 25 01 b1 02 95 07 b1 03 85 09 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d 09 0e a1 01 85 06 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 07 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 05 01 09 0c a1 01 85 08 15 00 25 01 09 c6 75 01 95 01 81 06 75 07 81 03 c0 05 01 09 80 a1 01 85 01 15 00 25 01 75 01 0a 81 00 0a
82 00 0a 83 00 95 03 81 06 95 05 81 01 c0 06 0c 00 09 01 a1 01 85 02 25 01 15 00 75 01 0a b5 00 0a b6 00 0a b7 00 0a cd 00 0a e2 00 0a a2 00 0a e9 00 0a ea 00 95 08 81 02 0a 83 01 0a 6f 00 0a 70 00 0a 88 01 0a 8a 01 0a 92 01 0a a8 02 0a 24 02 95 08 81 02 0a 21 02 0a 23 02 0a 96 01 0a 25 02 0a 26 02 0a 27 02 0a 23 02 0a b1 02 95 08 81 02 c0 06 00 ff 09 01 a1 01 85 05 15 00 26 ff 00 19 01 29 02 75 08 95 05 b1 02 c0",
)
--
2.51.1
^ permalink raw reply related
* [PATCH v2 4/4] selftests/hid: add a test for the Digitizer/Button Type pressurepad
From: Peter Hutterer via B4 Relay @ 2025-12-21 23:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Shuah Khan
Cc: Dmitry Torokhov, linux-input, linux-kselftest, linux-kernel,
Vadim Klishko, Peter Hutterer
In-Reply-To: <20251222-wip-hid-pressurepad-v2-0-054ac9689bb7@who-t.net>
From: Peter Hutterer <peter.hutterer@who-t.net>
We have to resort to a bit of a hack: python-libevdev gets the
properties from libevdev at module init time. If libevdev hasn't been
rebuilt with the new property it won't be automatically populated. So we
hack around this by constructing the property manually.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
.../testing/selftests/hid/tests/test_multitouch.py | 39 +++++++++++++++++++---
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/hid/tests/test_multitouch.py b/tools/testing/selftests/hid/tests/test_multitouch.py
index a06a087f00b6991f7514adf7f8c713bef1a43563..fa4fb2054bd4febb1d2497f2787944f538b27889 100644
--- a/tools/testing/selftests/hid/tests/test_multitouch.py
+++ b/tools/testing/selftests/hid/tests/test_multitouch.py
@@ -979,15 +979,36 @@ class BaseTest:
assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_ORIENTATION, 90) in events
class TestPTP(TestWin8Multitouch):
+ def test_buttontype(self):
+ """Check for the right ButtonType."""
+ uhdev = self.uhdev
+ assert uhdev is not None
+ evdev = uhdev.get_evdev()
+
+ # If libevdev.so is not yet compiled with INPUT_PROP_PRESSUREPAD
+ # python-libevdev won't have it either, let's fake it
+ if not getattr(libevdev, "INPUT_PROP_PRESSUREPAD", None):
+ prop = libevdev.InputProperty(name="INPUT_PROP_PRESSUREPAD", value=0x7)
+ libevdev.INPUT_PROP_PRESSUREPAD = prop
+ libevdev.props.append(prop)
+
+ if uhdev.buttontype == HIDButtonType.CLICKPAD:
+ assert libevdev.INPUT_PROP_BUTTONPAD in evdev.properties
+ elif uhdev.buttontype == HIDButtonType.PRESSUREPAD:
+ assert libevdev.INPUT_PROP_PRESSUREPAD in evdev.properties
+ else:
+ assert libevdev.INPUT_PROP_PRESSUREPAD not in evdev.properties
+ assert libevdev.INPUT_PROP_BUTTONPAD not in evdev.properties
+
def test_ptp_buttons(self):
"""check for button reliability.
- There are 2 types of touchpads: the click pads and the pressure pads.
- Each should reliably report the BTN_LEFT events.
+ There are 3 types of touchpads: click pads + pressure pads and
+ those with discrete buttons. Each should reliably report the BTN_LEFT events.
"""
uhdev = self.uhdev
evdev = uhdev.get_evdev()
- if uhdev.buttontype == HIDButtonType.CLICKPAD:
+ if uhdev.buttontype in [HIDButtonType.CLICKPAD, HIDButtonType.PRESSUREPAD]:
r = uhdev.event(click=True)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
@@ -999,7 +1020,7 @@ class BaseTest:
self.debug_reports(r, uhdev, events)
assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) in events
assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
- else:
+ elif uhdev.buttontype == HIDButtonType.DISCRETE_BUTTONS:
r = uhdev.event(left=True)
events = uhdev.next_sync_events()
self.debug_reports(r, uhdev, events)
@@ -2062,6 +2083,16 @@ class Testite_06cb_2968(BaseTest.TestPTP):
)
+class Testven_0488_108c(BaseTest.TestPTP):
+ def create_device(self):
+ return PTP(
+ "uhid test ven_0488_108c",
+ rdesc="05 01 09 02 a1 01 85 06 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 05 0d 09 05 a1 01 85 01 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00
75 10 95 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 05 0d 85 02 09 55 75 08 95 01 25 05 b1 02 09 59 b1 02 06 00 ff 85 03 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 05 0e 09 01 a1 02 85 13 09 23 15 00 25 64 75 08 95 01 b1 02 c0 c0 05 0d 09 0e a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 01 ff 09 02 a1 01 09 00 85 07 15 00 26 ff 00 75 08 96 12 02 b1 02 c0 06 00 ff 09 01 a1 01 85 0d 15 00 26 ff 00 75 08 95 11 09 01 81 02 09 01 91 02 c0 05 0e 09 01 a1 01 85 11 09 35 15 00 26 ff 00 75 08 95 17 b1 02 c0 06 81 ff 09 01 a1 01 09 20 85 17 15 00 26 ff 00 75 08 95 3f 09 01 81 02 09 01 91 02 c0",
+ input_info=(0x18, 0x0488, 0x108C),
+ buttontype=HIDButtonType.PRESSUREPAD,
+ )
+
+
class Testn_trig_1b96_0c01(BaseTest.TestWin8Multitouch):
def create_device(self):
return Digitizer(
--
2.51.1
^ permalink raw reply related
* [PATCH v2 1/4] HID: multitouch: set INPUT_PROP_PRESSUREPAD based on Digitizer/Button Type
From: Peter Hutterer via B4 Relay @ 2025-12-21 23:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Shuah Khan
Cc: Dmitry Torokhov, linux-input, linux-kselftest, linux-kernel,
Vadim Klishko, Peter Hutterer
In-Reply-To: <20251222-wip-hid-pressurepad-v2-0-054ac9689bb7@who-t.net>
From: Peter Hutterer <peter.hutterer@who-t.net>
A Digitizer/Button Type value of 1 indicates the device is a
pressurepad, see
https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchpad-windows-precision-touchpad-collection#device-capabilities-feature-report
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
drivers/hid/hid-multitouch.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 179dc316b4b518d78bdc900d9fd15756c5eba83e..382e6f50c4f7e663af7d028abb8be7cb2e6e7b8e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -81,6 +81,7 @@ MODULE_LICENSE("GPL");
#define MT_INPUTMODE_TOUCHPAD 0x03
#define MT_BUTTONTYPE_CLICKPAD 0
+#define MT_BUTTONTYPE_PRESSUREPAD 1
enum latency_mode {
HID_LATENCY_NORMAL = 0,
@@ -179,6 +180,7 @@ struct mt_device {
__u8 inputmode_value; /* InputMode HID feature value */
__u8 maxcontacts;
bool is_buttonpad; /* is this device a button pad? */
+ bool is_pressurepad; /* is this device a pressurepad? */
bool is_haptic_touchpad; /* is this device a haptic touchpad? */
bool serial_maybe; /* need to check for serial protocol */
@@ -530,8 +532,14 @@ static void mt_feature_mapping(struct hid_device *hdev,
}
mt_get_feature(hdev, field->report);
- if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
+ switch (field->value[usage->usage_index]) {
+ case MT_BUTTONTYPE_CLICKPAD:
td->is_buttonpad = true;
+ break;
+ case MT_BUTTONTYPE_PRESSUREPAD:
+ td->is_pressurepad = true;
+ break;
+ }
break;
case 0xff0000c5:
@@ -1393,6 +1401,8 @@ static int mt_touch_input_configured(struct hid_device *hdev,
if (td->is_buttonpad)
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
+ if (td->is_pressurepad)
+ __set_bit(INPUT_PROP_PRESSUREPAD, input->propbit);
app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
BITS_TO_LONGS(td->maxcontacts),
--
2.51.1
^ permalink raw reply related
* [PATCH v2 0/4] HID: multitouch: set INPUT_PROP_PRESSUREPAD on compatible touchpads
From: Peter Hutterer via B4 Relay @ 2025-12-21 23:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, Shuah Khan
Cc: Dmitry Torokhov, linux-input, linux-kselftest, linux-kernel,
Vadim Klishko, Peter Hutterer
Nicely enough MS defines a button type for a pressurepad touchpad [2]
and it looks like most touchpad vendors fill this in.
The selftests require a bit of prep work (and a hack for the test
itself) - hidtools 0.12 requires python-libevdev 0.13 which in turn
provides constructors for unknown properties.
[2] https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchpad-windows-precision-touchpad-collection#device-capabilities-feature-report
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
Changes in v2:
- rebased on top of 6.18
- hid-multitouch changes split out into a separate patch
- Patches reordered for slightly nicer history, tests changes are
grouped together
- Link to v1: https://lore.kernel.org/r/20251121-wip-hid-pressurepad-v1-0-e32e5565a527@who-t.net
---
Peter Hutterer (4):
HID: multitouch: set INPUT_PROP_PRESSUREPAD based on Digitizer/Button Type
selftests/hid: require hidtools 0.12
selftests/hid: use a enum class for the different button types
selftests/hid: add a test for the Digitizer/Button Type pressurepad
drivers/hid/hid-multitouch.c | 12 ++++-
tools/testing/selftests/hid/tests/conftest.py | 14 +++++
.../testing/selftests/hid/tests/test_multitouch.py | 61 +++++++++++++++++-----
3 files changed, 73 insertions(+), 14 deletions(-)
---
base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
change-id: 20251111-wip-hid-pressurepad-8a800cdf1813
Best regards,
--
Peter Hutterer <peter.hutterer@who-t.net>
^ permalink raw reply
* Re: [git pull] Input updates for v6.19-rc1
From: Dmitry Torokhov @ 2025-12-21 23:14 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
In-Reply-To: <CAHk-=wghOVD4usUy9Jowte5OXN_mnVJgHHMYyTS0O3KvR_J12g@mail.gmail.com>
On Sun, Dec 21, 2025 at 03:05:33PM -0800, Linus Torvalds wrote:
> On Sun, 21 Dec 2025 at 00:40, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
> >
> > Please pull from:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.19-rc1
>
> return -ENOSUCHTAG;
>
> Did you forget to push?
Oops, my bad. Should be there now.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [git pull] Input updates for v6.19-rc1
From: Linus Torvalds @ 2025-12-21 23:05 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-kernel, linux-input
In-Reply-To: <lxy277le4ku73e5xf4yawoviapa5ii3msto7wjgzl3o5fmwnrr@3bcntrq7tk4i>
On Sun, 21 Dec 2025 at 00:40, Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote:
>
> Please pull from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.19-rc1
return -ENOSUCHTAG;
Did you forget to push?
Linus
^ permalink raw reply
* [PATCH v3] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
From: pip-izony @ 2025-12-21 21:14 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Seungjin Bae, Kyungtae Kim, Sanghoon Choi, Dan Carpenter,
linux-input, linux-kernel
In-Reply-To: <20251220002447.392843-4-eeodqql09@gmail.com>
From: Seungjin Bae <eeodqql09@gmail.com>
The `ims_pcu_process_data()` processes incoming URB data byte by byte.
However, it fails to check if the `read_pos` index exceeds
IMS_PCU_BUF_SIZE.
If a malicious USB device sends a packet larger than IMS_PCU_BUF_SIZE,
`read_pos` will increment indefinitely. Moreover, since `read_pos` is
located immediately after `read_buf`, the attacker can overwrite
`read_pos` itself to arbitrarily control the index.
This manipulated `read_pos` is subsequently used in
`ims_pcu_handle_response()` to copy data into `cmd_buf`, leading to a
heap buffer overflow.
Specifically, an attacker can overwrite the `cmd_done.wait.head` located
at offset 136 relative to `cmd_buf` in the `ims_pcu_handle_response()`.
Consequently, when the driver calls `complete(&pcu->cmd_done)`, it
triggers a control flow hijack by using the manipulated pointer.
Fix this by adding a bounds check for `read_pos` before writing to
`read_buf`. If the packet is too long, discard it, log a warning,
and reset the parser state.
Fixes: 628329d524743 ("Input: add IMS Passenger Control Unit driver")
Co-developed-by: Sanghoon Choi <csh0052@gmail.com>
Signed-off-by: Sanghoon Choi <csh0052@gmail.com>
Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
---
v1 -> v2: Add warning and reset the state of the parser for bad packet
v2 -> v3: Add co-author information
drivers/input/misc/ims-pcu.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4581f1c53644..c98ef71c841e 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -450,6 +450,16 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
continue;
if (pcu->have_dle) {
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ pcu->have_stx = false;
+ pcu->have_dle = false;
+ pcu->read_pos = 0;
+ continue;
+ }
+
pcu->have_dle = false;
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
@@ -491,6 +501,16 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
break;
default:
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ pcu->have_stx = false;
+ pcu->have_dle = false;
+ pcu->read_pos = 0;
+ continue;
+ }
+
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
break;
--
2.43.0
^ permalink raw reply related
* [dtor-input:next 18/20] drivers/input/misc/twl4030-pwrbutton.c:46:44: warning: 'twl6030_chipdata' defined but not used
From: kernel test robot @ 2025-12-21 18:13 UTC (permalink / raw)
To: Andreas Kemnade; +Cc: oe-kbuild-all, linux-input, Dmitry Torokhov
tree: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
head: eeb2ea4b59df5fdcb697904fe6f49d5851543808
commit: ec8fce2a57e96e07d82d4e884430c2cb6c048998 [18/20] Input: twl4030 - add TWL603x power button
config: m68k-randconfig-r073-20251221 (https://download.01.org/0day-ci/archive/20251222/202512220251.jDE8tKup-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 12.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251222/202512220251.jDE8tKup-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512220251.jDE8tKup-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/input/misc/twl4030-pwrbutton.c:46:44: warning: 'twl6030_chipdata' defined but not used [-Wunused-const-variable=]
46 | static const struct twl_pwrbutton_chipdata twl6030_chipdata = {
| ^~~~~~~~~~~~~~~~
>> drivers/input/misc/twl4030-pwrbutton.c:41:44: warning: 'twl4030_chipdata' defined but not used [-Wunused-const-variable=]
41 | static const struct twl_pwrbutton_chipdata twl4030_chipdata = {
| ^~~~~~~~~~~~~~~~
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for I2C_K1
Depends on [n]: I2C [=y] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && OF [=n]
Selected by [y]:
- MFD_SPACEMIT_P1 [=y] && HAS_IOMEM [=y] && (ARCH_SPACEMIT || COMPILE_TEST [=y]) && I2C [=y]
vim +/twl6030_chipdata +46 drivers/input/misc/twl4030-pwrbutton.c
40
> 41 static const struct twl_pwrbutton_chipdata twl4030_chipdata = {
42 .status_reg = 0xf,
43 .need_manual_irq = false,
44 };
45
> 46 static const struct twl_pwrbutton_chipdata twl6030_chipdata = {
47 .status_reg = 0x2,
48 .need_manual_irq = true,
49 };
50
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH] HID: asus: add new Asus EC hid device for keyboard backlight and FN HotKeys
From: Alexandru Marc Serdeliuc via B4 Relay @ 2025-12-21 11:12 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-kernel, linux-input, Alexandru Marc Serdeliuc
From: Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
Add support for Asus Embedded Controlled accessed via HID
Currently working features:
- Keyboard Backlight
- FN HotKeys
Signed-off-by: Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
---
Add support for Asus Embedded Controlled accessed via HID
Currently working features:
- Keyboard Backlight
- FN HotKeys
---
drivers/hid/Kconfig | 10 ++
drivers/hid/Makefile | 1 +
drivers/hid/hid-asus-ec.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 397 insertions(+)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 920a64b66b25b39e8259105c7c9b975fb77b2725..f0fbc951735eeea39198137294a9429f5b9d34b8 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -202,6 +202,16 @@ config HID_ASUS
- GL553V series
- GL753V series
+config HID_ASUS_EC
+ tristate "ASUS EC HID support (Zenbook A14 UX3407QA)"
+ depends on HID && I2C_HID
+ help
+ Say Y here if you have an ASUS Zenbook A14 (UX3407QA) and want
+ support for its EC-controlled keyboard backlight and Fn hotkeys
+
+ This driver is currently only tested on the ASUS Zenbook A14
+ UX3407QA; behaviour on other models is unknown.
+
config HID_AUREAL
tristate "Aureal"
help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 361a7daedeb85454114def8afb5f58caeab58a00..bacccf00482c1b787ce59660e4366f8224aeefee 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
obj-$(CONFIG_HID_APPLETB_KBD) += hid-appletb-kbd.o
obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
obj-$(CONFIG_HID_ASUS) += hid-asus.o
+obj-$(CONFIG_HID_ASUS_EC) += hid-asus-ec.o
obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
diff --git a/drivers/hid/hid-asus-ec.c b/drivers/hid/hid-asus-ec.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cf61fb2468d079827bfdb1db49daca905e53874
--- /dev/null
+++ b/drivers/hid/hid-asus-ec.c
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * ASUS EC HID driver for Zenbook A14 (UX3407QA)
+ *
+ * EC I2C HID driver for keyboard backlight and Fn hotkeys.
+ *
+ * Copyright (c) 2025 Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/hid.h>
+#include <linux/input.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+
+#define ASUS_VENDOR_ID 0x0B05
+#define ASUS_PRODUCT_ID 0x0220
+
+#define A14_EC_REPORT_ID 0x5A
+#define A14_EC_REPORT_SIZE 64
+#define A14_EC_MAX_BACKLIGHT 3
+
+#define A14_EC_EVT_KEY_FN_ESC 0x4E
+#define A14_EC_EVT_KEY_FN_F4 0xC7
+#define A14_EC_EVT_KEY_FN_F5 0x10
+#define A14_EC_EVT_KEY_FN_F6 0x20
+#define A14_EC_EVT_KEY_FN_F8 0x7E
+#define A14_EC_EVT_KEY_FN_F9 0x7C
+#define A14_EC_EVT_KEY_FN_F10 0x85
+#define A14_EC_EVT_KEY_FN_F11 0x6B
+#define A14_EC_EVT_KEY_FN_F12 0x86
+#define A14_EC_EVT_KEY_FN_F 0x9d
+
+
+struct asus_hid_data {
+ struct hid_device *hdev;
+ struct led_classdev kbd_led_cdev;
+ struct input_dev *hotkey_input_dev;
+ enum led_brightness saved_brightness;
+};
+
+static struct asus_hid_data *asus_data;
+
+static int asus_send_ec_command(struct hid_device *hdev, u8 *cmd_buf)
+{
+ int ret;
+ u8 report_id = cmd_buf[0];
+
+ ret = hid_hw_raw_request(hdev, report_id, cmd_buf, A14_EC_REPORT_SIZE,
+ HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+
+ if (ret < 0)
+ dev_err(&hdev->dev, "hid_hw_raw_request failed with status: %d\n", ret);
+
+ return ret;
+}
+
+static int asus_kbd_led_init(struct hid_device *hdev)
+{
+ u8 ec_init_cmd[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xD0, 0x8F, 0x01 };
+ int ret;
+
+ ret = asus_send_ec_command(hdev, ec_init_cmd);
+
+ if (ret < 0)
+ return ret;
+
+ u8 brightness_cmd[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xBA, 0xC5,
+ 0xC4, A14_EC_MAX_BACKLIGHT };
+
+ ret = asus_send_ec_command(hdev, brightness_cmd);
+ if (ret < 0)
+ dev_warn(&hdev->dev, "Brightness init failed: %d\n", ret);
+
+ return ret;
+}
+
+static void asus_kbd_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct asus_hid_data *data = container_of(led_cdev, struct asus_hid_data, kbd_led_cdev);
+
+ u8 level = (u8)brightness;
+
+ if (level > A14_EC_MAX_BACKLIGHT)
+ level = A14_EC_MAX_BACKLIGHT;
+
+ u8 buf[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xBA, 0xC5, 0xC4, level };
+
+ asus_send_ec_command(data->hdev, buf);
+ msleep(20);
+ data->saved_brightness = (enum led_brightness)level;
+}
+
+static int asus_raw_event(struct hid_device *hdev, struct hid_report *report,
+ u8 *raw_data, int size)
+{
+ struct asus_hid_data *data = hid_get_drvdata(hdev);
+ struct input_dev *input_dev = data->hotkey_input_dev;
+
+ if (report->id == A14_EC_REPORT_ID && size >= 2) {
+ u8 usage_code = raw_data[1];
+
+ switch (usage_code) {
+ case A14_EC_EVT_KEY_FN_ESC:
+ input_event(input_dev, EV_KEY, KEY_FN_ESC, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_FN_ESC, 0);
+ input_sync(input_dev);
+ return 1;
+
+ /* FN + F1, F2 and F3 are not managed by EC*/
+
+ case A14_EC_EVT_KEY_FN_F4:
+ if (size >= 3) {
+ u8 current_level = data->saved_brightness;
+ u8 max_level = A14_EC_MAX_BACKLIGHT;
+ u8 next_level = (current_level + 1) % (max_level + 1);
+
+ asus_kbd_set_brightness(&data->kbd_led_cdev,
+ (enum led_brightness)next_level);
+ if (next_level > current_level ||
+ (current_level == max_level && next_level == 0)) {
+ if (next_level == 0) {
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ } else {
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMUP, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMUP, 0);
+ input_sync(input_dev);
+ }
+ } else if (next_level < current_level) {
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY,
+ KEY_KBDILLUMDOWN, 0);
+ input_sync(input_dev);
+ }
+ }
+ return 1;
+ case A14_EC_EVT_KEY_FN_F5:
+ input_event(input_dev, EV_KEY, KEY_BRIGHTNESSDOWN, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_BRIGHTNESSDOWN, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F6:
+ input_event(input_dev, EV_KEY, KEY_BRIGHTNESSUP, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_BRIGHTNESSUP, 0);
+ input_sync(input_dev);
+ return 1;
+
+ /* FN + F7 is not managed by the EC*/
+
+ case A14_EC_EVT_KEY_FN_F8:
+ input_event(input_dev, EV_KEY, KEY_EMOJI_PICKER, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_EMOJI_PICKER, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F9:
+ input_event(input_dev, EV_KEY, KEY_MICMUTE, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_MICMUTE, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F10:
+ input_event(input_dev, EV_KEY, KEY_CAMERA_ACCESS_TOGGLE, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_CAMERA_ACCESS_TOGGLE, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F11:
+ input_event(input_dev, EV_KEY, KEY_TOUCHPAD_TOGGLE, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_TOUCHPAD_TOGGLE, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F12:
+ input_event(input_dev, EV_KEY, KEY_PROG1, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_PROG1, 0);
+ input_sync(input_dev);
+ return 1;
+ case A14_EC_EVT_KEY_FN_F:
+ input_event(input_dev, EV_KEY, KEY_PERFORMANCE, 1);
+ input_sync(input_dev);
+ input_event(input_dev, EV_KEY, KEY_PERFORMANCE, 0);
+ input_sync(input_dev);
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int asus_hid_suspend(struct hid_device *hdev, pm_message_t message)
+{
+ struct asus_hid_data *data = hid_get_drvdata(hdev);
+
+ if (message.event == PM_EVENT_SUSPEND || message.event == PM_EVENT_HIBERNATE) {
+ asus_kbd_set_brightness(&data->kbd_led_cdev, LED_OFF);
+ return 0;
+ }
+
+ dev_dbg(&hdev->dev, "Runtime suspend: turning off keyboard backlight\n");
+ asus_kbd_set_brightness(&data->kbd_led_cdev, LED_OFF);
+ return 0;
+}
+
+
+static int asus_hid_resume(struct hid_device *hdev)
+{
+ struct asus_hid_data *data = hid_get_drvdata(hdev);
+ int ret;
+ int retry_count;
+
+ msleep(40);
+
+ dev_dbg(&hdev->dev, "Re-initialising EC backlight communication\n");
+ retry_count = 0;
+ do {
+ ret = asus_kbd_led_init(hdev);
+ if (ret >= 0) {
+ dev_dbg(&hdev->dev,
+ "EC init successful on attempt %d\n",
+ retry_count + 1);
+ break;
+ }
+ retry_count++;
+ dev_warn(&hdev->dev,
+ "EC init attempt %d failed: %d, retrying...\n",
+ retry_count, ret);
+ msleep(300 * retry_count);
+ } while (retry_count < 5);
+
+ if (ret < 0) {
+ dev_err(&hdev->dev,
+ "EC init on resume failed after %d attempts: %d\n",
+ retry_count, ret);
+ dev_err(&hdev->dev,
+ "Keyboard backlight may not work; try reloading the driver\n");
+ } else {
+ dev_dbg(&hdev->dev, "EC backlight communication restored\n");
+ }
+
+ asus_kbd_set_brightness(&data->kbd_led_cdev, data->saved_brightness);
+
+ dev_info(&hdev->dev, "Resume complete\n");
+ return 0;
+}
+
+static const struct hid_device_id asus_hid_devices[] = {
+ /* Tested on ASUS Zenbook A14 (UX3407QA) only. */
+ { HID_DEVICE(0x18, 0x00, ASUS_VENDOR_ID, ASUS_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(hid, asus_hid_devices);
+
+static int asus_hid_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+ int ret;
+ struct asus_hid_data *data;
+
+ data = devm_kzalloc(&hdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ data->hdev = hdev;
+ hid_set_drvdata(hdev, data);
+ asus_data = data;
+ data->saved_brightness = A14_EC_MAX_BACKLIGHT;
+ ret = hid_parse(hdev);
+ if (ret)
+ return ret;
+ ret = hid_hw_start(hdev, HID_INPUT_REPORT | HID_OUTPUT_REPORT | HID_FEATURE_REPORT);
+ if (ret)
+ return ret;
+ data->hotkey_input_dev = input_allocate_device();
+ if (!data->hotkey_input_dev) {
+ dev_err(&hdev->dev, "Failed to allocate hotkey input device\n");
+ hid_hw_stop(hdev); return -ENOMEM;
+ }
+ data->hotkey_input_dev->name = "ASUS EC I2C HID hotkeys";
+ data->hotkey_input_dev->phys = "i2c-hid/input1/hotkeys";
+ data->hotkey_input_dev->id.bustype = hdev->bus;
+ data->hotkey_input_dev->id.vendor = hdev->vendor;
+ data->hotkey_input_dev->id.product = hdev->product;
+ data->hotkey_input_dev->dev.parent = &hdev->dev;
+ set_bit(EV_KEY, data->hotkey_input_dev->evbit);
+ set_bit(KEY_FN_ESC, data->hotkey_input_dev->keybit);
+ set_bit(KEY_KBDILLUMUP, data->hotkey_input_dev->keybit);
+ set_bit(KEY_KBDILLUMDOWN, data->hotkey_input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSDOWN, data->hotkey_input_dev->keybit);
+ set_bit(KEY_BRIGHTNESSUP, data->hotkey_input_dev->keybit);
+ set_bit(KEY_SWITCHVIDEOMODE, data->hotkey_input_dev->keybit);
+ set_bit(KEY_EMOJI_PICKER, data->hotkey_input_dev->keybit);
+ set_bit(KEY_MICMUTE, data->hotkey_input_dev->keybit);
+ set_bit(KEY_CAMERA_ACCESS_TOGGLE, data->hotkey_input_dev->keybit);
+ set_bit(KEY_TOUCHPAD_TOGGLE, data->hotkey_input_dev->keybit);
+ set_bit(KEY_PROG1, data->hotkey_input_dev->keybit);
+ set_bit(KEY_PERFORMANCE, data->hotkey_input_dev->keybit);
+
+ ret = input_register_device(data->hotkey_input_dev);
+ if (ret) {
+ dev_err(&hdev->dev, "Failed to register hotkey input device\n");
+ input_free_device(data->hotkey_input_dev); hid_hw_stop(hdev);
+ return ret;
+ }
+ asus_kbd_led_init(hdev);
+ data->kbd_led_cdev.name = "asus::kbd_backlight";
+ data->kbd_led_cdev.brightness_set = asus_kbd_set_brightness;
+ data->kbd_led_cdev.max_brightness = A14_EC_MAX_BACKLIGHT;
+ ret = led_classdev_register(&hdev->dev, &data->kbd_led_cdev);
+ if (ret) {
+ input_unregister_device(data->hotkey_input_dev);
+ hid_hw_stop(hdev);
+ return ret;
+ }
+ dev_info(&hdev->dev,
+ "ASUS EC HID driver for Zenbook A14 loaded for 0x%04x:0x%04x\n",
+ ASUS_VENDOR_ID, ASUS_PRODUCT_ID);
+ return 0;
+}
+static void asus_hid_remove(struct hid_device *hdev)
+{
+ struct asus_hid_data *data = hid_get_drvdata(hdev);
+
+ led_classdev_unregister(&data->kbd_led_cdev);
+ input_unregister_device(data->hotkey_input_dev);
+ hid_hw_stop(hdev);
+ asus_data = NULL;
+}
+static struct hid_driver hid_asus_ec_driver = {
+ .name = "hid-asus-ec",
+ .id_table = asus_hid_devices,
+ .probe = asus_hid_probe,
+ .remove = asus_hid_remove,
+ .raw_event = asus_raw_event,
+ .suspend = asus_hid_suspend,
+ .resume = asus_hid_resume,
+};
+module_hid_driver(hid_asus_ec_driver);
+MODULE_AUTHOR("Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>");
+MODULE_DESCRIPTION("ASUS EC HID driver for Zenbook A14 (UX3407QA)");
+MODULE_LICENSE("GPL");
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251221-add-support-for-the-asus-hid-ec-a60b9a2d74b3
Best regards,
--
Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
^ permalink raw reply related
* [git pull] Input updates for v6.19-rc1
From: Dmitry Torokhov @ 2025-12-21 8:40 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
Hi Linus,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.19-rc1
to receive updates for the input subsystem. You will get:
- a quirk for i8042 to better handle another TUXEDO model
- a quirk to atkbd to handle incorcet behavior of HONOR FMB-P internal
keyboard
- a definition for a new ABS_SND_PROFILE event
- fixes to alps and lkkbd drivers to reliably shut down pending work on
removal
- a fix to apple_z2 driver tightening input report parsing
- a fix for "off-by-one" error when validating config in ti_am335x_tsc
driver
- addition of CRKD Guitars device IDs to xpad driver.
Changelog:
---------
Christoffer Sandberg (1):
Input: i8042 - add TUXEDO InfinityBook Max Gen10 AMD to i8042 quirk table
Cryolitia PukNgae (1):
Input: atkbd - skip deactivate for HONOR FMB-P's internal keyboard
Duoming Zhou (1):
Input: alps - fix use-after-free bugs caused by dev3_register_work
Gergo Koteles (1):
Input: add ABS_SND_PROFILE
Junjie Cao (1):
Input: ti_am335x_tsc - fix off-by-one error in wire_order validation
Minseong Kim (1):
Input: lkkbd - disable pending work before freeing device
Sanjay Govind (1):
Input: xpad - add support for CRKD Guitars
Sasha Finkelstein (1):
Input: apple_z2 - fix reading incorrect reports after exiting sleep
Diffstat:
--------
Documentation/input/event-codes.rst | 6 ++++++
drivers/hid/hid-debug.c | 1 +
drivers/input/joystick/xpad.c | 5 +++++
drivers/input/keyboard/atkbd.c | 7 +++++++
drivers/input/keyboard/lkkbd.c | 5 ++++-
drivers/input/mouse/alps.c | 1 +
drivers/input/serio/i8042-acpipnpio.h | 7 +++++++
drivers/input/touchscreen/apple_z2.c | 4 ++++
drivers/input/touchscreen/ti_am335x_tsc.c | 2 +-
include/uapi/linux/input-event-codes.h | 9 +++++++++
10 files changed, 45 insertions(+), 2 deletions(-)
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH] media: rc: rc_unregister_device() should not call rc_free_device()
From: Sean Young @ 2025-12-20 22:27 UTC (permalink / raw)
To: Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter,
Bruno Prémont, Jiri Kosina, Benjamin Tissoires, Hans Verkuil,
Mauro Carvalho Chehab, Sean Young, Maxim Levitsky,
Patrice Chotard, Chen-Yu Tsai, Samuel Holland,
David Härdeman, Benjamin Valentin, Greg Kroah-Hartman
Cc: Haotian Zhang, dri-devel, linux-kernel, linux-input, linux-media,
linux-arm-kernel, linux-sunxi, linux-staging
rc_unregister_device() does two things: it marks the device as
unregistered, so no new commands can be issued via the lirc chardev,
and also frees the rc device. Device drivers want to both cancel
in-flight commands (i.e. kill urbs) and prevent further commands from
being issued. Only once both are done, can we really free the rc device,
because it might be referenced in urb callbacks. This is impossible to
do with the current way of things.
This change removes the implicit call to rc_free_device() from
rc_unregister_device(). This means that device drivers can call
rc_unregister_device() in their remove or disconnect function, then cancel
all the urbs and interrupts before explicitly calling rc_free_device().
Note this is an alternative fix for an issue found by Haotian Zhang, see
the Closes: tags.
Reported-by: Haotian Zhang <vulab@iscas.ac.cn>
Closes: https://lore.kernel.org/linux-media/20251114101432.2566-1-vulab@iscas.ac.cn
Closes: https://lore.kernel.org/linux-media/20251114101418.2548-1-vulab@iscas.ac.cn
Closes: https://lore.kernel.org/linux-media/20251114101346.2530-1-vulab@iscas.ac.cn/
Closes: https://lore.kernel.org/linux-media/20251114090605.2413-1-vulab@iscas.ac.cn/
Signed-off-by: Sean Young <sean@mess.org>
---
drivers/gpu/drm/bridge/sil-sii8620.c | 1 +
drivers/hid/hid-picolcd_cir.c | 1 +
drivers/media/cec/core/cec-core.c | 2 +-
drivers/media/common/siano/smsir.c | 1 +
drivers/media/i2c/ir-kbd-i2c.c | 2 ++
drivers/media/pci/bt8xx/bttv-input.c | 1 +
drivers/media/pci/cx23885/cx23885-input.c | 1 +
drivers/media/pci/cx88/cx88-input.c | 1 +
drivers/media/pci/dm1105/dm1105.c | 1 +
drivers/media/pci/mantis/mantis_input.c | 1 +
drivers/media/pci/saa7134/saa7134-input.c | 1 +
drivers/media/pci/smipcie/smipcie-ir.c | 1 +
drivers/media/pci/ttpci/budget-ci.c | 1 +
drivers/media/rc/ati_remote.c | 4 ++--
drivers/media/rc/ene_ir.c | 2 +-
drivers/media/rc/fintek-cir.c | 3 ++-
drivers/media/rc/igorplugusb.c | 1 +
drivers/media/rc/iguanair.c | 1 +
drivers/media/rc/img-ir/img-ir-hw.c | 3 ++-
drivers/media/rc/img-ir/img-ir-raw.c | 3 ++-
drivers/media/rc/imon.c | 3 ++-
drivers/media/rc/ir-hix5hd2.c | 2 +-
drivers/media/rc/ir_toy.c | 1 +
drivers/media/rc/ite-cir.c | 2 +-
drivers/media/rc/mceusb.c | 1 +
drivers/media/rc/rc-ir-raw.c | 5 -----
drivers/media/rc/rc-loopback.c | 1 +
drivers/media/rc/rc-main.c | 6 +-----
drivers/media/rc/redrat3.c | 4 +++-
drivers/media/rc/st_rc.c | 2 +-
drivers/media/rc/streamzap.c | 3 ++-
drivers/media/rc/sunxi-cir.c | 1 +
drivers/media/rc/ttusbir.c | 2 +-
drivers/media/rc/winbond-cir.c | 2 +-
drivers/media/rc/xbox_remote.c | 3 ++-
drivers/media/usb/au0828/au0828-input.c | 1 +
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1 +
drivers/media/usb/dvb-usb/dvb-usb-remote.c | 6 ++++--
drivers/media/usb/em28xx/em28xx-input.c | 1 +
drivers/staging/media/av7110/av7110_ir.c | 1 +
include/media/rc-core.h | 2 --
41 files changed, 52 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 9e48ad39e1cc9..923e2ed30624b 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2221,6 +2221,7 @@ static void sii8620_detach(struct drm_bridge *bridge)
return;
rc_unregister_device(ctx->rc_dev);
+ rc_free_device(ctx->rc_dev);
}
static int sii8620_is_packing_required(struct sii8620 *ctx,
diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
index d6faa0e00f95a..6d4c636e1c9f7 100644
--- a/drivers/hid/hid-picolcd_cir.c
+++ b/drivers/hid/hid-picolcd_cir.c
@@ -134,5 +134,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
data->rc_dev = NULL;
rc_unregister_device(rdev);
+ rc_free_device(rdev);
}
diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
index dd6e24a0899bd..1b8a33c05b3c9 100644
--- a/drivers/media/cec/core/cec-core.c
+++ b/drivers/media/cec/core/cec-core.c
@@ -338,8 +338,8 @@ int cec_register_adapter(struct cec_adapter *adap,
res = cec_devnode_register(&adap->devnode, adap->owner);
if (res) {
#ifdef CONFIG_MEDIA_CEC_RC
- /* Note: rc_unregister also calls rc_free */
rc_unregister_device(adap->rc);
+ rc_free_device(adap->rc);
adap->rc = NULL;
#endif
return res;
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index af07fed21ae12..283770d583d56 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -92,6 +92,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
void sms_ir_exit(struct smscore_device_t *coredev)
{
rc_unregister_device(coredev->ir.dev);
+ rc_free_device(coredev->ir.dev);
pr_debug("\n");
}
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 5588cdd7ec20d..6047453170043 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -355,6 +355,7 @@ static void ir_work(struct work_struct *work)
mutex_unlock(&ir->lock);
if (rc == -ENODEV) {
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
ir->rc = NULL;
return;
}
@@ -972,6 +973,7 @@ static void ir_remove(struct i2c_client *client)
i2c_unregister_device(ir->tx_c);
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
}
static const struct i2c_device_id ir_kbd_id[] = {
diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
index 84aa269248fd3..660788080cbe2 100644
--- a/drivers/media/pci/bt8xx/bttv-input.c
+++ b/drivers/media/pci/bt8xx/bttv-input.c
@@ -574,6 +574,7 @@ void bttv_input_fini(struct bttv *btv)
bttv_ir_stop(btv);
rc_unregister_device(btv->remote->dev);
+ rc_free_device(btv->remote->dev);
kfree(btv->remote);
btv->remote = NULL;
}
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index d2e84c6457e0a..722329ef3fd2c 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -402,6 +402,7 @@ void cx23885_input_fini(struct cx23885_dev *dev)
if (dev->kernel_ir == NULL)
return;
rc_unregister_device(dev->kernel_ir->rc);
+ rc_free_device(dev->kernel_ir->rc);
kfree(dev->kernel_ir->phys);
kfree(dev->kernel_ir->name);
kfree(dev->kernel_ir);
diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
index b9f2c14d62b40..16c56d19f916d 100644
--- a/drivers/media/pci/cx88/cx88-input.c
+++ b/drivers/media/pci/cx88/cx88-input.c
@@ -511,6 +511,7 @@ int cx88_ir_fini(struct cx88_core *core)
cx88_ir_stop(core);
rc_unregister_device(ir->dev);
+ rc_free_device(ir->dev);
kfree(ir);
/* done */
diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
index 9e9c7c071accc..e1185aa669f48 100644
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -763,6 +763,7 @@ static int dm1105_ir_init(struct dm1105_dev *dm1105)
static void dm1105_ir_exit(struct dm1105_dev *dm1105)
{
rc_unregister_device(dm1105->ir.dev);
+ rc_free_device(dm1105->ir.dev);
}
static int dm1105_hw_init(struct dm1105_dev *dev)
diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
index 34c0d979240fd..edb4cacf55d22 100644
--- a/drivers/media/pci/mantis/mantis_input.c
+++ b/drivers/media/pci/mantis/mantis_input.c
@@ -72,5 +72,6 @@ EXPORT_SYMBOL_GPL(mantis_input_init);
void mantis_input_exit(struct mantis_pci *mantis)
{
rc_unregister_device(mantis->rc);
+ rc_free_device(mantis->rc);
}
EXPORT_SYMBOL_GPL(mantis_input_exit);
diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
index 468dbe8d552f8..d39537c95d9d3 100644
--- a/drivers/media/pci/saa7134/saa7134-input.c
+++ b/drivers/media/pci/saa7134/saa7134-input.c
@@ -834,6 +834,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
return;
rc_unregister_device(dev->remote->dev);
+ rc_free_device(dev->remote->dev);
kfree(dev->remote);
dev->remote = NULL;
}
diff --git a/drivers/media/pci/smipcie/smipcie-ir.c b/drivers/media/pci/smipcie/smipcie-ir.c
index c0604d9c70119..2949cc97462d4 100644
--- a/drivers/media/pci/smipcie/smipcie-ir.c
+++ b/drivers/media/pci/smipcie/smipcie-ir.c
@@ -180,6 +180,7 @@ void smi_ir_exit(struct smi_dev *dev)
struct rc_dev *rc_dev = ir->rc_dev;
rc_unregister_device(rc_dev);
+ rc_free_device(rc_dev);
smi_ir_stop(ir);
ir->rc_dev = NULL;
}
diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
index 33f08adf4feb1..16973ac8e6a92 100644
--- a/drivers/media/pci/ttpci/budget-ci.c
+++ b/drivers/media/pci/ttpci/budget-ci.c
@@ -249,6 +249,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work);
rc_unregister_device(budget_ci->ir.dev);
+ rc_free_device(budget_ci->ir.dev);
}
static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index a733914a25742..1dd1edb3702c6 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -921,7 +921,6 @@ static int ati_remote_probe(struct usb_interface *interface,
input_free_device(input_dev);
exit_unregister_device:
rc_unregister_device(rc_dev);
- rc_dev = NULL;
exit_kill_urbs:
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
@@ -941,6 +940,7 @@ static void ati_remote_disconnect(struct usb_interface *interface)
struct ati_remote *ati_remote;
ati_remote = usb_get_intfdata(interface);
+ rc_unregister_device(ati_remote->rdev);
usb_set_intfdata(interface, NULL);
if (!ati_remote) {
dev_warn(&interface->dev, "%s - null device?\n", __func__);
@@ -951,8 +951,8 @@ static void ati_remote_disconnect(struct usb_interface *interface)
usb_kill_urb(ati_remote->out_urb);
if (ati_remote->idev)
input_unregister_device(ati_remote->idev);
- rc_unregister_device(ati_remote->rdev);
ati_remote_free_buffers(ati_remote);
+ rc_free_device(ati_remote->rdev);
kfree(ati_remote);
}
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index d6c54a3bccc26..136fc4192265d 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1090,7 +1090,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
release_region(dev->hw_io, ENE_IO_SIZE);
exit_unregister_device:
rc_unregister_device(rdev);
- rdev = NULL;
exit_free_dev_rdev:
rc_free_device(rdev);
kfree(dev);
@@ -1110,6 +1109,7 @@ static void ene_remove(struct pnp_dev *pnp_dev)
ene_rx_restore_hw_buffer(dev);
spin_unlock_irqrestore(&dev->hw_lock, flags);
+ rc_free_device(dev->rdev);
free_irq(dev->irq, dev);
release_region(dev->hw_io, ENE_IO_SIZE);
kfree(dev);
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 3fb0968efd57d..9b789097cdd4c 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -568,6 +568,7 @@ static void fintek_remove(struct pnp_dev *pdev)
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
unsigned long flags;
+ rc_unregister_device(fintek->rdev);
spin_lock_irqsave(&fintek->fintek_lock, flags);
/* disable CIR */
fintek_disable_cir(fintek);
@@ -580,7 +581,7 @@ static void fintek_remove(struct pnp_dev *pdev)
free_irq(fintek->cir_irq, fintek);
release_region(fintek->cir_addr, fintek->cir_port_len);
- rc_unregister_device(fintek->rdev);
+ rc_free_device(fintek->rdev);
kfree(fintek);
}
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
index e034c93d57cf0..5ceb5ca44e235 100644
--- a/drivers/media/rc/igorplugusb.c
+++ b/drivers/media/rc/igorplugusb.c
@@ -242,6 +242,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_unpoison_urb(ir->urb);
usb_free_urb(ir->urb);
+ rc_free_device(ir->rc);
kfree(ir->buf_in);
}
diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
index 8af94246e5916..7bd6dd7254157 100644
--- a/drivers/media/rc/iguanair.c
+++ b/drivers/media/rc/iguanair.c
@@ -500,6 +500,7 @@ static void iguanair_disconnect(struct usb_interface *intf)
usb_set_intfdata(intf, NULL);
usb_kill_urb(ir->urb_in);
usb_kill_urb(ir->urb_out);
+ rc_free_device(ir->rc);
usb_free_urb(ir->urb_in);
usb_free_urb(ir->urb_out);
usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 63f6f5b36838d..f30adf4d8444d 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -1118,9 +1118,10 @@ void img_ir_remove_hw(struct img_ir_priv *priv)
struct rc_dev *rdev = hw->rdev;
if (!rdev)
return;
+ rc_unregister_device(rdev);
img_ir_set_decoder(priv, NULL, 0);
hw->rdev = NULL;
- rc_unregister_device(rdev);
+ rc_free_device(rdev);
#ifdef CONFIG_COMMON_CLK
if (!IS_ERR(priv->clk))
clk_notifier_unregister(priv->clk, &hw->clk_nb);
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
index 92fb7b555a0f6..f1460d4acf3e8 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.c
+++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -136,6 +136,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
if (!rdev)
return;
+ rc_unregister_device(rdev);
/* switch off and disable raw (edge) interrupts */
spin_lock_irq(&priv->lock);
raw->rdev = NULL;
@@ -145,7 +146,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
spin_unlock_irq(&priv->lock);
- rc_unregister_device(rdev);
+ rc_free_device(rdev);
timer_delete_sync(&raw->timer);
}
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 35b9e07003d88..48534bb52e4d0 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -2541,9 +2541,10 @@ static void imon_disconnect(struct usb_interface *interface)
if (ifnum == 0) {
ictx->dev_present_intf0 = false;
+ rc_unregister_device(ictx->rdev);
usb_kill_urb(ictx->rx_urb_intf0);
input_unregister_device(ictx->idev);
- rc_unregister_device(ictx->rdev);
+ rc_free_device(ictx->rdev);
if (ictx->display_supported) {
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
usb_deregister_dev(interface, &imon_lcd_class);
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index edc46828509c8..1b061e4a3dcfa 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -331,7 +331,6 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
regerr:
rc_unregister_device(rdev);
- rdev = NULL;
clkerr:
clk_disable_unprepare(priv->clock);
err:
@@ -346,6 +345,7 @@ static void hix5hd2_ir_remove(struct platform_device *pdev)
clk_disable_unprepare(priv->clock);
rc_unregister_device(priv->rdev);
+ rc_free_device(priv->rdev);
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c
index 533faa1175174..e79de56997a42 100644
--- a/drivers/media/rc/ir_toy.c
+++ b/drivers/media/rc/ir_toy.c
@@ -536,6 +536,7 @@ static void irtoy_disconnect(struct usb_interface *intf)
usb_free_urb(ir->urb_out);
usb_kill_urb(ir->urb_in);
usb_free_urb(ir->urb_in);
+ rc_free_device(ir->rc);
kfree(ir->in);
kfree(ir->out);
kfree(ir);
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index 2bacecb022623..23afbafb55748 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1414,7 +1414,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
release_region(itdev->cir_addr, itdev->params->io_region_size);
exit_unregister_device:
rc_unregister_device(rdev);
- rdev = NULL;
exit_free_dev_rdev:
rc_free_device(rdev);
kfree(itdev);
@@ -1439,6 +1438,7 @@ static void ite_remove(struct pnp_dev *pdev)
release_region(dev->cir_addr, dev->params->io_region_size);
rc_unregister_device(dev->rdev);
+ rc_free_device(dev->rdev);
kfree(dev);
}
diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
index 044767eb3a38c..a4c94fdf767ca 100644
--- a/drivers/media/rc/mceusb.c
+++ b/drivers/media/rc/mceusb.c
@@ -1850,6 +1850,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
usb_free_urb(ir->urb_in);
usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
usb_put_dev(dev);
+ rc_free_device(ir->rc);
kfree(ir);
}
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index 5dafe11f61c6b..76c3d1307f9f1 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -648,9 +648,6 @@ int ir_raw_event_register(struct rc_dev *dev)
void ir_raw_event_free(struct rc_dev *dev)
{
- if (!dev)
- return;
-
kfree(dev->raw);
dev->raw = NULL;
}
@@ -674,8 +671,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
lirc_bpf_free(dev);
- ir_raw_event_free(dev);
-
/*
* A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
* ensure that the raw member is null on unlock; this is how
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index 8288366f891fc..a108b057b5fd5 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -263,6 +263,7 @@ static int __init loop_init(void)
static void __exit loop_exit(void)
{
rc_unregister_device(loopdev.dev);
+ rc_free_device(loopdev.dev);
}
module_init(loop_init);
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index b9bf5cdcde4ae..6bdf32cb4a17d 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1611,6 +1611,7 @@ static void rc_dev_release(struct device *device)
{
struct rc_dev *dev = to_rc_dev(device);
+ ir_raw_event_free(dev);
kfree(dev);
}
@@ -1773,7 +1774,6 @@ struct rc_dev *devm_rc_allocate_device(struct device *dev,
}
rc->dev.parent = dev;
- rc->managed_alloc = true;
*dr = rc;
devres_add(dev, dr);
@@ -2042,11 +2042,7 @@ void rc_unregister_device(struct rc_dev *dev)
device_del(&dev->dev);
ida_free(&rc_ida, dev->minor);
-
- if (!dev->managed_alloc)
- rc_free_device(dev);
}
-
EXPORT_SYMBOL_GPL(rc_unregister_device);
/*
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index a49173f54a4d0..b8289327f6a20 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -1133,11 +1133,13 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
+ struct rc_dev *rc = rr3->rc;
usb_set_intfdata(intf, NULL);
- rc_unregister_device(rr3->rc);
+ rc_unregister_device(rc);
led_classdev_unregister(&rr3->led);
redrat3_delete(rr3, udev);
+ rc_free_device(rc);
}
static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
index 6b70bac5f45d6..0ba06bfc9e14b 100644
--- a/drivers/media/rc/st_rc.c
+++ b/drivers/media/rc/st_rc.c
@@ -203,6 +203,7 @@ static void st_rc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, false);
clk_disable_unprepare(rc_dev->sys_clock);
rc_unregister_device(rc_dev->rdev);
+ rc_free_device(rc_dev->rdev);
}
static int st_rc_open(struct rc_dev *rdev)
@@ -334,7 +335,6 @@ static int st_rc_probe(struct platform_device *pdev)
return ret;
rcerr:
rc_unregister_device(rdev);
- rdev = NULL;
clkerr:
clk_disable_unprepare(rc_dev->sys_clock);
err:
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index d3b48a0dd1f47..b9b241fe46ea1 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -388,15 +388,16 @@ static void streamzap_disconnect(struct usb_interface *interface)
struct streamzap_ir *sz = usb_get_intfdata(interface);
struct usb_device *usbdev = interface_to_usbdev(interface);
+ rc_unregister_device(sz->rdev);
usb_set_intfdata(interface, NULL);
if (!sz)
return;
usb_kill_urb(sz->urb_in);
- rc_unregister_device(sz->rdev);
usb_free_urb(sz->urb_in);
usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+ rc_free_device(sz->rdev);
kfree(sz);
}
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index 92ef4e7c6f69f..cb4c56bf0752a 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -371,6 +371,7 @@ static void sunxi_ir_remove(struct platform_device *pdev)
struct sunxi_ir *ir = platform_get_drvdata(pdev);
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
sunxi_ir_hw_exit(&pdev->dev);
}
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
index 560a26f3965cf..5234c1e9a58ea 100644
--- a/drivers/media/rc/ttusbir.c
+++ b/drivers/media/rc/ttusbir.c
@@ -333,7 +333,6 @@ static int ttusbir_probe(struct usb_interface *intf,
return 0;
out3:
rc_unregister_device(rc);
- rc = NULL;
out2:
led_classdev_unregister(&tt->led);
out:
@@ -373,6 +372,7 @@ static void ttusbir_disconnect(struct usb_interface *intf)
}
usb_kill_urb(tt->bulk_urb);
usb_free_urb(tt->bulk_urb);
+ rc_free_device(tt->rc);
usb_set_intfdata(intf, NULL);
kfree(tt);
}
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 25884a79985c8..14d8b58e28398 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1132,7 +1132,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
release_region(data->wbase, WAKEUP_IOMEM_LEN);
exit_unregister_device:
rc_unregister_device(data->dev);
- data->dev = NULL;
exit_free_rc:
rc_free_device(data->dev);
exit_unregister_led:
@@ -1163,6 +1162,7 @@ wbcir_remove(struct pnp_dev *device)
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
rc_unregister_device(data->dev);
+ rc_free_device(data->dev);
led_classdev_unregister(&data->led);
diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c
index a1572381d0971..027e75e170a1f 100644
--- a/drivers/media/rc/xbox_remote.c
+++ b/drivers/media/rc/xbox_remote.c
@@ -277,6 +277,7 @@ static void xbox_remote_disconnect(struct usb_interface *interface)
struct xbox_remote *xbox_remote;
xbox_remote = usb_get_intfdata(interface);
+ rc_unregister_device(xbox_remote->rdev);
usb_set_intfdata(interface, NULL);
if (!xbox_remote) {
dev_warn(&interface->dev, "%s - null device?\n", __func__);
@@ -284,7 +285,7 @@ static void xbox_remote_disconnect(struct usb_interface *interface)
}
usb_kill_urb(xbox_remote->irq_urb);
- rc_unregister_device(xbox_remote->rdev);
+ rc_free_device(xbox_remote->rdev);
usb_free_urb(xbox_remote->irq_urb);
kfree(xbox_remote);
}
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
index 3d3368202cd01..283ad2c6288cd 100644
--- a/drivers/media/usb/au0828/au0828-input.c
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -357,6 +357,7 @@ void au0828_rc_unregister(struct au0828_dev *dev)
return;
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
/* done */
kfree(ir);
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index f1c79f351ec8d..17e8961179d14 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -187,6 +187,7 @@ static int dvb_usbv2_remote_exit(struct dvb_usb_device *d)
if (d->rc_dev) {
cancel_delayed_work_sync(&d->rc_query_work);
rc_unregister_device(d->rc_dev);
+ rc_free_device(d->rc_dev);
d->rc_dev = NULL;
}
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
index 65e2c9e2cdc99..6dc11718dfb98 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
@@ -347,10 +347,12 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
{
if (d->state & DVB_USB_STATE_REMOTE) {
cancel_delayed_work_sync(&d->rc_query_work);
- if (d->props.rc.mode == DVB_RC_LEGACY)
+ if (d->props.rc.mode == DVB_RC_LEGACY) {
input_unregister_device(d->input_dev);
- else
+ } else {
rc_unregister_device(d->rc_dev);
+ rc_free_device(d->rc_dev);
+ }
}
d->state &= ~DVB_USB_STATE_REMOTE;
return 0;
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index 5f3b00869bdbc..26f333b5be732 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -853,6 +853,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
goto ref_put;
rc_unregister_device(ir->rc);
+ rc_free_device(ir->rc);
kfree(ir->i2c_client);
diff --git a/drivers/staging/media/av7110/av7110_ir.c b/drivers/staging/media/av7110/av7110_ir.c
index 68b3979ba5f20..fdae467fd7ab8 100644
--- a/drivers/staging/media/av7110/av7110_ir.c
+++ b/drivers/staging/media/av7110/av7110_ir.c
@@ -151,6 +151,7 @@ int av7110_ir_init(struct av7110 *av7110)
void av7110_ir_exit(struct av7110 *av7110)
{
rc_unregister_device(av7110->ir.rcdev);
+ rc_free_device(av7110->ir.rcdev);
}
//MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 35c7a0546f02e..7c964b5ad7926 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -81,7 +81,6 @@ struct lirc_fh {
/**
* struct rc_dev - represents a remote control device
* @dev: driver model's view of this device
- * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
* @registered: set to true by rc_register_device(), false by
* rc_unregister_device
* @idle: used to keep track of RX state
@@ -156,7 +155,6 @@ struct lirc_fh {
*/
struct rc_dev {
struct device dev;
- bool managed_alloc;
bool registered;
bool idle;
bool encode_wakeup;
--
2.52.0
^ permalink raw reply related
* [PATCH v2 RESEND] selftests: hid: tests: test_wacom_generic: add tests for display devices and opaque devices
From: Alex Tran @ 2025-12-20 20:48 UTC (permalink / raw)
To: jikos, bentiss, shuah
Cc: linux-input, linux-kselftest, linux-kernel, Alex Tran
Verify Wacom devices set INPUT_PROP_DIRECT on display devices and
INPUT_PROP_POINTER on opaque devices. Moved test_prop_pointer into
TestOpaqueTablet. Created a DirectTabletTest mixin class for
test_prop_direct that can be inherited by display tablet test classes.
Used DirectTabletTest for TestDTH2452Tablet case.
Signed-off-by: Alex Tran <alex.t.tran@gmail.com>
---
Changes in v2:
- Removed the tests from the BaseTest class
- Removed disabling tests for certain subclasses
- Moved test_prop_pointer under TestOpaqueTablet
- Created DirectTabletTest mixin class
- Moved test_prop_direct under TestDTH2452Tablet
.../selftests/hid/tests/test_wacom_generic.py | 30 +++++++++++--------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/tools/testing/selftests/hid/tests/test_wacom_generic.py b/tools/testing/selftests/hid/tests/test_wacom_generic.py
index 2d6d04f0f..9d0b0802d 100644
--- a/tools/testing/selftests/hid/tests/test_wacom_generic.py
+++ b/tools/testing/selftests/hid/tests/test_wacom_generic.py
@@ -598,18 +598,6 @@ class BaseTest:
if unit_set:
assert required[usage].contains(field)
- def test_prop_direct(self):
- """
- Todo: Verify that INPUT_PROP_DIRECT is set on display devices.
- """
- pass
-
- def test_prop_pointer(self):
- """
- Todo: Verify that INPUT_PROP_POINTER is set on opaque devices.
- """
- pass
-
class PenTabletTest(BaseTest.TestTablet):
def assertName(self, uhdev):
@@ -677,6 +665,13 @@ class TestOpaqueTablet(PenTabletTest):
uhdev.event(130, 240, pressure=0), [], auto_syn=False, strict=True
)
+ def test_prop_pointer(self):
+ """
+ Verify that INPUT_PROP_POINTER is set on opaque devices.
+ """
+ evdev = self.uhdev.get_evdev()
+ assert libevdev.INPUT_PROP_POINTER in evdev.properties
+
class TestOpaqueCTLTablet(TestOpaqueTablet):
def create_device(self):
@@ -862,7 +857,16 @@ class TestPTHX60_Pen(TestOpaqueCTLTablet):
)
-class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest):
+class DirectTabletTest():
+ def test_prop_direct(self):
+ """
+ Verify that INPUT_PROP_DIRECT is set on display devices.
+ """
+ evdev = self.uhdev.get_evdev()
+ assert libevdev.INPUT_PROP_DIRECT in evdev.properties
+
+
+class TestDTH2452Tablet(test_multitouch.BaseTest.TestMultitouch, TouchTabletTest, DirectTabletTest):
ContactIds = namedtuple("ContactIds", "contact_id, tracking_id, slot_num")
def create_device(self):
--
2.51.0
^ permalink raw reply related
* [PATCH] HID: input: Increase maximum number of joystick buttons
From: Ivan Gorinov @ 2025-12-20 19:41 UTC (permalink / raw)
To: Jiri Kosina; +Cc: linux-input, linux-kernel
This patch increases the limit from 80 to 112 key codes.
If a joystick has 80 or fewer buttons, mapping stays the same.
If a joystick has more than 80 buttons:
Map buttons [ 0 .. 15 ] to key codes starting with BTN_JOYSTICK;
Map buttons [ 16 .. 47 ] to key codes starting with KEY_MACRO1;
Map buttons [ 48 .. 111 ] to key codes starting with BTN_TRIGGER_HAPPY.
Signed-off-by: Ivan Gorinov <linux-kernel@altimeter.info>
---
drivers/hid/hid-input.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 2633fcd8f910..c6159f96de04 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -763,7 +763,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
if (code <= 0xf)
code += BTN_JOYSTICK;
else
- code += BTN_TRIGGER_HAPPY - 0x10;
+ if (field->maxusage <= 80)
+ code += BTN_TRIGGER_HAPPY - 0x10;
+ else
+ if (code <= 0x2f)
+ code += KEY_MACRO1 - 0x10;
+ else
+ code += BTN_TRIGGER_HAPPY - 0x30;
break;
case HID_GD_GAMEPAD:
if (code <= 0xf)
--
2.43.0
^ permalink raw reply related
* [dtor-input:for-linus] BUILD SUCCESS 248d3a73a0167dce15ba100477c3e778c4787178
From: kernel test robot @ 2025-12-20 19:09 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
branch HEAD: 248d3a73a0167dce15ba100477c3e778c4787178 Input: ti_am335x_tsc - fix off-by-one error in wire_order validation
elapsed time: 2224m
configs tested: 81
configs skipped: 0
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-15.1.0
alpha allyesconfig gcc-15.1.0
alpha defconfig gcc-15.1.0
arc allnoconfig gcc-15.1.0
arc allyesconfig clang-22
arc allyesconfig gcc-15.1.0
arc defconfig gcc-15.1.0
arm allnoconfig clang-22
arm allnoconfig gcc-15.1.0
arm defconfig gcc-15.1.0
arm64 allmodconfig clang-19
arm64 allmodconfig clang-22
arm64 allnoconfig gcc-15.1.0
arm64 defconfig gcc-15.1.0
csky allmodconfig gcc-15.1.0
csky allnoconfig gcc-15.1.0
csky defconfig gcc-15.1.0
hexagon allmodconfig clang-17
hexagon allmodconfig gcc-15.1.0
hexagon allnoconfig clang-22
hexagon allnoconfig gcc-15.1.0
hexagon defconfig gcc-15.1.0
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-15.1.0
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001-20251220 gcc-14
i386 buildonly-randconfig-002-20251220 gcc-14
i386 buildonly-randconfig-003-20251220 gcc-14
i386 buildonly-randconfig-004-20251220 gcc-14
i386 buildonly-randconfig-005-20251220 gcc-14
i386 buildonly-randconfig-006-20251220 gcc-14
i386 defconfig gcc-15.1.0
loongarch allmodconfig clang-19
loongarch allmodconfig clang-22
loongarch allnoconfig clang-22
loongarch allnoconfig gcc-15.1.0
m68k allmodconfig gcc-15.1.0
m68k allnoconfig gcc-15.1.0
microblaze allnoconfig gcc-15.1.0
microblaze allyesconfig gcc-15.1.0
mips allnoconfig gcc-15.1.0
mips allyesconfig gcc-15.1.0
nios2 allmodconfig clang-22
nios2 allnoconfig clang-22
nios2 allnoconfig gcc-11.5.0
openrisc allmodconfig clang-22
openrisc allnoconfig clang-22
openrisc allnoconfig gcc-15.1.0
parisc allnoconfig clang-22
parisc allnoconfig gcc-15.1.0
powerpc allnoconfig clang-22
powerpc allnoconfig gcc-15.1.0
riscv allmodconfig clang-22
riscv allnoconfig clang-22
riscv allnoconfig gcc-15.1.0
s390 allnoconfig clang-22
sh allmodconfig gcc-15.1.0
sh allnoconfig clang-22
sh allnoconfig gcc-15.1.0
sparc allnoconfig clang-22
sparc allnoconfig gcc-15.1.0
sparc64 allmodconfig clang-22
um allnoconfig clang-22
um allyesconfig gcc-14
um allyesconfig gcc-15.1.0
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-20
x86_64 allnoconfig clang-22
x86_64 allyesconfig clang-20
x86_64 kexec clang-20
x86_64 rhel-9.4 clang-20
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-20
x86_64 rhel-9.4-kselftests clang-20
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig clang-22
xtensa allnoconfig gcc-15.1.0
xtensa allyesconfig clang-22
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [dtor-input:next] BUILD SUCCESS eeb2ea4b59df5fdcb697904fe6f49d5851543808
From: kernel test robot @ 2025-12-20 11:22 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: eeb2ea4b59df5fdcb697904fe6f49d5851543808 Input: ilitek_ts_i2c - switch mdelay() to fsleep()
elapsed time: 1757m
configs tested: 43
configs skipped: 0
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-15.1.0
alpha allyesconfig gcc-15.1.0
arc allnoconfig gcc-15.1.0
arc allyesconfig gcc-15.1.0
arm allnoconfig clang-22
arm64 allmodconfig clang-19
arm64 allnoconfig gcc-15.1.0
csky allmodconfig gcc-15.1.0
csky allnoconfig gcc-15.1.0
hexagon allmodconfig clang-17
hexagon allnoconfig clang-22
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allyesconfig gcc-14
loongarch allmodconfig clang-19
loongarch allnoconfig clang-22
m68k allmodconfig gcc-15.1.0
m68k allnoconfig gcc-15.1.0
microblaze allnoconfig gcc-15.1.0
microblaze allyesconfig gcc-15.1.0
mips allnoconfig gcc-15.1.0
mips allyesconfig gcc-15.1.0
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig gcc-11.5.0
openrisc allmodconfig gcc-15.1.0
openrisc allnoconfig gcc-15.1.0
parisc allnoconfig gcc-15.1.0
powerpc allnoconfig gcc-15.1.0
riscv allmodconfig clang-22
riscv allnoconfig gcc-15.1.0
s390 allnoconfig clang-22
sh allmodconfig gcc-15.1.0
sh allnoconfig gcc-15.1.0
sparc allnoconfig gcc-15.1.0
sparc64 allmodconfig clang-22
um allnoconfig clang-22
um allyesconfig gcc-14
x86_64 allmodconfig clang-20
x86_64 allnoconfig clang-20
x86_64 allyesconfig clang-20
x86_64 rhel-9.4-rust clang-20
xtensa allnoconfig gcc-15.1.0
xtensa allyesconfig gcc-15.1.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH v2] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
From: pip-izony @ 2025-12-20 0:24 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Seungjin Bae, Kyungtae Kim, Sanghoon Choi, Dan Carpenter,
linux-input, linux-kernel
In-Reply-To: <hr5f6diryl6xrmszastqyyfnsfsve4uxqzee4ct7ihj6agzkmo@dm3wm2mwhg2w>
From: Seungjin Bae <eeodqql09@gmail.com>
The `ims_pcu_process_data()` processes incoming URB data byte by byte.
However, it fails to check if the `read_pos` index exceeds
IMS_PCU_BUF_SIZE.
If a malicious USB device sends a packet larger than IMS_PCU_BUF_SIZE,
`read_pos` will increment indefinitely. Moreover, since `read_pos` is
located immediately after `read_buf`, the attacker can overwrite
`read_pos` itself to arbitrarily control the index.
This manipulated `read_pos` is subsequently used in
`ims_pcu_handle_response()` to copy data into `cmd_buf`, leading to a
heap buffer overflow.
Specifically, an attacker can overwrite the `cmd_done.wait.head` located
at offset 136 relative to `cmd_buf` in the `ims_pcu_handle_response()`.
Consequently, when the driver calls `complete(&pcu->cmd_done)`, it
triggers a control flow hijack by using the manipulated pointer.
Fix this by adding a bounds check for `read_pos` before writing to
`read_buf`. If the packet is too long, discard it, log a warining,
and reset the parser state.
Fixes: 628329d524743 ("Input: add IMS Passenger Control Unit driver")
Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
---
v1 -> v2: Add warning and reset the state of the parser for bad packet
drivers/input/misc/ims-pcu.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4581f1c53644..c98ef71c841e 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -450,6 +450,16 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
continue;
if (pcu->have_dle) {
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ pcu->have_stx = false;
+ pcu->have_dle = false;
+ pcu->read_pos = 0;
+ continue;
+ }
+
pcu->have_dle = false;
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
@@ -491,6 +501,16 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
break;
default:
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ pcu->have_stx = false;
+ pcu->have_dle = false;
+ pcu->read_pos = 0;
+ continue;
+ }
+
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
break;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
From: Dmitry Torokhov @ 2025-12-19 23:36 UTC (permalink / raw)
To: pip-izony
Cc: Kyungtae Kim, Sanghoon Choi, Dan Carpenter, linux-input,
linux-kernel
In-Reply-To: <20251219223417.369278-2-eeodqql09@gmail.com>
Hi Seungjin,
On Fri, Dec 19, 2025 at 05:34:18PM -0500, pip-izony wrote:
> From: Seungjin Bae <eeodqql09@gmail.com>
>
> The `ims_pcu_process_data()` processes incoming URB data byte by byte.
> However, it fails to check if the `read_pos` index exceeds
> IMS_PCU_BUF_SIZE.
>
> If a malicious USB device sends a packet larger than IMS_PCU_BUF_SIZE,
> `read_pos` will increment indefinitely. Moreover, since `read_pos` is
> located immediately after `read_buf`, the attacker can overwrite
> `read_pos` itself to arbitrarily control the index.
>
> This manipulated `read_pos` is subsequently used in
> `ims_pcu_handle_response()` to copy data into `cmd_buf`, leading to a
> heap buffer overflow.
>
> Specifically, an attacker can overwrite the `cmd_done.wait.head` located
> at offset 136 relative to `cmd_buf` in the `ims_pcu_handle_response()`.
> Consequently, when the driver calls `complete(&pcu->cmd_done)`, it
> triggers a control flow hijack by using the manipulated pointer.
>
> Fix this by adding a bounds check for `read_pos` before writing to
> `read_buf`.
>
> Fixes: 628329d524743 ("Input: add IMS Passenger Control Unit driver")
> Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
> ---
> drivers/input/misc/ims-pcu.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
> index 4581f1c53644..402bf03ca8f6 100644
> --- a/drivers/input/misc/ims-pcu.c
> +++ b/drivers/input/misc/ims-pcu.c
> @@ -451,7 +451,8 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
>
> if (pcu->have_dle) {
> pcu->have_dle = false;
> - pcu->read_buf[pcu->read_pos++] = data;
> + if (pcu->read_pos < IMS_PCU_BUF_SIZE)
> + pcu->read_buf[pcu->read_pos++] = data;
I think we might want a warning if we're overflowing the buffer.
> pcu->check_sum += data;
I don't think we should be adding the discarded bytes to the checksum.
Or maybe we should reset the state of the parser, discarding bad (too
large) packet.
> continue;
> }
> @@ -491,7 +492,8 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
> break;
>
> default:
> - pcu->read_buf[pcu->read_pos++] = data;
> + if (pcu->read_pos < IMS_PCU_BUF_SIZE)
> + pcu->read_buf[pcu->read_pos++] = data;
> pcu->check_sum += data;
> break;
> }
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
From: pip-izony @ 2025-12-19 22:34 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Seungjin Bae, Kyungtae Kim, Sanghoon Choi, Dan Carpenter,
linux-input, linux-kernel
From: Seungjin Bae <eeodqql09@gmail.com>
The `ims_pcu_process_data()` processes incoming URB data byte by byte.
However, it fails to check if the `read_pos` index exceeds
IMS_PCU_BUF_SIZE.
If a malicious USB device sends a packet larger than IMS_PCU_BUF_SIZE,
`read_pos` will increment indefinitely. Moreover, since `read_pos` is
located immediately after `read_buf`, the attacker can overwrite
`read_pos` itself to arbitrarily control the index.
This manipulated `read_pos` is subsequently used in
`ims_pcu_handle_response()` to copy data into `cmd_buf`, leading to a
heap buffer overflow.
Specifically, an attacker can overwrite the `cmd_done.wait.head` located
at offset 136 relative to `cmd_buf` in the `ims_pcu_handle_response()`.
Consequently, when the driver calls `complete(&pcu->cmd_done)`, it
triggers a control flow hijack by using the manipulated pointer.
Fix this by adding a bounds check for `read_pos` before writing to
`read_buf`.
Fixes: 628329d524743 ("Input: add IMS Passenger Control Unit driver")
Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
---
drivers/input/misc/ims-pcu.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4581f1c53644..402bf03ca8f6 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -451,7 +451,8 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
if (pcu->have_dle) {
pcu->have_dle = false;
- pcu->read_buf[pcu->read_pos++] = data;
+ if (pcu->read_pos < IMS_PCU_BUF_SIZE)
+ pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
continue;
}
@@ -491,7 +492,8 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
break;
default:
- pcu->read_buf[pcu->read_pos++] = data;
+ if (pcu->read_pos < IMS_PCU_BUF_SIZE)
+ pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
break;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3] hid/hid-multitouch: Keep latency normal on deactivate for reactivation gesture
From: Werner Sembach @ 2025-12-19 15:55 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <rejkk25fhay4ozlnrior3vbpo4wa6s2rpezmt3kydf7e3jr7k4@vv7423v4mssq>
Am 19.12.25 um 14:10 schrieb Benjamin Tissoires:
> On Nov 12 2025, Werner Sembach wrote:
>> Am 12.11.25 um 15:47 schrieb Werner Sembach:
>>> Uniwill devices have a built in gesture in the touchpad to de- and
>>> reactivate it by double taping the upper left corner. This gesture stops
>>> working when latency is set to high, so this patch keeps the latency on
>>> normal.
>>>
>>> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
>>> Cc: stable@vger.kernel.org
>>> ---
>>> V1->V2: Use a quirk to narrow down the devices this is applied to.
>>> V2->V3: Fix this patch breaking touchpads on some devices.
>>> Add another device ID.
>>>
>>> I have three Uniwill devices at hand right now that have at least two
>>> physically different touchpads, but same Vendor + Product ID combination.
>>> Maybe the vendor uses this product ID for all i2c connected touchpads, or
>>> it is used as some kind of subvendor ID to indicate Uniwill?
>>>
>>> To be able to really narrow it down to Uniwill only devices I would need to
>>> check DMI strings, but then I will probably narrow it down to much as I
>>> only know what we at TUXEDO use there.
>>>
>>> drivers/hid/hid-multitouch.c | 26 +++++++++++++++++++++++++-
>>> 1 file changed, 25 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
>>> index 179dc316b4b51..ed9eb4e0d5038 100644
>>> --- a/drivers/hid/hid-multitouch.c
>>> +++ b/drivers/hid/hid-multitouch.c
>>> @@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
>>> #define MT_QUIRK_DISABLE_WAKEUP BIT(21)
>>> #define MT_QUIRK_ORIENTATION_INVERT BIT(22)
>>> #define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
>>> +#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(24)
>>> #define MT_INPUTMODE_TOUCHSCREEN 0x02
>>> #define MT_INPUTMODE_TOUCHPAD 0x03
>>> @@ -211,6 +212,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
>>> #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
>>> #define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017
>>> #define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018
>>> +#define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019
>> A college realized that at some points in the code some, but not all, of the
>> MT_CLS_WIN_8* classes are checked for directly. Should I add my new class
>> there too?
> It depends. If it's truely a WIN_8 touchpad then I guess those checks
> are here for a reason, but if this particular device works without them,
> then it's your call in the end.
Didn't notice a difference, but will it include anyway to be on the safe side.
v4 incoming
>
> Cheers,
> Benjamin
^ permalink raw reply
* Re: [PATCH 3/3] HID: multitouch: set INPUT_PROP_PRESSUREPAD based on Digitizer/Button Type
From: Benjamin Tissoires @ 2025-12-19 14:00 UTC (permalink / raw)
To: Peter Hutterer
Cc: Jiri Kosina, Shuah Khan, Dmitry Torokhov, linux-input,
linux-kselftest, linux-kernel, Vadim Klishko
In-Reply-To: <20251121-wip-hid-pressurepad-v1-3-e32e5565a527@who-t.net>
On Nov 21 2025, Peter Hutterer wrote:
> A Digitizer/Button Type value of 1 indicates the device is a
> pressurepad, see
> https://learn.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchpad-windows-precision-touchpad-collection#device-capabilities-feature-report
>
> For the selftests we have to resort to a bit of a hack: python-libevdev
> gets the properties from libevdev at module init time. If libevdev
> hasn't been rebuilt with the new property it won't be automatically
> populated. So we hack around this by constructing the property manually.
>
> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
> ---
> drivers/hid/hid-multitouch.c | 12 ++++++-
> .../testing/selftests/hid/tests/test_multitouch.py | 39 +++++++++++++++++++---
> 2 files changed, 46 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index 179dc316b4b518d78bdc900d9fd15756c5eba83e..382e6f50c4f7e663af7d028abb8be7cb2e6e7b8e 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -81,6 +81,7 @@ MODULE_LICENSE("GPL");
> #define MT_INPUTMODE_TOUCHPAD 0x03
>
> #define MT_BUTTONTYPE_CLICKPAD 0
> +#define MT_BUTTONTYPE_PRESSUREPAD 1
>
> enum latency_mode {
> HID_LATENCY_NORMAL = 0,
> @@ -179,6 +180,7 @@ struct mt_device {
> __u8 inputmode_value; /* InputMode HID feature value */
> __u8 maxcontacts;
> bool is_buttonpad; /* is this device a button pad? */
> + bool is_pressurepad; /* is this device a pressurepad? */
> bool is_haptic_touchpad; /* is this device a haptic touchpad? */
> bool serial_maybe; /* need to check for serial protocol */
>
> @@ -530,8 +532,14 @@ static void mt_feature_mapping(struct hid_device *hdev,
> }
>
> mt_get_feature(hdev, field->report);
> - if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD)
> + switch (field->value[usage->usage_index]) {
> + case MT_BUTTONTYPE_CLICKPAD:
> td->is_buttonpad = true;
> + break;
> + case MT_BUTTONTYPE_PRESSUREPAD:
> + td->is_pressurepad = true;
> + break;
> + }
>
> break;
> case 0xff0000c5:
> @@ -1393,6 +1401,8 @@ static int mt_touch_input_configured(struct hid_device *hdev,
>
> if (td->is_buttonpad)
> __set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
> + if (td->is_pressurepad)
> + __set_bit(INPUT_PROP_PRESSUREPAD, input->propbit);
>
> app->pending_palm_slots = devm_kcalloc(&hi->input->dev,
> BITS_TO_LONGS(td->maxcontacts),
> diff --git a/tools/testing/selftests/hid/tests/test_multitouch.py b/tools/testing/selftests/hid/tests/test_multitouch.py
> index a06a087f00b6991f7514adf7f8c713bef1a43563..fa4fb2054bd4febb1d2497f2787944f538b27889 100644
> --- a/tools/testing/selftests/hid/tests/test_multitouch.py
> +++ b/tools/testing/selftests/hid/tests/test_multitouch.py
> @@ -979,15 +979,36 @@ class BaseTest:
> assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_ORIENTATION, 90) in events
>
> class TestPTP(TestWin8Multitouch):
> + def test_buttontype(self):
> + """Check for the right ButtonType."""
> + uhdev = self.uhdev
> + assert uhdev is not None
> + evdev = uhdev.get_evdev()
> +
> + # If libevdev.so is not yet compiled with INPUT_PROP_PRESSUREPAD
> + # python-libevdev won't have it either, let's fake it
> + if not getattr(libevdev, "INPUT_PROP_PRESSUREPAD", None):
> + prop = libevdev.InputProperty(name="INPUT_PROP_PRESSUREPAD", value=0x7)
> + libevdev.INPUT_PROP_PRESSUREPAD = prop
> + libevdev.props.append(prop)
> +
> + if uhdev.buttontype == HIDButtonType.CLICKPAD:
> + assert libevdev.INPUT_PROP_BUTTONPAD in evdev.properties
> + elif uhdev.buttontype == HIDButtonType.PRESSUREPAD:
> + assert libevdev.INPUT_PROP_PRESSUREPAD in evdev.properties
> + else:
> + assert libevdev.INPUT_PROP_PRESSUREPAD not in evdev.properties
> + assert libevdev.INPUT_PROP_BUTTONPAD not in evdev.properties
> +
> def test_ptp_buttons(self):
> """check for button reliability.
> - There are 2 types of touchpads: the click pads and the pressure pads.
> - Each should reliably report the BTN_LEFT events.
> + There are 3 types of touchpads: click pads + pressure pads and
> + those with discrete buttons. Each should reliably report the BTN_LEFT events.
> """
> uhdev = self.uhdev
> evdev = uhdev.get_evdev()
>
> - if uhdev.buttontype == HIDButtonType.CLICKPAD:
> + if uhdev.buttontype in [HIDButtonType.CLICKPAD, HIDButtonType.PRESSUREPAD]:
> r = uhdev.event(click=True)
> events = uhdev.next_sync_events()
> self.debug_reports(r, uhdev, events)
> @@ -999,7 +1020,7 @@ class BaseTest:
> self.debug_reports(r, uhdev, events)
> assert libevdev.InputEvent(libevdev.EV_KEY.BTN_LEFT, 0) in events
> assert evdev.value[libevdev.EV_KEY.BTN_LEFT] == 0
> - else:
> + elif uhdev.buttontype == HIDButtonType.DISCRETE_BUTTONS:
> r = uhdev.event(left=True)
> events = uhdev.next_sync_events()
> self.debug_reports(r, uhdev, events)
> @@ -2062,6 +2083,16 @@ class Testite_06cb_2968(BaseTest.TestPTP):
> )
>
>
> +class Testven_0488_108c(BaseTest.TestPTP):
> + def create_device(self):
> + return PTP(
> + "uhid test ven_0488_108c",
> + rdesc="05 01 09 02 a1 01 85 06 09 01 a1 00 05 09 19 01 29
> 03 15 00 25 01 95 03 75 01 81 02 95 01 75 05 81 03 05 01 09 30 09 31 09
> 38 15 81 25 7f 75 08 95 03 81 06 c0 c0 05 0d 09 05 a1 01 85 01 05 0d 09
> 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09
> 51 81 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0
> 05 95 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f
> 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1 02 15 00 25 01 09 47 09 42 95 02
> 75 01 81 02 95 01 75 03 25 05 09 51 81 02 81 03 05 01 15 00 26 ba 0d 75
> 10 55 0e 65 11 09 30 35 00 46 d0 05 95 01 81 02 26 d0 06 46 bb 02 09 31
> 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff 7f 09 30 81 02 c0 05 0d 09 22 a1
> 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 95 01 75 03 25 05 09 51 81
> 02 81 03 05 01 15 00 26 ba 0d 75 10 55 0e 65 11 09 30 35 00 46 d0 05 95
> 01 81 02 26 d0 06 46 bb 02 09 31 81 02 05 0d 95 01 75 10 26 ff 7f 46 ff
> 7f 09 30 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95
> 01 05 0d 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 09 01 25 01 75
> 01 95 01 81 02 95 07 81 03 05 0d 85 02 09 55 75 08 95 01 25 05 b1 02 09
> 59 b1 02 06 00 ff 85 03 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 05 0e
> 09 01 a1 02 85 13 09 23 15 00 25 64 75 08 95 01 b1 02 c0 c0 05 0d 09 0e
> a1 01 85 04 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1 02 c0 09 22 a1
> 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03 c0 c0 06 01 ff
> 09 02 a1 01 09 00 85 07 15 00 26 ff 00 75 08 96 12 02 b1 02 c0 06 00 ff
> 09 01 a1 01 85 0d 15 00 26 ff 00 75 08 95 11 09 01 81 02 09 01 91 02 c0
> 05 0e 09 01 a1 01 85 11 09 35 15 00 26 ff 00 75 08 95 17 b1 02 c0 06 81
> ff 09 01 a1 01 09 20 85 17 15 00 26 ff 00 75 08 95 3f 09 01 81 02 09 01
> 91 02 c0",
Patch is also corrupt here.
Given that you need to send another revision, would you mind splitting
the hid-multitouch.c changes from the selftests?
Cheers,
Benjamin
> + input_info=(0x18, 0x0488, 0x108C),
> + buttontype=HIDButtonType.PRESSUREPAD,
> + )
> +
> +
> class Testn_trig_1b96_0c01(BaseTest.TestWin8Multitouch):
> def create_device(self):
> return Digitizer(
>
> --
> 2.51.1
>
^ permalink raw reply
* Re: [PATCH 2/3] selftests/hid: use a enum class for the different button types
From: Benjamin Tissoires @ 2025-12-19 13:59 UTC (permalink / raw)
To: Peter Hutterer
Cc: Jiri Kosina, Shuah Khan, Dmitry Torokhov, linux-input,
linux-kselftest, linux-kernel, Vadim Klishko
In-Reply-To: <20251121-wip-hid-pressurepad-v1-2-e32e5565a527@who-t.net>
On Nov 21 2025, Peter Hutterer wrote:
> Instead of multiple spellings of a string-provided argument, let's make
> this a tad more type-safe and use an enum here.
>
> And while we do this fix the two wrong devices:
> - elan_04f3_313a (HP ZBook Fury 15) is discrete button pad
> - dell_044e_1220 (Dell Precision 7740) is a discrete button pad
>
> Equivalent hid-tools commit
> https://gitlab.freedesktop.org/libevdev/hid-tools/-/commit/8300a55bf4213c6a252cab8cb5b34c9ddb191625
>
> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
> ---
> .../testing/selftests/hid/tests/test_multitouch.py | 24 +++++++++++++---------
> 1 file changed, 14 insertions(+), 10 deletions(-)
>
> diff --git a/tools/testing/selftests/hid/tests/test_multitouch.py b/tools/testing/selftests/hid/tests/test_multitouch.py
> index ece0ba8e7d34b75d42245e5936ecf804c46b0846..a06a087f00b6991f7514adf7f8c713bef1a43563 100644
> --- a/tools/testing/selftests/hid/tests/test_multitouch.py
> +++ b/tools/testing/selftests/hid/tests/test_multitouch.py
> @@ -9,6 +9,7 @@
> from . import base
> from hidtools.hut import HUT
> from hidtools.util import BusType
> +import enum
> import libevdev
> import logging
> import pytest
> @@ -232,11 +233,17 @@ class Digitizer(base.UHIDTestDevice):
> return 0
>
>
> +class HIDButtonType(enum.IntEnum):
> + CLICKPAD = 0
> + PRESSUREPAD = 1
> + DISCRETE_BUTTONS = 2
> +
> +
> class PTP(Digitizer):
> def __init__(
> self,
> name,
> - type="Click Pad",
> + buttontype=HIDButtonType.CLICKPAD,
> rdesc_str=None,
> rdesc=None,
> application="Touch Pad",
> @@ -244,11 +251,8 @@ class PTP(Digitizer):
> max_contacts=None,
> input_info=None,
> ):
> - self.type = type.lower().replace(" ", "")
> - if self.type == "clickpad":
> - self.buttontype = 0
> - else: # pressurepad
> - self.buttontype = 1
> + self.buttontype = buttontype
> +
> self.clickpad_state = False
> self.left_state = False
> self.right_state = False
> @@ -983,7 +987,7 @@ class BaseTest:
> uhdev = self.uhdev
> evdev = uhdev.get_evdev()
>
> - if uhdev.type == "clickpad":
> + if uhdev.buttontype == HIDButtonType.CLICKPAD:
> r = uhdev.event(click=True)
> events = uhdev.next_sync_events()
> self.debug_reports(r, uhdev, events)
> @@ -1918,7 +1922,7 @@ class Testdell_044e_1220(BaseTest.TestPTP):
> def create_device(self):
> return PTP(
> "uhid test dell_044e_1220",
> - type="pressurepad",
> + buttontype=HIDButtonType.DISCRETE_BUTTONS,
> rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29
> 03 15 00 25 01 75 01 95 03 81 02 95 05 81 01 05 01 09 30 09 31 15 81 25
> 7f 75 08 95 02 81 06 09 38 95 01 81 06 05 0c 0a 38 02 81 06 c0 c0 05 0d
> 09 05 a1 01 85 08 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02
> 95 01 75 03 25 05 09 51 81 02 75 01 95 03 81 03 05 01 15 00 26 af 04 75
> 10 55 0e 65 11 09 30 35 00 46 e8 03 95 01 81 02 26 7b 02 46 12 02 09 31
> 81 02 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 05 0d
> 09 56 81 02 09 54 25 05 95 01 75 08 81 02 05 09 19 01 29 03 25 01 75 01
> 95 03 81 02 95 05 81 03 05 0d 85 09 09 55 75 08 95 01 25 05 b1 02 06 00
> ff 85 0a 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 06 01 ff 09 01 a1
> 01 85 03 09 01 15 00 26 ff 00 95 1b 81 02 85 04 09 02 95 50 81 02 85 05
> 09 03 95 07 b1 02 85 06 09 04 81 02 c0 06 02 ff 09 01 a1 01 85 07 09 02
> 95 86 75 08 b1 02 c0 05 0d 09 0e a1 01 85 0b 09 22 a1 02 09 52 15 00 25
> 0a 75 08 95 01 b1 02 c0 09 22 a1 00 85 0c 09 57 09 58 75 01 95 02 25 01
> b1 02 95 06 b1 03 c0 c0",
Damn, I wanted to apply the patches, but this one is corrupt here (line
wrapped).
Cheers,
Benjamin
> )
>
> @@ -2018,7 +2022,7 @@ class Testelan_04f3_313a(BaseTest.TestPTP):
> def create_device(self):
> return PTP(
> "uhid test elan_04f3_313a",
> - type="touchpad",
> + buttontype=HIDButtonType.DISCRETE_BUTTONS,
> input_info=(BusType.I2C, 0x04F3, 0x313A),
> rdesc="05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29
> 03 15 00 25 01 75 01 95 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25
> 7f 75 08 95 02 81 06 75 08 95 05 81 03 c0 06 00 ff 09 01 85 0e 09 c5 15
> 00 26 ff 00 75 08 95 04 b1 02 85 0a 09 c6 15 00 26 ff 00 75 08 95 04 b1
> 02 c0 06 00 ff 09 01 a1 01 85 5c 09 01 95 0b 75 08 81 06 85 0d 09 c5 15
> 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 80 03 75 08 b1 02 85 0b 09
> c7 95 82 75 08 b1 02 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01
> 09 47 09 42 95 02 75 01 81 02 05 09 09 02 09 03 15 00 25 01 75 01 95 02
> 81 02 05 0d 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 d7 0e 75 10 55
> 0d 65 11 09 30 35 00 46 44 2f 95 01 81 02 46 12 16 26 eb 06 26 eb 06 09
> 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff
> ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 25 01 75
> 01 95 08 81 03 09 c5 75 08 95 02 81 03 05 0d 85 02 09 55 09 59 75 04 95
> 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06
> 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 c0 05 0d
> 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 10 95 01 b1 02 c0 09
> 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 01 b1 02 95 0e b1 03 c0 c0 05
> 01 09 02 a1 01 85 2a 09 01 a1 00 05 09 19 01 29 03 15 00 25 01 75 01 95
> 03 81 02 95 05 81 03 05 01 09 30 09 31 15 81 25 7f 35 81 45 7f 55 00 65
> 13 75 08 95 02 81 06 75 08 95 05 81 03 c0 c0",
> )
> @@ -2110,7 +2114,7 @@ class Testsipodev_0603_0002(BaseTest.TestPTP):
> def create_device(self):
> return PTP(
> "uhid test sipodev_0603_0002",
> - type="clickpad",
> + buttontype=HIDButtonType.CLICKPAD,
> rdesc="05 01 09 02 a1 01 85 03 09 01 a1 00 05 09 19 01 29
> 02 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 15 80 25 7f 75
> 08 95 02 81 06 c0 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09
> 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 05 09 51 81
> 02 05 01 15 00 26 44 0a 75 0c 55 0e 65 11 09 30 35 00 46 ac 03 95 01 81
> 02 46 fe 01 26 34 05 75 0c 09 31 81 02 05 0d c0 55 0c 66 01 10 47 ff ff
> 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 0a 95 01 75 04 81
> 02 75 01 95 03 81 03 05 09 09 01 25 01 75 01 95 01 81 02 05 0d 85 0a 09
> 55 09 59 75 04 95 02 25 0f b1 02 85 0b 09 60 75 01 95 01 15 00 25 01 b1
> 02 95 07 b1 03 85 09 06 00 ff 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02
> c0 05 0d 09 0e a1 01 85 06 09 22 a1 02 09 52 15 00 25 0a 75 08 95 01 b1
> 02 c0 09 22 a1 00 85 07 09 57 09 58 75 01 95 02 25 01 b1 02 95 06 b1 03
> c0 c0 05 01 09 0c a1 01 85 08 15 00 25 01 09 c6 75 01 95 01 81 06 75 07
> 81 03 c0 05 01 09 80 a1 01 85 01 15 00 25 01 75 01 0a 81 00 0a 82 00 0a
> 83 00 95 03 81 06 95 05 81 01 c0 06 0c 00 09 01 a1 01 85 02 25 01 15 00
> 75 01 0a b5 00 0a b6 00 0a b7 00 0a cd 00 0a e2 00 0a a2 00 0a e9 00 0a
> ea 00 95 08 81 02 0a 83 01 0a 6f 00 0a 70 00 0a 88 01 0a 8a 01 0a 92 01
> 0a a8 02 0a 24 02 95 08 81 02 0a 21 02 0a 23 02 0a 96 01 0a 25 02 0a 26
> 02 0a 27 02 0a 23 02 0a b1 02 95 08 81 02 c0 06 00 ff 09 01 a1 01 85 05
> 15 00 26 ff 00 19 01 29 02 75 08 95 05 b1 02 c0",
> )
>
>
> --
> 2.51.1
>
^ permalink raw reply
* Re: [PATCH v3] hid/hid-multitouch: Keep latency normal on deactivate for reactivation gesture
From: Benjamin Tissoires @ 2025-12-19 13:10 UTC (permalink / raw)
To: Werner Sembach; +Cc: Jiri Kosina, linux-input, linux-kernel
In-Reply-To: <ae75b604-9bdb-430a-bd4d-8e1e669cf4d8@tuxedocomputers.com>
On Nov 12 2025, Werner Sembach wrote:
>
> Am 12.11.25 um 15:47 schrieb Werner Sembach:
> > Uniwill devices have a built in gesture in the touchpad to de- and
> > reactivate it by double taping the upper left corner. This gesture stops
> > working when latency is set to high, so this patch keeps the latency on
> > normal.
> >
> > Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> > Cc: stable@vger.kernel.org
> > ---
> > V1->V2: Use a quirk to narrow down the devices this is applied to.
> > V2->V3: Fix this patch breaking touchpads on some devices.
> > Add another device ID.
> >
> > I have three Uniwill devices at hand right now that have at least two
> > physically different touchpads, but same Vendor + Product ID combination.
> > Maybe the vendor uses this product ID for all i2c connected touchpads, or
> > it is used as some kind of subvendor ID to indicate Uniwill?
> >
> > To be able to really narrow it down to Uniwill only devices I would need to
> > check DMI strings, but then I will probably narrow it down to much as I
> > only know what we at TUXEDO use there.
> >
> > drivers/hid/hid-multitouch.c | 26 +++++++++++++++++++++++++-
> > 1 file changed, 25 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> > index 179dc316b4b51..ed9eb4e0d5038 100644
> > --- a/drivers/hid/hid-multitouch.c
> > +++ b/drivers/hid/hid-multitouch.c
> > @@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
> > #define MT_QUIRK_DISABLE_WAKEUP BIT(21)
> > #define MT_QUIRK_ORIENTATION_INVERT BIT(22)
> > #define MT_QUIRK_APPLE_TOUCHBAR BIT(23)
> > +#define MT_QUIRK_KEEP_LATENCY_ON_CLOSE BIT(24)
> > #define MT_INPUTMODE_TOUCHSCREEN 0x02
> > #define MT_INPUTMODE_TOUCHPAD 0x03
> > @@ -211,6 +212,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app);
> > #define MT_CLS_WIN_8_DISABLE_WAKEUP 0x0016
> > #define MT_CLS_WIN_8_NO_STICKY_FINGERS 0x0017
> > #define MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU 0x0018
> > +#define MT_CLS_WIN_8_KEEP_LATENCY_ON_CLOSE 0x0019
> A college realized that at some points in the code some, but not all, of the
> MT_CLS_WIN_8* classes are checked for directly. Should I add my new class
> there too?
It depends. If it's truely a WIN_8 touchpad then I guess those checks
are here for a reason, but if this particular device works without them,
then it's your call in the end.
Cheers,
Benjamin
^ permalink raw reply
* Re: [PATCH] HID: Intel-thc-hid: Intel-thc: Fix wrong register reading
From: Benjamin Tissoires @ 2025-12-19 13:06 UTC (permalink / raw)
To: jikos, Even Xu; +Cc: srinivas.pandruvada, linux-input, linux-kernel
In-Reply-To: <20251219011438.2104441-1-even.xu@intel.com>
On Fri, 19 Dec 2025 09:14:38 +0800, Even Xu wrote:
> Correct the read register for the setting of max input size and
> interrupt delay.
>
>
Applied to hid/hid.git (for-6.19/upstream-fixes), thanks!
[1/1] HID: Intel-thc-hid: Intel-thc: Fix wrong register reading
https://git.kernel.org/hid/hid/c/f39006965dd3
Cheers,
--
Benjamin Tissoires <bentiss@kernel.org>
^ permalink raw reply
* Re: [PATCH] HID: multitouch: add MT_QUIRK_STICKY_FINGERS to MT_CLS_VTL
From: Benjamin Tissoires @ 2025-12-19 13:06 UTC (permalink / raw)
To: Benjamin Tissoires, DaytonCL; +Cc: jikos, linux-input, linux-kernel
In-Reply-To: <20251214133648.307106-2-artem749507@gmail.com>
On Sun, 14 Dec 2025 14:34:36 +0100, DaytonCL wrote:
> Some VTL-class touchpads (e.g. TOPS0102:00 35CC:0104) intermittently
> fail to release a finger contact. A previous slot remains logically
> active, accompanied by stale BTN_TOOL_DOUBLETAP state, causing
> gestures to stay latched and resulting in stuck two-finger
> scrolling and false right-clicks.
>
> Apply MT_QUIRK_STICKY_FINGERS to handle the unreleased contact correctly.
>
> [...]
Applied to hid/hid.git (for-6.19/upstream-fixes), thanks!
[1/1] HID: multitouch: add MT_QUIRK_STICKY_FINGERS to MT_CLS_VTL
https://git.kernel.org/hid/hid/c/ff3f234ff1dc
Cheers,
--
Benjamin Tissoires <bentiss@kernel.org>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox