Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 3/4] Input: defer handler's start() until device is opened
From: Dmitry Torokhov @ 2026-06-24  5:50 UTC (permalink / raw)
  To: linux-input, Jiri Kosina, Benjamin Tissoires; +Cc: linux-kernel
In-Reply-To: <20260624055008.2494980-1-dmitry.torokhov@gmail.com>

When registering an input handle, handler->start() is currently called
immediately. However, the input device might not be fully opened or
ready to process events at this stage, meaning any state synchronization
events (like setting LED states) injected by the handler's start method
might be dropped.

Move the handler->start() invocation to input_open_device(). If it is
the first handle opening the device, start() is called after the driver's
open() method has successfully completed and the device is fully prepared.

To facilitate this, factor out the device startup logic (calling driver's
open and starting polling) into input_start_device().

For passive observer handlers, their start() method is also deferred
until the handle is opened. Since opening a passive observer handle does
not start the underlying hardware device, their start() method is called
immediately upon opening, regardless of whether the device is active.

Fixes: c7e8dc6ee6d5 ("Input: add start() method to input handlers")
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input.c | 45 +++++++++++++++++++++++++------------------
 include/linux/input.h |  5 +++--
 2 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index c2a038d31beb..0a95cbdc467e 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -568,6 +568,28 @@ void input_release_device(struct input_handle *handle)
 }
 EXPORT_SYMBOL(input_release_device);
 
+static int input_start_device(struct input_dev *dev)
+{
+	int error;
+
+	lockdep_assert_held(&dev->mutex);
+
+	if (dev->users++ == 0 && !dev->inhibited) {
+		if (dev->open) {
+			error = dev->open(dev);
+			if (error) {
+				dev->users--;
+				return error;
+			}
+		}
+
+		if (dev->poller)
+			input_dev_poller_start(dev->poller);
+	}
+
+	return 0;
+}
+
 /**
  * input_open_device - open input device
  * @handle: handle through which device is being accessed
@@ -586,21 +608,9 @@ int input_open_device(struct input_handle *handle)
 
 		handle->open++;
 
-		if (handle->handler->passive_observer)
-			return 0;
-
-		if (dev->users++ || dev->inhibited) {
-			/*
-			 * Device is already opened and/or inhibited,
-			 * so we can exit immediately and report success.
-			 */
-			return 0;
-		}
-
-		if (dev->open) {
-			error = dev->open(dev);
+		if (!handle->handler->passive_observer) {
+			error = input_start_device(dev);
 			if (error) {
-				dev->users--;
 				handle->open--;
 				/*
 				 * Make sure we are not delivering any more
@@ -611,8 +621,8 @@ int input_open_device(struct input_handle *handle)
 			}
 		}
 
-		if (dev->poller)
-			input_dev_poller_start(dev->poller);
+		if (handle->open == 1 && handle->handler->start)
+			handle->handler->start(handle);
 	}
 
 	return 0;
@@ -2662,9 +2672,6 @@ int input_register_handle(struct input_handle *handle)
 	 */
 	list_add_tail_rcu(&handle->h_node, &handler->h_list);
 
-	if (handler->start)
-		handler->start(handle);
-
 	return 0;
 }
 EXPORT_SYMBOL(input_register_handle);
diff --git a/include/linux/input.h b/include/linux/input.h
index 3022bb730898..f7a2cfad5448 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -284,8 +284,9 @@ struct input_handle;
  * @connect: called when attaching a handler to an input device
  * @disconnect: disconnects a handler from input device
  * @start: starts handler for given handle. This function is called by
- *	input core right after connect() method and also when a process
- *	that "grabbed" a device releases it
+ *	input core when device is open and ready to process events,
+ *	and also when device is uninhibited or when a process that "grabbed"
+ *	a device releases it
  * @passive_observer: set to %true by drivers only interested in observing
  *	data stream from devices if there are other users present. Such
  *	drivers will not result in starting underlying hardware device
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [PATCH 2/4] Input: call handler->start() when uninhibiting device
From: Dmitry Torokhov @ 2026-06-24  5:50 UTC (permalink / raw)
  To: linux-input, Jiri Kosina, Benjamin Tissoires; +Cc: linux-kernel
In-Reply-To: <20260624055008.2494980-1-dmitry.torokhov@gmail.com>

When an input device is inhibited via input_inhibit_device(), the driver
is closed and physical feedback (like LEDs and sounds) is toggled off.
However, from the input core's perspective, the handles remain open.

When the device is later uninhibited, the driver is re-opened. While the
core restores simple LED states via input_dev_toggle(), complex handlers
(such as vt/keyboard) may need to re-synchronize their broader logical
state with the hardware.

Fixes: a181616487db ("Input: Add "inhibited" property")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index d99dfe69e12d..c2a038d31beb 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1780,6 +1780,7 @@ static int input_inhibit_device(struct input_dev *dev)
 
 static int input_uninhibit_device(struct input_dev *dev)
 {
+	struct input_handle *handle;
 	int error;
 
 	guard(mutex)(&dev->mutex);
@@ -1803,6 +1804,11 @@ static int input_uninhibit_device(struct input_dev *dev)
 	if (dev->users && dev->poller)
 		input_dev_poller_start(dev->poller);
 
+	list_for_each_entry(handle, &dev->h_list, d_node) {
+		if (handle->open && handle->handler->start)
+			handle->handler->start(handle);
+	}
+
 	return 0;
 }
 
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [PATCH 1/4] Input: fix poller start order on uninhibit
From: Dmitry Torokhov @ 2026-06-24  5:50 UTC (permalink / raw)
  To: linux-input, Jiri Kosina, Benjamin Tissoires; +Cc: linux-kernel

When uninhibiting a device, we start the poller before marking the
device as uninhibited (setting dev->inhibited = false). Since the
poller immediately polls the device and reports events via input_event(),
these initial events are dropped because dev->inhibited is still true.

Fix this by starting the poller only after the device is fully uninhibited
and its state is replayed.

Fixes: a181616487db ("Input: Add "inhibited" property")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
 drivers/input/input.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/input/input.c b/drivers/input/input.c
index cf6fecea79b8..d99dfe69e12d 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -1793,8 +1793,6 @@ static int input_uninhibit_device(struct input_dev *dev)
 			if (error)
 				return error;
 		}
-		if (dev->poller)
-			input_dev_poller_start(dev->poller);
 	}
 
 	dev->inhibited = false;
@@ -1802,6 +1800,9 @@ static int input_uninhibit_device(struct input_dev *dev)
 	scoped_guard(spinlock_irq, &dev->event_lock)
 		input_dev_toggle(dev, true);
 
+	if (dev->users && dev->poller)
+		input_dev_poller_start(dev->poller);
+
 	return 0;
 }
 
-- 
2.55.0.rc0.799.gd6f94ed593-goog


^ permalink raw reply related

* [dtor-input:next] BUILD SUCCESS 0c9245c455e809c8111cb60284328c79064df050
From: kernel test robot @ 2026-06-24  4:40 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: 0c9245c455e809c8111cb60284328c79064df050  Input: cap11xx - add support for CAP1114

elapsed time: 722m

configs tested: 259
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-23
arc                              allmodconfig    gcc-16.1.0
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    clang-23
arc                              allyesconfig    gcc-16.1.0
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260624    gcc-15.2.0
arc                   randconfig-001-20260624    gcc-9.5.0
arc                   randconfig-002-20260624    gcc-15.2.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-16.1.0
arm                              allyesconfig    clang-23
arm                              allyesconfig    gcc-16.1.0
arm                                 defconfig    clang-23
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260624    clang-19
arm                   randconfig-001-20260624    gcc-15.2.0
arm                   randconfig-002-20260624    gcc-15.2.0
arm                   randconfig-002-20260624    gcc-8.5.0
arm                   randconfig-003-20260624    gcc-15.2.0
arm                   randconfig-004-20260624    clang-16
arm                   randconfig-004-20260624    gcc-15.2.0
arm                           sama5_defconfig    gcc-16.1.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                 randconfig-001-20260624    clang-21
arm64                 randconfig-002-20260624    clang-21
arm64                 randconfig-003-20260624    clang-21
arm64                 randconfig-004-20260624    clang-21
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                  randconfig-001-20260624    clang-21
csky                  randconfig-002-20260624    clang-21
hexagon                          allmodconfig    clang-23
hexagon                          allmodconfig    gcc-16.1.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-16.1.0
hexagon                             defconfig    clang-23
hexagon                             defconfig    gcc-16.1.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260624    clang-20
hexagon               randconfig-001-20260624    gcc-11.5.0
hexagon               randconfig-001-20260624    gcc-9.5.0
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260624    clang-23
hexagon               randconfig-002-20260624    gcc-11.5.0
hexagon               randconfig-002-20260624    gcc-9.5.0
i386                             allmodconfig    clang-22
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-16.1.0
i386                             allyesconfig    clang-22
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260624    gcc-12
i386        buildonly-randconfig-001-20260624    gcc-14
i386        buildonly-randconfig-002-20260624    gcc-12
i386        buildonly-randconfig-002-20260624    gcc-14
i386        buildonly-randconfig-003-20260624    gcc-12
i386        buildonly-randconfig-004-20260624    gcc-12
i386        buildonly-randconfig-004-20260624    gcc-14
i386        buildonly-randconfig-005-20260624    gcc-12
i386        buildonly-randconfig-005-20260624    gcc-14
i386        buildonly-randconfig-006-20260624    gcc-12
i386        buildonly-randconfig-006-20260624    gcc-14
i386                                defconfig    clang-22
i386                                defconfig    gcc-16.1.0
i386                  randconfig-001-20260624    clang-22
i386                  randconfig-002-20260624    clang-22
i386                  randconfig-003-20260624    clang-22
i386                  randconfig-004-20260624    clang-22
i386                  randconfig-005-20260624    clang-22
i386                  randconfig-006-20260624    clang-22
i386                  randconfig-007-20260624    clang-22
i386                  randconfig-011-20260624    clang-22
i386                  randconfig-012-20260624    clang-22
i386                  randconfig-012-20260624    gcc-14
i386                  randconfig-013-20260624    clang-22
i386                  randconfig-014-20260624    clang-22
i386                  randconfig-015-20260624    clang-22
i386                  randconfig-015-20260624    gcc-14
i386                  randconfig-016-20260624    clang-22
i386                  randconfig-017-20260624    clang-22
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-20
loongarch                         allnoconfig    gcc-16.1.0
loongarch                           defconfig    clang-23
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260624    gcc-11.5.0
loongarch             randconfig-001-20260624    gcc-16.1.0
loongarch             randconfig-001-20260624    gcc-9.5.0
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260624    gcc-11.5.0
loongarch             randconfig-002-20260624    gcc-15.2.0
loongarch             randconfig-002-20260624    gcc-9.5.0
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    clang-23
m68k                             allyesconfig    gcc-16.1.0
m68k                                defconfig    clang-23
m68k                        stmark2_defconfig    gcc-16.1.0
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
nios2                            allmodconfig    clang-20
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-23
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260624    gcc-11.5.0
nios2                 randconfig-001-20260624    gcc-9.5.0
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260624    gcc-11.5.0
nios2                 randconfig-002-20260624    gcc-9.5.0
openrisc                         allmodconfig    clang-20
openrisc                         allmodconfig    gcc-16.1.0
openrisc                          allnoconfig    clang-23
openrisc                          allnoconfig    gcc-16.1.0
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    clang-23
parisc                            allnoconfig    gcc-16.1.0
parisc                           allyesconfig    clang-17
parisc                           allyesconfig    gcc-16.1.0
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260624    gcc-16.1.0
parisc                randconfig-002-20260624    gcc-14.3.0
parisc                randconfig-002-20260624    gcc-16.1.0
parisc64                            defconfig    clang-23
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    clang-23
powerpc                           allnoconfig    gcc-16.1.0
powerpc                     asp8347_defconfig    clang-23
powerpc                        fsp2_defconfig    gcc-16.1.0
powerpc               randconfig-001-20260624    clang-23
powerpc               randconfig-001-20260624    gcc-16.1.0
powerpc               randconfig-002-20260624    gcc-16.1.0
powerpc               randconfig-002-20260624    gcc-8.5.0
powerpc64             randconfig-001-20260624    gcc-16.1.0
powerpc64             randconfig-001-20260624    gcc-8.5.0
powerpc64             randconfig-002-20260624    gcc-11.5.0
powerpc64             randconfig-002-20260624    gcc-16.1.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                             allnoconfig    gcc-16.1.0
riscv                            allyesconfig    clang-23
riscv                               defconfig    clang-23
riscv                               defconfig    gcc-16.1.0
riscv                          randconfig-001    clang-18
riscv                 randconfig-001-20260624    clang-18
riscv                          randconfig-002    clang-18
riscv                 randconfig-002-20260624    clang-18
s390                             allmodconfig    clang-17
s390                             allmodconfig    clang-23
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    clang-18
s390                                defconfig    gcc-16.1.0
s390                           randconfig-001    clang-18
s390                  randconfig-001-20260624    clang-18
s390                           randconfig-002    clang-18
s390                  randconfig-002-20260624    clang-18
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    clang-23
sh                                allnoconfig    gcc-16.1.0
sh                               allyesconfig    clang-17
sh                               allyesconfig    gcc-16.1.0
sh                                  defconfig    gcc-14
sh                             randconfig-001    clang-18
sh                    randconfig-001-20260624    clang-18
sh                             randconfig-002    clang-18
sh                    randconfig-002-20260624    clang-18
sparc                             allnoconfig    clang-23
sparc                             allnoconfig    gcc-16.1.0
sparc                               defconfig    gcc-16.1.0
sparc                 randconfig-001-20260624    gcc-14.3.0
sparc                 randconfig-001-20260624    gcc-8.5.0
sparc                 randconfig-002-20260624    gcc-14.3.0
sparc                 randconfig-002-20260624    gcc-8.5.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260624    clang-20
sparc64               randconfig-001-20260624    gcc-14.3.0
sparc64               randconfig-002-20260624    clang-20
sparc64               randconfig-002-20260624    gcc-14.3.0
um                               allmodconfig    clang-17
um                               allmodconfig    clang-23
um                                allnoconfig    clang-16
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-16.1.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260624    clang-23
um                    randconfig-001-20260624    gcc-14.3.0
um                    randconfig-002-20260624    clang-16
um                    randconfig-002-20260624    gcc-14.3.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-22
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-22
x86_64      buildonly-randconfig-001-20260624    clang-22
x86_64      buildonly-randconfig-002-20260624    clang-22
x86_64      buildonly-randconfig-003-20260624    clang-22
x86_64      buildonly-randconfig-004-20260624    clang-22
x86_64      buildonly-randconfig-005-20260624    clang-22
x86_64      buildonly-randconfig-006-20260624    clang-22
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                         randconfig-001    clang-22
x86_64                randconfig-001-20260624    clang-22
x86_64                         randconfig-002    clang-22
x86_64                randconfig-002-20260624    clang-22
x86_64                         randconfig-003    clang-22
x86_64                randconfig-003-20260624    clang-22
x86_64                         randconfig-004    clang-22
x86_64                randconfig-004-20260624    clang-22
x86_64                         randconfig-005    clang-22
x86_64                randconfig-005-20260624    clang-22
x86_64                         randconfig-006    clang-22
x86_64                randconfig-006-20260624    clang-22
x86_64                randconfig-011-20260624    gcc-14
x86_64                randconfig-012-20260624    gcc-14
x86_64                randconfig-013-20260624    gcc-14
x86_64                randconfig-014-20260624    gcc-14
x86_64                randconfig-015-20260624    gcc-14
x86_64                randconfig-016-20260624    gcc-14
x86_64                randconfig-071-20260624    gcc-14
x86_64                randconfig-072-20260624    clang-22
x86_64                randconfig-072-20260624    gcc-14
x86_64                randconfig-073-20260624    gcc-14
x86_64                randconfig-074-20260624    clang-22
x86_64                randconfig-074-20260624    gcc-14
x86_64                randconfig-075-20260624    gcc-14
x86_64                randconfig-076-20260624    clang-22
x86_64                randconfig-076-20260624    gcc-14
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    clang-23
xtensa                            allnoconfig    gcc-16.1.0
xtensa                           allyesconfig    clang-20
xtensa                randconfig-001-20260624    gcc-14.3.0
xtensa                randconfig-002-20260624    gcc-14.3.0
xtensa                randconfig-002-20260624    gcc-16.1.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [dtor-input:for-linus] BUILD SUCCESS 7a0e692a0381254b2f77c54dec100cd3325a6fdf
From: kernel test robot @ 2026-06-24  4:40 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: 7a0e692a0381254b2f77c54dec100cd3325a6fdf  Merge branch 'next' into for-linus

elapsed time: 722m

configs tested: 195
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-16.1.0
alpha                            allyesconfig    gcc-16.1.0
alpha                               defconfig    gcc-16.1.0
arc                              allmodconfig    clang-23
arc                               allnoconfig    gcc-16.1.0
arc                              allyesconfig    clang-23
arc                                 defconfig    gcc-16.1.0
arc                   randconfig-001-20260624    gcc-15.2.0
arc                   randconfig-002-20260624    gcc-15.2.0
arm                               allnoconfig    gcc-16.1.0
arm                              allyesconfig    clang-23
arm                                 defconfig    gcc-16.1.0
arm                   randconfig-001-20260624    gcc-15.2.0
arm                   randconfig-002-20260624    gcc-15.2.0
arm                   randconfig-003-20260624    gcc-15.2.0
arm                   randconfig-004-20260624    gcc-15.2.0
arm                           sama5_defconfig    gcc-16.1.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-16.1.0
arm64                               defconfig    gcc-16.1.0
arm64                 randconfig-001-20260624    clang-21
arm64                 randconfig-002-20260624    clang-21
arm64                 randconfig-003-20260624    clang-21
arm64                 randconfig-004-20260624    clang-21
csky                             allmodconfig    gcc-16.1.0
csky                              allnoconfig    gcc-16.1.0
csky                                defconfig    gcc-16.1.0
csky                  randconfig-001-20260624    clang-21
csky                  randconfig-002-20260624    clang-21
hexagon                          allmodconfig    gcc-16.1.0
hexagon                           allnoconfig    gcc-16.1.0
hexagon                             defconfig    gcc-16.1.0
hexagon                        randconfig-001    gcc-11.5.0
hexagon               randconfig-001-20260624    gcc-11.5.0
hexagon               randconfig-001-20260624    gcc-9.5.0
hexagon                        randconfig-002    gcc-11.5.0
hexagon               randconfig-002-20260624    gcc-11.5.0
hexagon               randconfig-002-20260624    gcc-9.5.0
i386                             allmodconfig    clang-22
i386                              allnoconfig    gcc-16.1.0
i386                             allyesconfig    clang-22
i386        buildonly-randconfig-001-20260624    gcc-12
i386        buildonly-randconfig-002-20260624    gcc-12
i386        buildonly-randconfig-003-20260624    gcc-12
i386        buildonly-randconfig-004-20260624    gcc-12
i386        buildonly-randconfig-005-20260624    gcc-12
i386        buildonly-randconfig-006-20260624    gcc-12
i386                                defconfig    gcc-16.1.0
i386                  randconfig-001-20260624    clang-22
i386                  randconfig-002-20260624    clang-22
i386                  randconfig-003-20260624    clang-22
i386                  randconfig-004-20260624    clang-22
i386                  randconfig-005-20260624    clang-22
i386                  randconfig-006-20260624    clang-22
i386                  randconfig-007-20260624    clang-22
i386                  randconfig-011-20260624    clang-22
i386                  randconfig-012-20260624    clang-22
i386                  randconfig-013-20260624    clang-22
i386                  randconfig-014-20260624    clang-22
i386                  randconfig-015-20260624    clang-22
i386                  randconfig-016-20260624    clang-22
i386                  randconfig-017-20260624    clang-22
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    gcc-16.1.0
loongarch                           defconfig    clang-23
loongarch                      randconfig-001    gcc-11.5.0
loongarch             randconfig-001-20260624    gcc-11.5.0
loongarch             randconfig-001-20260624    gcc-9.5.0
loongarch                      randconfig-002    gcc-11.5.0
loongarch             randconfig-002-20260624    gcc-11.5.0
loongarch             randconfig-002-20260624    gcc-9.5.0
m68k                             allmodconfig    gcc-16.1.0
m68k                              allnoconfig    gcc-16.1.0
m68k                             allyesconfig    clang-23
m68k                                defconfig    clang-23
m68k                        stmark2_defconfig    gcc-16.1.0
microblaze                        allnoconfig    gcc-16.1.0
microblaze                       allyesconfig    gcc-16.1.0
microblaze                          defconfig    clang-23
mips                             allmodconfig    gcc-16.1.0
mips                              allnoconfig    gcc-16.1.0
mips                             allyesconfig    gcc-16.1.0
nios2                            allmodconfig    clang-20
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-23
nios2                          randconfig-001    gcc-11.5.0
nios2                 randconfig-001-20260624    gcc-11.5.0
nios2                 randconfig-001-20260624    gcc-9.5.0
nios2                          randconfig-002    gcc-11.5.0
nios2                 randconfig-002-20260624    gcc-11.5.0
nios2                 randconfig-002-20260624    gcc-9.5.0
openrisc                         allmodconfig    clang-20
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-16.1.0
parisc                           allmodconfig    gcc-16.1.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-17
parisc                              defconfig    gcc-16.1.0
parisc                randconfig-001-20260624    gcc-16.1.0
parisc                randconfig-002-20260624    gcc-16.1.0
parisc64                            defconfig    clang-23
powerpc                          allmodconfig    gcc-16.1.0
powerpc                           allnoconfig    clang-23
powerpc                     asp8347_defconfig    clang-23
powerpc                        fsp2_defconfig    gcc-16.1.0
powerpc               randconfig-001-20260624    gcc-16.1.0
powerpc               randconfig-002-20260624    gcc-16.1.0
powerpc64             randconfig-001-20260624    gcc-16.1.0
powerpc64             randconfig-002-20260624    gcc-16.1.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-23
riscv                               defconfig    gcc-16.1.0
riscv                          randconfig-001    clang-18
riscv                 randconfig-001-20260624    clang-18
riscv                          randconfig-002    clang-18
riscv                 randconfig-002-20260624    clang-18
s390                             allmodconfig    clang-17
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-16.1.0
s390                                defconfig    gcc-16.1.0
s390                           randconfig-001    clang-18
s390                  randconfig-001-20260624    clang-18
s390                           randconfig-002    clang-18
s390                  randconfig-002-20260624    clang-18
sh                               allmodconfig    gcc-16.1.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-17
sh                                  defconfig    gcc-14
sh                             randconfig-001    clang-18
sh                    randconfig-001-20260624    clang-18
sh                             randconfig-002    clang-18
sh                    randconfig-002-20260624    clang-18
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-16.1.0
sparc                 randconfig-001-20260624    gcc-14.3.0
sparc                 randconfig-002-20260624    gcc-14.3.0
sparc64                          allmodconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260624    gcc-14.3.0
sparc64               randconfig-002-20260624    gcc-14.3.0
um                               allmodconfig    clang-17
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-16.1.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260624    gcc-14.3.0
um                    randconfig-002-20260624    gcc-14.3.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-22
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-22
x86_64      buildonly-randconfig-001-20260624    clang-22
x86_64      buildonly-randconfig-002-20260624    clang-22
x86_64      buildonly-randconfig-003-20260624    clang-22
x86_64      buildonly-randconfig-004-20260624    clang-22
x86_64      buildonly-randconfig-005-20260624    clang-22
x86_64      buildonly-randconfig-006-20260624    clang-22
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-22
x86_64                         randconfig-001    clang-22
x86_64                randconfig-001-20260624    clang-22
x86_64                         randconfig-002    clang-22
x86_64                randconfig-002-20260624    clang-22
x86_64                         randconfig-003    clang-22
x86_64                randconfig-003-20260624    clang-22
x86_64                         randconfig-004    clang-22
x86_64                randconfig-004-20260624    clang-22
x86_64                         randconfig-005    clang-22
x86_64                randconfig-005-20260624    clang-22
x86_64                         randconfig-006    clang-22
x86_64                randconfig-006-20260624    clang-22
x86_64                randconfig-011-20260624    gcc-14
x86_64                randconfig-012-20260624    gcc-14
x86_64                randconfig-013-20260624    gcc-14
x86_64                randconfig-014-20260624    gcc-14
x86_64                randconfig-015-20260624    gcc-14
x86_64                randconfig-016-20260624    gcc-14
x86_64                randconfig-071-20260624    gcc-14
x86_64                randconfig-072-20260624    gcc-14
x86_64                randconfig-073-20260624    gcc-14
x86_64                randconfig-074-20260624    gcc-14
x86_64                randconfig-075-20260624    gcc-14
x86_64                randconfig-076-20260624    gcc-14
x86_64                               rhel-9.4    clang-22
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-22
x86_64                    rhel-9.4-kselftests    clang-22
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-22
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-20
xtensa                randconfig-001-20260624    gcc-14.3.0
xtensa                randconfig-002-20260624    gcc-14.3.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH v2 2/2] arm64: dts: qcom: sdm845-oneplus: Update compatible to include model
From: Dmitry Torokhov @ 2026-06-24  4:28 UTC (permalink / raw)
  To: David Heidelberg
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Jason A. Donenfeld, Matthias Schiffer, Vincent Huang,
	Bjorn Andersson, Konrad Dybcio, linux-input, devicetree,
	linux-kernel, linux-arm-msm, phone-devel, Krzysztof Kozlowski,
	Konrad Dybcio
In-Reply-To: <742c7a13-9465-40e8-8990-e679712e9784@ixit.cz>

Hi David,

On Sun, Jun 21, 2026 at 07:11:45PM +0200, David Heidelberg wrote:
> On 28/05/2026 00:13, David Heidelberg wrote:
> > On 27/05/2026 23:56, Dmitry Torokhov wrote:
> > > Hi David,
> > > 
> > > On Sat, May 23, 2026 at 11:45:35AM +0200, David Heidelberg via B4 Relay wrote:
> > > > From: David Heidelberg <david@ixit.cz>
> > > > 
> > > > We know the driver is reporting s3706b, introduce the compatible so we
> > > > can more easily introduce quirks for weird touchscreen replacements in
> > > > followup series.
> > > > 
> > > > Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
> > > > Signed-off-by: David Heidelberg <david@ixit.cz>
> > > > ---
> > > >   arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi | 2 +-
> > > >   1 file changed, 1 insertion(+), 1 deletion(-)
> > > > 
> > > > diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> > > > b/arch/ arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> > > > index 6b7378cf4d493..148164d456a5a 100644
> > > > --- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> > > > +++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
> > > > @@ -475,17 +475,17 @@ bq27441_fg: bq27441-battery@55 {
> > > >       };
> > > >   };
> > > >   &i2c12 {
> > > >       status = "okay";
> > > >       clock-frequency = <400000>;
> > > >       synaptics-rmi4-i2c@20 {
> > > > -        compatible = "syna,rmi4-i2c";
> > > > +        compatible = "syna,rmi4-s3706b", "syna,rmi4-i2c";
> > > 
> > > So I believe we established that this device (s3706b) does not in fact
> > > implement rmi4 protocol properly. Why do we have "syna,rmi4-i2c" as a
> > > fallback? Shouldn't it be just "syna,rmi4-s3706b"?
> > 
> > The vendor supplies s3706b which does implement the RMI4 properly.
> > 
> > The 3rd party replacement impersonating original parts may not implement
> > it properly, but I don't address this issue in this initial submission.
> > 
> > With this compatible we know which original part is used by the vendor
> > and installed in the phones, so later we can deduct specific sequences
> > for the replacement aftermarket parts to keep phone touchscreen working
> > same as they do on Android without affecting other devices.
> 
> Hello Dmitry.
> 
> May I ask what is currently preventing this series from moving forward?
> 
> The first version was posted in 2023 [1]. I picked it up again in 2025 [2]
> and am now on the 9th iteration (this patchset). At this point, the series
> has been under discussion for well over a year, with relatively little
> feedback and increasingly long gaps between review rounds.
> 
> The current approach is based on the guidance I have received so far,
> including suggestions from the device-tree maintainers. When concerns were
> raised, I tried to address them and rework the series accordingly.
> 
> What I am struggling with is understanding what specific issue still needs
> to be resolved before these patches can be accepted. If there are remaining
> requirements, objections to the approach, or technical concerns that I have
> not addressed, I would appreciate having them stated explicitly so I can
> work on them.
> 
> I also split out the straightforward, self-contained changes in the hope
> that at least those could progress independently while I continued working
> on any follow-up requirements. However, even those patches do not appear to
> be moving forward.
> 
> Could you please clarify what outcome you would like to see from this
> series, and what concrete changes would be required to get it accepted?

I am still confused about how you want to differentiate between the full
RMI4 support vs the OnePlus flavor. The "syna,rmi4-s3706b", as you
mentioned, implements RMI4 protocol properly, so we do not need to
actually have it documented neither in binding nor in DTS.

The issue you have with after-market parts that are not compliant and we
need to figure out how to deal with them. Inside the driver I
essentially need a"incomplete protocol" flag that we can use to
implement additional checks or skip known to be not implemented
functions/queries. In DT we could introduce something like
"oneplus,rmi4-i2c" that is decidedly not compatible with "syna,rmi4-i2c"
and neither one should be a fallback for the other.

This of course needs buy-in from DT maintainers.

Does this make sense?

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH] Input: mtk-pmic-keys: Count available keys during probe instead of pre-counting
From: Dmitry Torokhov @ 2026-06-24  4:14 UTC (permalink / raw)
  To: Rosen Penev
  Cc: linux-input, Matthias Brugger, AngeloGioacchino Del Regno,
	open list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support,
	moderated list:ARM/Mediatek SoC support
In-Reply-To: <20260528235600.312045-1-rosenp@gmail.com>

Hi Rosen,

On Thu, May 28, 2026 at 04:56:00PM -0700, Rosen Penev wrote:
> Replace the separate of_get_available_child_count() pre-count and
> validation step with a single pass through for_each_child_of_node_scoped().
> Skip unavailable child nodes and bail out if more than
> MTK_PMIC_MAX_KEY_COUNT available keys are found. Set nkeys after the
> loop so suspend/resume iterate only over initialized entries.
> 
> Also use a key variable in the loop for clarity.
> 
> Use of_device_get_match_data() to fetch the PMIC key register data directly
> instead of open-coding an of_match_device() lookup.

Please split this out into a separate patch.

> 
> This also lets the driver drop the of_device.h include.
> 
> Assisted-by: OpenCode:BigPickle
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  drivers/input/keyboard/mtk-pmic-keys.c | 53 ++++++++++++--------------
>  1 file changed, 24 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
> index c78d9f6d97c4..e34856693ee2 100644
> --- a/drivers/input/keyboard/mtk-pmic-keys.c
> +++ b/drivers/input/keyboard/mtk-pmic-keys.c
> @@ -16,7 +16,6 @@
>  #include <linux/mfd/mt6397/core.h>
>  #include <linux/mfd/mt6397/registers.h>
>  #include <linux/module.h>
> -#include <linux/of_device.h>
>  #include <linux/of.h>
>  #include <linux/platform_device.h>
>  #include <linux/regmap.h>
> @@ -147,6 +146,7 @@ struct mtk_pmic_keys {
>  	struct input_dev *input_dev;
>  	struct device *dev;
>  	struct regmap *regmap;
> +	unsigned int nkeys;
>  	struct mtk_pmic_keys_info keys[MTK_PMIC_MAX_KEY_COUNT];
>  };
>  
> @@ -267,7 +267,7 @@ static int mtk_pmic_keys_suspend(struct device *dev)
>  	struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
>  	int index;
>  
> -	for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
> +	for (index = 0; index < keys->nkeys; index++) {
>  		if (keys->keys[index].wakeup) {
>  			enable_irq_wake(keys->keys[index].irq);
>  			if (keys->keys[index].irq_r > 0)
> @@ -283,7 +283,7 @@ static int mtk_pmic_keys_resume(struct device *dev)
>  	struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
>  	int index;
>  
> -	for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
> +	for (index = 0; index < keys->nkeys; index++) {
>  		if (keys->keys[index].wakeup) {
>  			disable_irq_wake(keys->keys[index].irq);
>  			if (keys->keys[index].irq_r > 0)
> @@ -325,24 +325,23 @@ MODULE_DEVICE_TABLE(of, of_mtk_pmic_keys_match_tbl);
>  static int mtk_pmic_keys_probe(struct platform_device *pdev)
>  {
>  	int error, index = 0;
> -	unsigned int keycount;
>  	struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent);
>  	struct device_node *node = pdev->dev.of_node;
>  	static const char *const irqnames[] = { "powerkey", "homekey" };
>  	static const char *const irqnames_r[] = { "powerkey_r", "homekey_r" };
>  	struct mtk_pmic_keys *keys;
>  	const struct mtk_pmic_regs *mtk_pmic_regs;
> +	struct mtk_pmic_keys_info *key;
>  	struct input_dev *input_dev;
> -	const struct of_device_id *of_id =
> -		of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
>  
>  	keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
>  	if (!keys)
>  		return -ENOMEM;
> -
>  	keys->dev = &pdev->dev;
>  	keys->regmap = pmic_chip->regmap;
> -	mtk_pmic_regs = of_id->data;
> +	mtk_pmic_regs = of_device_get_match_data(&pdev->dev);
> +	if (!mtk_pmic_regs)
> +		return -EINVAL;
>  
>  	keys->input_dev = input_dev = devm_input_allocate_device(keys->dev);
>  	if (!input_dev) {
> @@ -356,31 +355,26 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
>  	input_dev->id.product = 0x0001;
>  	input_dev->id.version = 0x0001;
>  
> -	keycount = of_get_available_child_count(node);
> -	if (keycount > MTK_PMIC_MAX_KEY_COUNT ||
> -	    keycount > ARRAY_SIZE(irqnames)) {
> -		dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
> -		return -EINVAL;
> -	}
> +	for_each_available_child_of_node_scoped(node, child) {

Let's keep using for_each_child_of_node_scoped() and check
of_device_is_available() inside the loop. This will allow marking a key
as disabled without shifting it's meaning (power key vs home key).

In the rest of the driver we should be able to determine if key is set
up checking for key->irq > 0.

Thanks.

-- 
Dmitry

^ permalink raw reply

* [PATCH] HID: core: Expose id attributes in sysfs
From: Vicki Pfau @ 2026-06-24  2:36 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires, linux-input; +Cc: Vicki Pfau

udev rules for handling input devices generally match on idVendor and
idProduct for USB hidraw or id/vendor and id/product for evdev nodes.
However, hidraw nodes that aren't created by the USB subsystem will only
expose this information to udev via the kernel path itself. This leads to
doing substring matching, which can be error-prone or overzealous. Instead,
since the HID subsystem already has this information, we can expose it
directly in the same format that evdev exposes it.

Signed-off-by: Vicki Pfau <vi@endrift.com>
---
 drivers/hid/hid-core.c | 45 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 41a79e43c82b..397de63297c6 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2900,6 +2900,45 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
 }
 static DEVICE_ATTR_RO(modalias);
 
+/*
+ * Expose this as bustype instead of bus as
+ * that's the name the input subsystem uses
+ */
+static ssize_t bustype_show(struct device *dev, struct device_attribute *a,
+			     char *buf)
+{
+	struct hid_device *hdev = to_hid_device(dev);
+
+	return sysfs_emit(buf, "%04x\n", hdev->bus);
+}
+static DEVICE_ATTR_RO(bustype);
+
+#define HID_DEV_ID_ATTR(name)				\
+static ssize_t name##_show(struct device *dev,		\
+			struct device_attribute *attr,	\
+			char *buf)			\
+{							\
+	struct hid_device *hdev = to_hid_device(dev);	\
+							\
+	return sysfs_emit(buf, "%04x\n", hdev->name);	\
+}							\
+static DEVICE_ATTR_RO(name)
+
+HID_DEV_ID_ATTR(vendor);
+HID_DEV_ID_ATTR(product);
+HID_DEV_ID_ATTR(version);
+
+static struct attribute *hid_dev_id_attrs[] = {
+	&dev_attr_bustype.attr,
+	&dev_attr_vendor.attr,
+	&dev_attr_product.attr,
+	&dev_attr_version.attr,
+	NULL
+};
+static const struct attribute_group hid_dev_id_attr_group = {
+	.name	= "id",
+	.attrs	= hid_dev_id_attrs,
+};
 static struct attribute *hid_dev_attrs[] = {
 	&dev_attr_modalias.attr,
 	NULL,
@@ -2912,7 +2951,11 @@ static const struct attribute_group hid_dev_group = {
 	.attrs = hid_dev_attrs,
 	.bin_attrs = hid_dev_bin_attrs,
 };
-__ATTRIBUTE_GROUPS(hid_dev);
+static const struct attribute_group *hid_dev_groups[] = {
+	&hid_dev_group,
+	&hid_dev_id_attr_group,
+	NULL
+};
 
 static int hid_uevent(const struct device *dev, struct kobj_uevent_env *env)
 {
-- 
2.54.0


^ permalink raw reply related

* [git pull] Input updates for v7.2-rc0
From: Dmitry Torokhov @ 2026-06-24  2:21 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-v7.2-rc0

to receive updates for the input subsystem. You will get:

- A new driver for Wacom W9000-series penabled touchscreens

- Updates to STM FTS driver adding support for reset line and preparing
  the driver for STMFTS5 support
  
- Updates to RMI4 and IMS PCU drivers hardening the code

- Support for half-duplex mode restored in ADS7846 driver

- Updates to driver's device_id tables to use named initializers

- Removal of no longer used PCAP keys and touchscreen drivers (support
  for the ezx series of phones was removed in 2022)

- Removal of xilinx_ps2 driver which is no longer used either

- Updates to userio to allow setting up additional serio port
  characteristics (such as id, extra and proto)

- Assorted hardening and cleanup fixes for other drivers.


Changelog:
---------

Aaro Koskinen (1):
      Input: ads7846 - restore half-duplex support

Arnd Bergmann (2):
      Input: pcap_keys - remove unused driver
      Input: pcap_ts - remove unused driver

Bryam Vargas (4):
      Input: touchwin - reset the packet index on every complete packet
      Input: mms114 - reject an oversized device packet size
      Input: goodix - clamp the device-reported contact count
      Input: iforce - bound the device-reported force-feedback effect index

Colin Ian King (1):
      Input: lm8323 - remove space before newline

David Heidelberg (6):
      Input: stmfts - fix the MODULE_LICENSE() string
      Input: stmfts - use dev struct directly
      Input: stmfts - switch to devm_regulator_bulk_get_const
      Input: stmfts - abstract reading information from the firmware
      Input: stmfts - disable regulators and disable irq when power on fails
      dt-bindings: input: touchscreen: st,stmfts: Introduce reset GPIO

Dmitry Torokhov (40):
      Input: stmfts - fix formatting issues
      Input: atmel_mxt_ts - use __free() for obuf in mxt_object_show
      Input: atlas_btns - modernize the driver
      Input: ims-pcu - only expose sysfs attributes on control interface
      Input: ims-pcu - fix logic error in packet reset
      Input: ims-pcu - release data interface on disconnect
      Input: ims-pcu - fix use-after-free and double-free in disconnect
      Input: ims-pcu - fix type confusion in CDC union descriptor parsing
      Input: ims-pcu - fix firmware leak in async update
      Input: ims-pcu - fix race condition in reset_device sysfs callback
      Input: ims-pcu - validate control endpoint type
      Input: ims-pcu - fix out-of-bounds read in ims_pcu_irq() debug logging
      Input: ims-pcu - fix DMA mapping violation in line setup
      Input: ims-pcu - add response length checks
      Input: ims-pcu - fix potential infinite loop in CDC union descriptor parsing
      Input: ipaq-micro-keys - fix potential deadlock
      Input: ipaq-micro-keys - add length check in micro_key_receive
      Input: rmi4 - fix register descriptor address calculation
      Input: rmi4 - refactor register descriptor parsing
      Input: rmi4 - fix type overflow in register counts
      Input: rmi4 - fix num_subpackets overflow in register descriptor
      Input: rmi4 - initialize attn_fifo properly
      Input: rmi4 - fix memory leak in rmi_set_attn_data()
      Input: rmi4 - iterative IRQ handler
      Input: rmi4 - fix bit count in bitmap_copy()
      Input: rmi4 - fix limit in rmi_register_desc_has_subpacket()
      Input: rmi4 - use local presence map in rmi_read_register_desc()
      Input: rmi4 - refactor function allocation and registration
      Input: rmi4 - use kzalloc_flex() for struct rmi_function
      Input: rmi4 - refactor F12 probe function
      Input: rmi4 - change reg_size type to u32
      Input: rmi4 - use unaligned access helpers in F12
      Input: rmi4 - use flexible array member for IRQ masks in F12
      Input: rmi4 - use devm_kmalloc for F12 data packet buffer
      Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators
      Input: rmi4 - simplify size calculations in F12
      Input: rmi4 - propagate proper error code in F12 sensor tuning
      Input: rmi4 - update formatting in F12
      Input: stop force-feedback timer when unregistering input devices
      Input: mms114 - fix touch indexing for MMS134S and MMS136

Elliot Tester (1):
      Input: remove changelogs

Haoxiang Li (1):
      Input: synaptics-rmi4 - unregister function handlers on physical driver registration failure

Hendrik Noack (2):
      dt-bindings: Input: Add Wacom W9000-series penabled touchscreens
      Input: Add support for Wacom W9000-series penabled touchscreens

Kris Bahnsen (1):
      Input: ads7846 - don't use scratch for tx_buf when clearing register

Petr Hodina (2):
      Input: stmfts - use client to make future code cleaner
      Input: stmfts - add optional reset GPIO support

Ranjan Kumar (1):
      Input: elan_i2c - prevent division by zero and arithmetic underflow

Ricardo Ribalda (1):
      Input: atmel_mxt_ts - set byte_offset as signed

Rosen Penev (3):
      Input: xilinx_ps2 - remove driver
      Input: apbps2 - simplify resource mapping and IRQ retrieval
      Input: ipaq-micro-keys - simplify allocation

Uwe Kleine-König (The Capable Hub) (3):
      Input: Use named initializers for arrays of i2c_device_data
      Input: iqs5xx - drop unused i2c driver_data
      Input: Drop unused assignments from pnp_device_id arrays

Vicki Pfau (2):
      Input: userio - update maintainer name
      Input: userio - allow setting other id values

Yuki Horii (1):
      Input: tsc2007 - reduce I2C transactions for Z2 read

Diffstat:
--------

 .../bindings/input/touchscreen/st,stmfts.yaml      |   4 +
 .../input/touchscreen/wacom,w9007a-lt03.yaml       |  73 ++++
 Documentation/input/userio.rst                     |  25 +-
 MAINTAINERS                                        |   2 +-
 drivers/input/ff-memless.c                         |  27 +-
 drivers/input/gameport/ns558.c                     |  46 +--
 drivers/input/input.c                              |   3 +
 drivers/input/joystick/adafruit-seesaw.c           |   2 +-
 drivers/input/joystick/as5011.c                    |   2 +-
 drivers/input/joystick/iforce/iforce-packets.c     |  18 +-
 drivers/input/joystick/qwiic-joystick.c            |   2 +-
 drivers/input/keyboard/adp5588-keys.c              |   4 +-
 drivers/input/keyboard/cap11xx.c                   |  14 +-
 drivers/input/keyboard/cypress-sf.c                |   2 +-
 drivers/input/keyboard/dlink-dir685-touchkeys.c    |   2 +-
 drivers/input/keyboard/ipaq-micro-keys.c           |  24 +-
 drivers/input/keyboard/lm8323.c                    |   4 +-
 drivers/input/keyboard/lm8333.c                    |   2 +-
 drivers/input/keyboard/max7359_keypad.c            |   2 +-
 drivers/input/keyboard/mpr121_touchkey.c           |   2 +-
 drivers/input/keyboard/qt1070.c                    |   2 +-
 drivers/input/keyboard/qt2160.c                    |   2 +-
 drivers/input/keyboard/tca8418_keypad.c            |   2 +-
 drivers/input/keyboard/tm2-touchkey.c              |   2 +-
 drivers/input/misc/Kconfig                         |  10 -
 drivers/input/misc/Makefile                        |   1 -
 drivers/input/misc/ad714x-i2c.c                    |  10 +-
 drivers/input/misc/adxl34x-i2c.c                   |   2 +-
 drivers/input/misc/apanel.c                        |   2 +-
 drivers/input/misc/atlas_btns.c                    | 109 ++---
 drivers/input/misc/atmel_captouch.c                |   2 +-
 drivers/input/misc/bma150.c                        |   6 +-
 drivers/input/misc/cma3000_d0x_i2c.c               |   2 +-
 drivers/input/misc/da7280.c                        |   2 +-
 drivers/input/misc/drv260x.c                       |   8 +-
 drivers/input/misc/drv2665.c                       |   2 +-
 drivers/input/misc/drv2667.c                       |   2 +-
 drivers/input/misc/ims-pcu.c                       | 131 +++++-
 drivers/input/misc/kxtj9.c                         |   2 +-
 drivers/input/misc/mma8450.c                       |   2 +-
 drivers/input/misc/pcap_keys.c                     | 125 ------
 drivers/input/misc/pcf8574_keypad.c                |   2 +-
 drivers/input/misc/yealink.c                       |   9 -
 drivers/input/mouse/cyapa.c                        |   2 +-
 drivers/input/mouse/elan_i2c_core.c                |  38 +-
 drivers/input/mouse/synaptics_i2c.c                |   2 +-
 drivers/input/rmi4/rmi_2d_sensor.h                 |   4 +-
 drivers/input/rmi4/rmi_bus.c                       |  34 +-
 drivers/input/rmi4/rmi_bus.h                       |   1 +
 drivers/input/rmi4/rmi_driver.c                    | 204 ++++++----
 drivers/input/rmi4/rmi_driver.h                    |  13 +-
 drivers/input/rmi4/rmi_f11.c                       |   2 +-
 drivers/input/rmi4/rmi_f12.c                       | 415 +++++++++----------
 drivers/input/rmi4/rmi_i2c.c                       |   2 +-
 drivers/input/rmi4/rmi_smbus.c                     |   2 +-
 drivers/input/serio/Kconfig                        |  10 -
 drivers/input/serio/Makefile                       |   1 -
 drivers/input/serio/apbps2.c                       |   7 +-
 drivers/input/serio/i8042-acpipnpio.h              |  56 +--
 drivers/input/serio/userio.c                       |  34 +-
 drivers/input/serio/xilinx_ps2.c                   | 363 -----------------
 drivers/input/tablet/aiptek.c                      |  31 --
 drivers/input/touchscreen/Kconfig                  |  22 +-
 drivers/input/touchscreen/Makefile                 |   2 +-
 drivers/input/touchscreen/ad7879-i2c.c             |   4 +-
 drivers/input/touchscreen/ads7846.c                | 173 +++++++-
 drivers/input/touchscreen/ar1021_i2c.c             |   2 +-
 drivers/input/touchscreen/atmel_mxt_ts.c           |  23 +-
 drivers/input/touchscreen/auo-pixcir-ts.c          |   2 +-
 drivers/input/touchscreen/bu21013_ts.c             |   2 +-
 drivers/input/touchscreen/bu21029_ts.c             |   2 +-
 drivers/input/touchscreen/cy8ctma140.c             |   2 +-
 drivers/input/touchscreen/cy8ctmg110_ts.c          |   2 +-
 drivers/input/touchscreen/cyttsp5.c                |   2 +-
 drivers/input/touchscreen/cyttsp_i2c.c             |   2 +-
 drivers/input/touchscreen/eeti_ts.c                |   2 +-
 drivers/input/touchscreen/egalax_ts.c              |   2 +-
 drivers/input/touchscreen/elants_i2c.c             |   6 +-
 drivers/input/touchscreen/exc3000.c                |   8 +-
 drivers/input/touchscreen/goodix.c                 |   5 +-
 drivers/input/touchscreen/hideep.c                 |   2 +-
 drivers/input/touchscreen/himax_hx83112b.c         |   4 +-
 drivers/input/touchscreen/hynitron-cst816x.c       |   2 +-
 drivers/input/touchscreen/ili210x.c                |   8 +-
 drivers/input/touchscreen/ilitek_ts_i2c.c          |   2 +-
 drivers/input/touchscreen/iqs5xx.c                 |   6 +-
 drivers/input/touchscreen/max11801_ts.c            |   2 +-
 drivers/input/touchscreen/melfas_mip4.c            |   2 +-
 drivers/input/touchscreen/migor_ts.c               |   2 +-
 drivers/input/touchscreen/mms114.c                 |  26 +-
 drivers/input/touchscreen/novatek-nvt-ts.c         |   4 +-
 drivers/input/touchscreen/pcap_ts.c                | 252 ------------
 drivers/input/touchscreen/pixcir_i2c_ts.c          |   4 +-
 drivers/input/touchscreen/raydium_i2c_ts.c         |   4 +-
 drivers/input/touchscreen/rohm_bu21023.c           |   2 +-
 drivers/input/touchscreen/s6sy761.c                |   2 +-
 drivers/input/touchscreen/silead.c                 |  12 +-
 drivers/input/touchscreen/sis_i2c.c                |   4 +-
 drivers/input/touchscreen/st1232.c                 |   4 +-
 drivers/input/touchscreen/stmfts.c                 | 162 +++++---
 drivers/input/touchscreen/touchwin.c               |  15 +-
 drivers/input/touchscreen/tsc2004.c                |   2 +-
 drivers/input/touchscreen/tsc2007_core.c           |   8 +-
 drivers/input/touchscreen/wacom_i2c.c              |   2 +-
 drivers/input/touchscreen/wacom_w9000.c            | 444 +++++++++++++++++++++
 drivers/input/touchscreen/wdt87xx_i2c.c            |   2 +-
 drivers/input/touchscreen/zet6223.c                |   2 +-
 drivers/input/touchscreen/zforce_ts.c              |   2 +-
 include/linux/input.h                              |   3 +
 include/uapi/linux/userio.h                        |   7 +-
 110 files changed, 1673 insertions(+), 1501 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/input/touchscreen/wacom,w9007a-lt03.yaml
 delete mode 100644 drivers/input/misc/pcap_keys.c
 delete mode 100644 drivers/input/serio/xilinx_ps2.c
 delete mode 100644 drivers/input/touchscreen/pcap_ts.c
 create mode 100644 drivers/input/touchscreen/wacom_w9000.c

Thanks.


-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v2 0/8] HID: iio: Avoid race between callback setup and device exposure
From: Sanjay Chitroda @ 2026-06-24  1:43 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Jiri Kosina, Jonathan Cameron, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, Archana Patni, Song Hongyan,
	linux-input, linux-iio, linux-kernel, srinivas pandruvada
In-Reply-To: <ajpgQ8vCHacv_klG@ashevche-desk.local>



On 23 June 2026 4:00:27 pm IST, Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
>On Mon, Jun 22, 2026 at 10:59:56AM +0530, Sanjay Chitroda wrote:
>> 
>> This series avoid a race condition in HID IIO drivers related to the
>> ordering between callback registration and device exposure.
>> 
>> Currently, several HID IIO drivers register the IIO device (making it
>> visible to userspace and other kernel consumers) before all required
>> callbacks and resources are fully initialized, or rely on devm-based
>> cleanup in a way that does not guarantee correct teardown ordering.
>> This creates a window where the device can be accessed while it is
>
>There is a difference between "this creates" and "this might create".
>I believe Srinivas and others were asking for the proof. So, what path
>in the code makes this happen or possible to happen?
>
iio_device_register() exposes the IIO device to user space, while sensor_hub_register_callback() registers callbacks for buffered IIO(streaming mode).

This might create window where from userspace buffer mode is enabled and callbacks are not registered which would result into loss of samples until callback registration completes, although no explicit failure. In teardown path which can resulting in stale/no data.

This was discussed in the v1 thread and v2 was posted based on discussion and agreement:
 https://lore.kernel.org/all/3FED088A-651B-4E8B-840B-1B92CB4DF6F4@gmail.com/


>> not fully initialized or is being torn down, potentially leading to
>> sample drop or stale/no data.
>> 
>> To handle this, the series ensures that:
>>   - All required callbacks and resources are set up before the device
>>     is registered with the IIO core
>>   - Resource cleanup is performed explicitly where ordering matters
>> 
>> PS: This is prepratory series to convert all HID IIO driver to devm.
>> 
>> Testing:
>>   - Compiled with W=1 for each patch in series
>> 
>> ---
>> Changes in v2:
>> - Drop fixes tag and rectify commit message with reference to that
>
>You also dropped my tag. Why?
>
Thank you for the review and tag on v1.

While code changes are intact in v2, the rational and commit message were updated substantially. Since commit message is as important as change which will be permanent in history for future reference, I chose to drop the tag to request a fresh review.

I shall highlight the same in change log. I'll make sure to note in future revision.

Thanks, Sanjay

>> - Link to v1: https://patch.msgid.link/20260606-5-june-hid-iio-race-fixes-v1-0-27a848c5758f@gmail.com
>

^ permalink raw reply

* [PATCH v5 5/6] arm64: dts: allwinner: a100: Add LRADC node
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

A100/A133 SoCs feature a Low Rate ADC (LRADC) for Key application.

Specs:
- Power supply voltage: 1.8 V
- Reference voltage: 1.35 V
- Interrupt support
- Support Hold Key and General Key
- Support normal, continue and single work mode
- 6-bits resolution, sample rate up to 2 kHz
- Voltage input range between 0 and 1.35 V

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v5:
- reflowed "compatible" property of lradc node
v4:
- added allwinner,sun50i-a100-lradc compatible
v3:
- new patch

 arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
index b3fb1e0ee796..ba6020989ce9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a100.dtsi
@@ -466,6 +466,16 @@ ths: thermal-sensor@5070400 {
 			#thermal-sensor-cells = <1>;
 		};
 
+		lradc: lradc@5070800 {
+			compatible = "allwinner,sun50i-a100-lradc",
+				     "allwinner,sun50i-r329-lradc";
+			reg = <0x05070800 0x400>;
+			interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_LRADC>;
+			resets = <&ccu RST_BUS_LRADC>;
+			status = "disabled";
+		};
+
 		usb_otg: usb@5100000 {
 			compatible = "allwinner,sun50i-a100-musb",
 				     "allwinner,sun8i-a33-musb";
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 6/6] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

Baijie Helper A133 board is a development board around Baijie A133 Core
SBC. Features:

- 1/2/4GiB LPDDR4 DRAM
- 8/16/32GiB eMMC
- AXP707 PMIC
- USB-C OTG port in peripheral mode (via onboard hub)
- 2 USB 2.0 ports
- MicroSD slot and on-board eMMC module
- Gigabit Ethernet
- Bluetooth
- WiFi

Add initial support for both the Helper and Core boards, including UART,
PMU, eMMC, USB, Ethernet, LRADC-connected buttons.

UART1 can only be used for Bluetooth module, but BT-WiFi combo Allwinner
AW869A chip has no mainline driver currently.

Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v5:
- no changes
v4:
- renamed "sun50i-a133-baijie-helper.dtb" -> "sun50i-a133-helperboard.dtb"
- added "model" property into root of sun50i-a133-helperboard-core.dtsi
- added "cap-mmc-highspeed" and "max-frequency" into &mmc2
- added "x-powers,drive-vbus-en" and "*-supply" into &axp803
- dropped all "regulator-enable-ramp-delay" properties
- replaced &reg_dcdc3 with a "polyphased" comment
- exact DRAM voltage in &reg_dcdc5
- disabled &reg_dcdc6 to avoid "[   31.710641] dcdc6: disabling"
- added &reg_vdd5v "root" regulator
- added "disable-wp" into &mmc0
- commented &usb_otg
- assigned usb1_vbus-supply in &usbphy
v3:
- added my copyrights into the newly introduced DTs
- all DT nodes sorted alphabetically
- all always-on regulators commented/propetly named
- all regulators got proper voltages (not default ranges)
- ADC-sensed buttons K1..K5 added
- re-labelled "eth_phy" -> "rgmii_phy"
- usbphy 0 switched from host into peripheral mode (downstream from an
  onboard hub)
- typo sun50i-a133-baije-core.dtsi -> sun50i-a133-baijie-core.dtsi
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board

 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../sun50i-a133-helperboard-core.dtsi         | 197 ++++++++++++++++++
 .../dts/allwinner/sun50i-a133-helperboard.dts | 148 +++++++++++++
 3 files changed, 346 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts

diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 53e6b701e7d3..aa21f58a4be1 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -24,6 +24,7 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h64-remix-mini-pc.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a100-allwinner-perf1.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-helperboard.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a133-liontron-h-a133l.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-bananapi-m2-plus-v1.2.dtb
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
new file mode 100644
index 000000000000..545972d2324a
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Arm Ltd.
+ * Copyright (c) 2026 Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a100.dtsi"
+#include "sun50i-a100-cpu-opp.dtsi"
+
+/{
+	model = "Baijie A133 HelperBoard Core";
+	compatible = "baijie,helperboard-a133-core",
+		     "allwinner,sun50i-a100";
+
+	aliases {
+		serial1 = &uart1;	/* BT module */
+	};
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&lradc {
+	vref-supply = <&reg_aldo1>;
+};
+
+&mmc2 {
+	vmmc-supply = <&reg_dcdc1>;
+	vqmmc-supply = <&reg_eldo1>;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	max-frequency = <100000000>;
+	non-removable;
+	bus-width = <8>;
+	mmc-ddr-1_8v;
+	mmc-hs200-1_8v;
+	status = "okay";
+};
+
+&pio {
+	vcc-pb-supply = <&reg_dcdc1>;
+	vcc-pc-supply = <&reg_eldo1>;
+	vcc-pd-supply = <&reg_dcdc1>;
+	vcc-pe-supply = <&reg_dldo2>;
+	vcc-pf-supply = <&reg_dcdc1>;
+	vcc-pg-supply = <&reg_dldo1>;
+	vcc-ph-supply = <&reg_dcdc1>;
+	/*
+	 * PL0/PL1 are the I2C connection to PMIC, but it would create a
+	 * circular dependency:
+	 * vcc-pl-supply = <&reg_aldo3>;
+	 */
+};
+
+&r_i2c0 {
+	status = "okay";
+
+	axp803: pmic@34 {
+		compatible = "x-powers,axp803";
+		reg = <0x34>;
+		interrupt-parent = <&r_intc>;
+		interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+		x-powers,drive-vbus-en;		/* set N_VBUSEN as output pin */
+		aldoin-supply = <&reg_vdd5v>;
+		dldoin-supply = <&reg_vdd5v>;
+		eldoin-supply = <&reg_vdd5v>;
+		fldoin-supply = <&reg_dcdc5>;
+		vin1-supply = <&reg_vdd5v>;
+		vin2-supply = <&reg_vdd5v>;
+		vin3-supply = <&reg_vdd5v>;
+		vin4-supply = <&reg_vdd5v>;
+		vin5-supply = <&reg_vdd5v>;
+		vin6-supply = <&reg_vdd5v>;
+		drivevbus-supply = <&reg_vdd5v>;
+	};
+};
+
+#include "axp803.dtsi"
+
+&ac_power_supply {
+	status = "okay";
+};
+
+&reg_aldo1 {
+	/* PLL + LRADC analog reference */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pll";
+};
+
+&reg_aldo2 {
+	/* LPDDR */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vdd18-lpddr";
+};
+
+&reg_aldo3 {
+	/*
+	 * Port L, but linking it to &pio node would create a circular
+	 * dependency because of PL0/PL1 I2C connection to PMIC
+	 */
+	regulator-always-on;
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pl";
+};
+
+&reg_dcdc1 {
+	/* Besides Port D it also powers analog part of USB IP and SoC I/O */
+	regulator-always-on;
+	regulator-min-microvolt = <3300000>;
+	regulator-max-microvolt = <3300000>;
+	regulator-name = "vcc-3v3";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <810000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "vdd-cpu";
+};
+
+/* DCDC3 is polyphased with DCDC2 */
+
+&reg_dcdc4 {
+	/* Digital part of USB IP, "System" SoC power rail */
+	regulator-always-on;
+	regulator-min-microvolt = <950000>;
+	regulator-max-microvolt = <950000>;
+	regulator-name = "vdd-sys";
+};
+
+&reg_dcdc5 {
+	regulator-always-on;
+	regulator-min-microvolt = <1100000>;
+	regulator-max-microvolt = <1100000>;
+	regulator-name = "vcc-dram";
+};
+
+/* DCDC6 unused */
+&reg_dcdc6 {
+	status = "disabled";
+};
+
+&reg_dldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pg";
+};
+
+&reg_dldo2 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pe";
+};
+
+&reg_dldo3 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "avdd-csi";
+};
+
+&reg_dldo4 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	regulator-name = "afvcc-csi";
+};
+
+&reg_eldo1 {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-name = "vcc-pc";
+};
+
+&reg_eldo2 {
+	regulator-min-microvolt = <1200000>;
+	regulator-max-microvolt = <1200000>;
+	regulator-name = "dvdd-csi";
+};
+
+/* ELDO3 unused */
+
+&reg_fldo1 {
+	/* CPUS power rail */
+	regulator-always-on;
+	regulator-min-microvolt = <900000>;
+	regulator-max-microvolt = <900000>;
+	regulator-name = "vdd-cpus";
+};
+
+/* reg_drivevbus unused */
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts
new file mode 100644
index 000000000000..694c0cacf906
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2025 Arm Ltd.
+ * Copyright (c) 2026 Alexander Sverdlin <alexander.sverdlin@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sun50i-a133-helperboard-core.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+
+/{
+	model = "Baijie HelperBoard A133";
+	compatible = "baijie,helperboard-a133",
+		     "baijie,helperboard-a133-core",
+		     "allwinner,sun50i-a100";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led {
+			function = LED_FUNCTION_INDICATOR;
+			color = <LED_COLOR_ID_GREEN>;
+			gpios = <&pio 7 13 GPIO_ACTIVE_LOW>;	/* PH13 */
+		};
+	};
+
+	reg_vdd5v: vdd5v {
+		/* board wide 5V supply from a 12V->5V regulator */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd-5v";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&emac0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii0_pins>;
+	phy-handle = <&rgmii_phy>;
+	phy-mode = "rgmii-id";
+	allwinner,rx-delay-ps = <200>;
+	allwinner,tx-delay-ps = <200>;
+	status = "okay";
+};
+
+&lradc {
+	wakeup-source;
+	status = "okay";
+
+	button-115 {
+		label = "K1";
+		linux,code = <KEY_1>;
+		channel = <0>;
+		voltage = <114607>;
+	};
+
+	button-235 {
+		label = "K2";
+		linux,code = <KEY_2>;
+		channel = <0>;
+		voltage = <234783>;
+	};
+
+	button-360 {
+		label = "K3";
+		linux,code = <KEY_3>;
+		channel = <0>;
+		voltage = <360000>;
+	};
+
+	button-476 {
+		label = "K4";
+		linux,code = <KEY_4>;
+		channel = <0>;
+		voltage = <476471>;
+	};
+
+	button-592 {
+		label = "K5";
+		linux,code = <KEY_5>;
+		channel = <0>;
+		voltage = <591946>;
+	};
+};
+
+&mdio0 {
+	reset-gpios = <&pio 7 11 GPIO_ACTIVE_LOW>;	/* PH11 */
+	reset-delay-us = <10000>;
+	reset-post-delay-us = <150000>;
+
+	rgmii_phy: ethernet-phy@1 {
+		compatible = "ethernet-phy-ieee802.3-c22";
+		reg = <1>;
+	};
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_dcdc1>;
+	cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>;	/* PF6 */
+	bus-width = <4>;
+	disable-wp;
+	status = "okay";
+};
+
+&ohci1 {
+	status = "okay";
+};
+
+&rgmii0_pins {
+	drive-strength = <30>;
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	/*
+	 * Connected to a downstream port of an onboard hub, therefore only
+	 * "peripheral" mode will work here.
+	 */
+	dr_mode = "peripheral";
+	status = "okay";
+};
+
+&usbphy {
+	usb1_vbus-supply = <&reg_vdd5v>;
+	status = "okay";
+};
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 4/6] dt-bindings: input: sun4i-lradc-keys: Add A100/A133 compatible
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

The Allwinner A100/A133 SoCs have an LRADC which is compatible with the
versions in existing SoCs. Add a compatible string for A100, with the R329
fallback.

Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v5:
- no changes
v4:
- new patch

 .../bindings/input/allwinner,sun4i-a10-lradc-keys.yaml           | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
index 6bdb8040be65..524c8b51f53f 100644
--- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
+++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
@@ -23,6 +23,7 @@ properties:
       - const: allwinner,sun50i-r329-lradc
       - items:
           - enum:
+              - allwinner,sun50i-a100-lradc
               - allwinner,sun50i-h616-lradc
               - allwinner,sun20i-d1-lradc
           - const: allwinner,sun50i-r329-lradc
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 3/6] dt-bindings: arm: sunxi: Add Baijie HelperBoard A133 compatible
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input, Conor Dooley
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

Baijie HelperBoard A133 is a development board around their A133 Core
board. Introduce a compatible for both the Core and the development
boards.

Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v5:
- no changes
v4:
- renamed "Baijie Helper A133" -> "Baijie A133 HelperBoard"
- renamed "baijie,helper-a133" -> "baijie,helperboard-a133"
v3:
- no separate section for "core" .dtsi
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board

 Documentation/devicetree/bindings/arm/sunxi.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/sunxi.yaml b/Documentation/devicetree/bindings/arm/sunxi.yaml
index e6443c266fa1..82dd58b95f8a 100644
--- a/Documentation/devicetree/bindings/arm/sunxi.yaml
+++ b/Documentation/devicetree/bindings/arm/sunxi.yaml
@@ -96,6 +96,12 @@ properties:
           - const: allwinner,ba10-tvbox
           - const: allwinner,sun4i-a10
 
+      - description: Baijie A133 HelperBoard
+        items:
+          - const: baijie,helperboard-a133
+          - const: baijie,helperboard-a133-core
+          - const: allwinner,sun50i-a100
+
       - description: BananaPi
         items:
           - const: lemaker,bananapi
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 2/6] dt-bindings: vendor-prefixes: Add Shenzhen Baijie Technology Co., Ltd.
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input, Conor Dooley, Paul Kocialkowski
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

Shenzhen Baijie Technology Co., Ltd. focuses on R&D and production of
embedded products as well as customization of embedded solutions.

Link: https://szbaijie.com/
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v2-v5:
- no changes

 Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 6b9fb6a6bf0b..88225786e216 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -229,6 +229,8 @@ patternProperties:
     description: Azoteq (Pty) Ltd
   "^azw,.*":
     description: Shenzhen AZW Technology Co., Ltd.
+  "^baijie,.*":
+    description: Shenzhen Baijie Technology Co., Ltd.
   "^baikal,.*":
     description: BAIKAL ELECTRONICS, JSC
   "^bananapi,.*":
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 1/6] arm64: defconfig: Enable Allwinner LRADC input driver
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input
In-Reply-To: <20260623204824.691832-1-alexander.sverdlin@gmail.com>

Enable Allwinner LRADC input driver as module to support buttons on Baijie
HelperBoard A133.

Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@gmail.com>
---
Changelog:
v4-v5:
- no changes
v3:
- new patch

 arch/arm64/configs/defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 654a102cb5bc..c267f0906460 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -527,6 +527,7 @@ CONFIG_KEYBOARD_GPIO=y
 CONFIG_KEYBOARD_GPIO_POLLED=m
 CONFIG_KEYBOARD_SNVS_PWRKEY=m
 CONFIG_KEYBOARD_IMX_SC_KEY=m
+CONFIG_KEYBOARD_SUN4I_LRADC=m
 CONFIG_KEYBOARD_CROS_EC=y
 CONFIG_KEYBOARD_MTK_PMIC=m
 CONFIG_MOUSE_ELAN_I2C=m
-- 
2.54.0


^ permalink raw reply related

* [PATCH v5 0/6] Add support for Baijie Helper A133 board
From: Alexander Sverdlin @ 2026-06-23 20:48 UTC (permalink / raw)
  To: linux-arm-kernel, linux-sunxi
  Cc: Alexander Sverdlin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland,
	Hans de Goede, Dmitry Torokhov, Andre Przywara, Jun Yan,
	Lukas Schmid, J. Neuschäfer, Eric Biggers, Michal Simek,
	Luca Weiss, Sven Peter, Maxime Ripard, devicetree, linux-kernel,
	linux-input

Baijie Helper A133 board is a development board around Baijie A133 Core
SBC. Features:

- 1/2/4GiB LPDDR4 DRAM
- 8/16/32GiB eMMC
- AXP707 PMIC
- USB-C OTG port in peripheral mode (via onboard hub)
- 2 USB 2.0 ports
- MicroSD slot and on-board eMMC module
- Gigabit Ethernet
- Bluetooth
- WiFi

Add initial support for both the Helper and Core boards, including UART,
PMU, eMMC, USB, Ethernet, LRADC-connected buttons.

UART1 can only be used for Bluetooth module, but BT-WiFi combo Allwinner
AW869A chip has not mainline driver currently.

Link: https://szbaijie.com/index/product/product_detail.html?product_id=23&language=en

Changelog:
v5:
- sun50i-a100.dtsi: reflowed "compatible" property of lradc node
- dropped "reserve RAM for ATF" patch [v4 6/7]
v4:
- reserve RAM for ATF
- sun4i-lradc-keys: Add A100/A133 compatible
- dt-bindings: renamed "Baijie Helper A133" -> "Baijie A133 HelperBoard"
- dt-bindings: renamed "baijie,helper-a133" -> "baijie,helperboard-a133"
- dt-bindings: introduced allwinner,sun50i-a100-lradc
- reserve RAM for ATF
- renamed "sun50i-a133-baijie-helper.dtb" -> "sun50i-a133-helperboard.dtb"
- added "model" property into root of sun50i-a133-helperboard-core.dtsi
- added "cap-mmc-highspeed" and "max-frequency" into &mmc2
- added "x-powers,drive-vbus-en" and "*-supply" into &axp803
- dropped all "regulator-enable-ramp-delay" properties
- replaced &reg_dcdc3 with a "polyphased" comment
- exact DRAM voltage in &reg_dcdc5
- disabled &reg_dcdc6 to avoid "[   31.710641] dcdc6: disabling"
- added &reg_vdd5v "root" regulator
- added "disable-wp" into &mmc0
- commented &usb_otg
- assigned usb1_vbus-supply in &usbphy
- https://lore.kernel.org/all/20260605070923.3045073-1-alexander.sverdlin@gmail.com/
v3:
- added lradc node to sun50i-a100.dtsi
- enabled LRADC driver in arm64 defconfig
- added my copyrights into the newly introduced DTs
- all DT nodes sorted alphabetically
- all always-on regulators commented/propetly named
- all regulators got proper voltages (not default ranges)
- ADC-sensed buttons K1..K5 added
- re-labelled "eth_phy" -> "rgmii_phy"
- usbphy 0 switched from host into peripheral mode (downstream from an
  onboard hub)
- typo sun50i-a133-baije-core.dtsi -> sun50i-a133-baijie-core.dtsi
- https://lore.kernel.org/all/20260517234134.2737320-1-alexander.sverdlin@gmail.com/
v2:
- introduced baijie,helper-a133-core compatible for the Core (SoM) board
- https://lore.kernel.org/all/20260510201644.4143710-1-alexander.sverdlin@gmail.com/
v1:
- https://lore.kernel.org/all/20260503191842.2736130-1-alexander.sverdlin@gmail.com/

Alexander Sverdlin (6):
  arm64: defconfig: Enable Allwinner LRADC input driver
  dt-bindings: vendor-prefixes: Add Shenzhen Baijie Technology Co., Ltd.
  dt-bindings: arm: sunxi: Add Baijie HelperBoard A133 compatible
  dt-bindings: input: sun4i-lradc-keys: Add A100/A133 compatible
  arm64: dts: allwinner: a100: Add LRADC node
  arm64: dts: allwinner: A133: add support for Baijie Helper A133 board

 .../devicetree/bindings/arm/sunxi.yaml        |   6 +
 .../input/allwinner,sun4i-a10-lradc-keys.yaml |   1 +
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 arch/arm64/boot/dts/allwinner/Makefile        |   1 +
 .../arm64/boot/dts/allwinner/sun50i-a100.dtsi |  10 +
 .../sun50i-a133-helperboard-core.dtsi         | 197 ++++++++++++++++++
 .../dts/allwinner/sun50i-a133-helperboard.dts | 148 +++++++++++++
 arch/arm64/configs/defconfig                  |   1 +
 8 files changed, 366 insertions(+)
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard-core.dtsi
 create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-a133-helperboard.dts

-- 
2.54.0


^ permalink raw reply

* Re: [PATCH v1] iio: temperature: hid-sensor-temperature: switch to non-devm iio_device_register()
From: Jonathan Cameron @ 2026-06-23 19:06 UTC (permalink / raw)
  To: srinivas pandruvada
  Cc: Maxwell Doose, Sanjay Chitroda, jikos, dlechner, nuno.sa, andy,
	hongyan.song, linux-input, linux-iio, linux-kernel
In-Reply-To: <0e198f80c6f28e448611e02e1fe20af632931dd3.camel@linux.intel.com>

On Mon, 22 Jun 2026 13:50:22 -0700
srinivas pandruvada <srinivas.pandruvada@linux.intel.com> wrote:

> On Mon, 2026-06-22 at 10:27 -0500, Maxwell Doose wrote:
> > On Mon, Jun 22, 2026 at 10:26 AM srinivas pandruvada
> > <srinivas.pandruvada@linux.intel.com> wrote:  
> > > 
> > > On Mon, 2026-06-22 at 10:51 +0530, Sanjay Chitroda wrote:  
> > > > From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
> > > > 
> > > > Avoid using devm_iio_device_register(), as this driver requires
> > > > explicit
> > > > error handling and teardown ordering.
> > > > 
> > > > Mixing devm_* APIs with goto-based error unwinding breaks the
> > > > expected
> > > > LIFO resource release model and can introduce race windows during
> > > > device
> > > > removal. In particular, the IIO device may remain visible to
> > > > userspace
> > > > while dependent resources are already being freed, potentially
> > > > leading
> > > > to use-after-free issues.  
> > > 
> > > Please explain this use after free case here.
> > > 
> > > Thanks,
> > > Srinivas  
> > 
> > My guess is that because the device would still be registered but
> > would actually be removed, sysfs still has "wild" pointers to
> > read_raw() and write_raw() (which don't exist anymore), causing the
> > UAF. If I'm wrong feel free to correct me though.  
> 
> iio_device_unregister() will be last one to be called after device
> removal from devm action handler. This will cleanup attributes. So,
> read_raw() or write_raw() can be called. The problem can be handlers
> for read_raw() and write_raw() if anything there which are dependent on
> clean done by hid_temperature_remove(). Here callbacks are cleaned up,
> so nothing to respond to read  sensor_hub_input_attr_get_raw_value(),
> so it has to wait for 5 seconds to timeout, which is not great. So
> nothing against change done here.
> 
> But still not sure any use after free case, unless I am missing
> something.
> 
Agreed that to call UAF you need an explained path (and preferably
testing that it happens).  The timeout issue Srinivas calls out is
sufficient for us to merge this as a fix, but the patch description
should then talk about that.

Thanks,

Jonathan
> Thanks,
> Srinivas
> 
> 


^ permalink raw reply

* Re: [PATCH 0/3] HID: iio: callback API signature match for usage_id
From: Jonathan Cameron @ 2026-06-23 19:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Sanjay Chitroda, Jiri Kosina, Srinivas Pandruvada, David Lechner,
	Nuno Sá, Andy Shevchenko, linux-input, linux-iio,
	linux-kernel
In-Reply-To: <ajLC09uEIOClVzEq@ashevche-desk.local>

On Wed, 17 Jun 2026 18:52:51 +0300
Andy Shevchenko <andriy.shevchenko@intel.com> wrote:

> On Tue, Jun 16, 2026 at 06:55:19PM +0530, Sanjay Chitroda wrote:
> > 
> > Most of HID IIO driver has correct 'u32' type of usage_id with
> > https://lore.kernel.org/all/20260610-6-june-hid-iio-correct-usage-id-v2-0-c3c5f0720493@gmail.com/
> > series which is applied on iio/testing branch.
> > 
> > On top of the same, this series updates remaining HID IIO drivers
> > to use 'u32' for the usage_id parameter.
> > 
> > Pending list of HID IIO drivers are extracted with command line:
> > find drivers/iio/ -type f -name "*hid*" | xargs grep -A 5 static | \
> >     grep -E -A 5 "_proc_event\(|_capture_sample\(|_parse_report\(" --color | \
> >     grep usage_id  
> 
> I recommend to get used with `git grep ...` which is more powerful and much
> faster (on a Git index).
> 
> 	git grep -lw 'u[^3].* usage_id' -- drivers/iio/
> 
> for the list of files, and
> 
> 	git grep -np -w 'u[^3].* usage_id' -- drivers/iio/
> 
> for a better view.
> 
> (It gives one false positive, though :-)
> 
> > This matches expected callback API type as HID usage IDs are
> > defined as 32-bit values.
> > 
> > No functional changes are introduced.
> > 
> > Testing:
> >   - Compiled with W=1 for each patch in the series  
> 
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
> 
> Jonathan, it seems the missing part of the initial unification. Please, apply
> to your testing branch.
Applied to the testing branch of iio.git.

Thanks,

Jonathan

> 


^ permalink raw reply

* Re: [PATCH v4 08/10] HID: steelseries: Manage battery lifetime with refcounting
From: sashiko-bot @ 2026-06-23 17:36 UTC (permalink / raw)
  To: Sriman Achanta; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260623172310.272708-9-srimanachanta@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Dangling pointer left in device driver data on probe error path leads to Use-After-Free.
- [High] Race condition in sibling interface lookup during probe leading to Use-After-Free of `hid_device`.
--

commit 5a206f2162dc642386285174c7af698f767dad15
Author: Sriman Achanta <srimanachanta@gmail.com>

HID: steelseries: Manage battery lifetime with refcounting

The next change shares one steelseries_device between two HID interfaces,
so the state can outlive either interface. Stop using devm for it. Reference
count the struct with a kref and free it from steelseries_device_release().

> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> index 1f0e9cb5138f6..734cf1eb87894 100644
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> @@ -361,12 +373,15 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
>  
>  err_stop:
>  	hid_hw_stop(hdev);
> +err_put:
> +	kref_put(&sd->refcnt, steelseries_device_release);

[Severity: High]
Does this error path leave a dangling pointer in the device's driver data?

If hid_hw_start() or hid_hw_open() fails during the sync interface probe,
the driver explicitly frees the sd struct via kref_put(). However, it leaves
a dangling pointer because hid_set_drvdata(hdev, sd) was already called
earlier and is not reverted here.

If the async interface is probed concurrently (e.g., via sysfs bind),
it calls steelseries_get_sibling_hdev() to find the sync interface's HID
device and reads its driver data. It might receive this dangling pointer
and call kref_get() on freed memory, resulting in a use-after-free.

>  	return ret;
>  }

[Severity: High]
Is there a race condition when looking up the sibling interface during probe
that could lead to a use-after-free of the hid_device?

When probing the async interface, steelseries_get_sibling_hdev() retrieves
the sibling interface's hid_device pointer locklessly:

drivers/hid/hid-steelseries-arctis.c:steelseries_get_sibling_hdev() {
    ...
    sibling_hdev = usb_get_intfdata(sibling_intf);
    return sibling_hdev;
}

Then in steelseries_arctis_probe():

    master_hdev = steelseries_get_sibling_hdev(hdev, info->sync_interface);
    if (!master_hdev || !hid_get_drvdata(master_hdev))
        return -EPROBE_DEFER;

If the sync interface is unbound concurrently (e.g., via sysfs unbind),
hid_destroy_device() can free the hid_device. If the async probe reads
the intfdata pointer just before it is cleared and dereferences it via
hid_get_drvdata(master_hdev), it accesses freed memory. The HID device
probe path does not seem to hold the parent USB device lock to prevent
this concurrent execution.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260623172310.272708-1-srimanachanta@gmail.com?part=8

^ permalink raw reply

* Re: [PATCH v4 09/10] HID: steelseries: Add async status interface support
From: sashiko-bot @ 2026-06-23 17:36 UTC (permalink / raw)
  To: Sriman Achanta; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260623172310.272708-10-srimanachanta@gmail.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

New issues:
- [Critical] The driver blindly casts the sibling interface's driver data to a `struct hid_device` without verifying the bound driver, leading to type confusion and memory corruption.
- [Critical] The sync interface publishes `sd` to `drvdata` before initialization is complete, allowing the async interface to crash the kernel by scheduling an uninitialized work struct.
- [High] Lockless retrieval and access of the sibling interface's driver data leads to a Use-After-Free if the sync interface is unbound concurrently.
- [High] If the sync interface probe fails after the async interface binds to it, the async interface will access a freed `sd->hdev` pointer.

Pre-existing issues:
- [High] An ERR_PTR temporarily assigned to `sd->battery` during initialization failure can be concurrently dereferenced by the raw event handler.
--

commit 002dd61306f7255151ab901886b17a9e612226ad
Author: Sriman Achanta <srimanachanta@gmail.com>
Subject: HID: steelseries: Add async status interface support

This commit adds support for a second HID interface that sends battery
and connection updates asynchronously. This allows the driver to stop
polling the sync interface by watching the async interface instead.

> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> index 734cf1eb87894..2208d0e4cd2ad 100644
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> @@ -316,6 +318,23 @@ static int steelseries_battery_register(struct steelseries_device *sd)
>  	return 0;
>  }
>  
> +static struct hid_device *steelseries_get_sibling_hdev(struct hid_device *hdev,
> +						       int interface_num)
> +{
> +	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
> +	struct usb_device *usb_dev = interface_to_usbdev(intf);
> +	struct usb_interface *sibling_intf;
> +	struct hid_device *sibling_hdev;
> +
> +	sibling_intf = usb_ifnum_to_if(usb_dev, interface_num);
> +	if (!sibling_intf)
> +		return NULL;
> +
> +	sibling_hdev = usb_get_intfdata(sibling_intf);

[Severity: High]
Does this code safely retrieve the sibling interface's driver data? Because
no reference is taken on the USB interface and usb_driver_claim_interface()
is not used, could a concurrent sysfs unbind destroy the interface and the
retrieved data while we are accessing it?

[Severity: Critical]
Is it safe to assume usb_get_intfdata() returns a struct hid_device pointer
here? If the sync interface is bound to a different driver (such as
snd-usb-audio), its driver data would be a completely different structure.
Could this lead to type confusion and memory corruption when the pointer is
dereferenced later in the probe function?

> +
> +	return sibling_hdev;
> +}
> +
>  static int steelseries_arctis_probe(struct hid_device *hdev,
>  				    const struct hid_device_id *id)
>  {
> @@ -337,39 +356,76 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
>  	if (ret)
>  		return ret;
>  
> -	/* Let hid-generic handle non-sync interfaces */
> -	if (interface_num != info->sync_interface)
> +	/* Let hid-generic handle non-vendor or unknown interfaces */
> +	if (interface_num != info->sync_interface &&
> +	    (!info->async_interface || interface_num != info->async_interface))
>  		return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
>  
> -	sd = kzalloc_obj(*sd, GFP_KERNEL);
> -	if (!sd)
> -		return -ENOMEM;
> +	if (interface_num == info->sync_interface) {
> +		sd = kzalloc_obj(*sd, GFP_KERNEL);
> +		if (!sd)
> +			return -ENOMEM;
>  
> -	kref_init(&sd->refcnt);
> -	sd->hdev = hdev;
> -	sd->info = info;
> -	spin_lock_init(&sd->lock);
> +		kref_init(&sd->refcnt);
> +		sd->hdev = hdev;
> +		sd->info = info;
> +		spin_lock_init(&sd->lock);
>  
> -	hid_set_drvdata(hdev, sd);
> +		hid_set_drvdata(hdev, sd);

[Severity: Critical]
By calling hid_set_drvdata() here, sd is globally published before
INIT_DELAYED_WORK() is called below. If the async interface probes concurrently
and immediately receives an event, could it call schedule_delayed_work() on
an uninitialized work struct?

>  
> -	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> -	if (ret)
> -		goto err_put;
> +		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> +		if (ret)
> +			goto err_put;
>  
> -	ret = hid_hw_open(hdev);
> -	if (ret)
> -		goto err_stop;
> +		ret = hid_hw_open(hdev);
> +		if (ret)
> +			goto err_stop;

[Severity: High]
If the sync interface probe fails after this point (for example, if hid_hw_open()
or steelseries_battery_register() fails) and returns an error, but the async
interface has already bound and incremented sd->refcnt:

Since steelseries_arctis_remove() is never called for the failed sync probe,
sd->removed remains false. If the driver core clears the sync interface's driver
data and the sibling interface is unbound, sd->hdev is freed.

Could the still-active async interface then process raw events, bypass the
sd->removed check, and access the freed sd->hdev pointer via
steelseries_headset_set_wireless_status()?

> +
> +		if (info->capabilities & SS_CAP_BATTERY) {
> +			ret = steelseries_battery_register(sd);
> +			if (ret < 0)
> +				hid_warn(hdev, "Failed to register battery: %d\n", ret);
> +		}
>  
> -	if (info->capabilities & SS_CAP_BATTERY) {
> -		ret = steelseries_battery_register(sd);
> -		if (ret < 0)
> -			hid_warn(hdev, "Failed to register battery: %d\n", ret);
> +		INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
> +		schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
> +
> +		return 0;
>  	}
[ ... ]
> @@ -442,6 +509,10 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
>  			old_connected ? "" : "not ",
>  			sd->headset_connected ? "" : "not ");
>  
> +		if (sd->headset_connected && !old_connected &&
> +		    sd->info->async_interface && is_async_interface)
> +			schedule_delayed_work(&sd->status_work, 0);
> +
>  		if (sd->battery) {
>  			steelseries_headset_set_wireless_status(sd->hdev,
>  							       sd->headset_connected);
>  			power_supply_changed(sd->battery);

[Severity: High]
This is a pre-existing issue, but is there a data race with sd->battery here?

During initialization in steelseries_battery_register():

	sd->battery = power_supply_register(&sd->hdev->dev,
			&sd->battery_desc, &battery_cfg);
	if (IS_ERR(sd->battery)) {
		ret = PTR_ERR(sd->battery);
		sd->battery = NULL;

Since hardware has already been enabled via hid_hw_start(), interrupts can
arrive concurrently. If an event arrives during the window where sd->battery
holds an ERR_PTR, if (sd->battery) will evaluate to true.

Could this cause power_supply_changed(sd->battery) to dereference the error
pointer?

>  		}
>  
> @@ -465,6 +536,8 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
>  			power_supply_changed(sd->battery);
>  	}
>  
> +	spin_unlock_irqrestore(&sd->lock, flags);
> +
>  	return 0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260623172310.272708-1-srimanachanta@gmail.com?part=9

^ permalink raw reply

* Re: [PATCH v4 10/10] HID: steelseries: Add support for Arctis Nova 7 Gen2 family
From: sashiko-bot @ 2026-06-23 17:35 UTC (permalink / raw)
  To: Sriman Achanta; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260623172310.272708-11-srimanachanta@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [Medium] The unconditional minimum size check in the Gen2 parsing function may silently drop valid unsolicited status updates.

Pre-existing issues:
- [High] Unsafe fetching of the sibling interface's private data lacks driver validation and synchronization, leading to Type Confusion and Use-After-Free.
--

commit ca415cb624472143e783db3389a867c4e203e6c8
Author: Sriman Achanta <srimanachanta@gmail.com>

HID: steelseries: Add support for Arctis Nova 7 Gen2 family

This commit adds support for the Arctis Nova 7 Gen2 headsets.
It introduces a new parsing helper for the Gen2 status format and uses an
async interface to handle unsolicited battery and connection updates without
polling.

> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> @@ -163,6 +170,30 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
>  	}
>  }
>  
> +static void steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_device *sd,
> +							u8 *data, int size)
> +{
> +	if (size < 4)
> +		return;

[Severity: Medium]
Will this strict minimum size check silently drop valid short packets?

Since opcodes like 0xb7, 0xb9, and 0xbb only appear to require 2 bytes of
payload (e.g., data[0] and data[1]), if the hardware sends an unsolicited
report as a 2 or 3 byte packet, it seems it would be dropped before
processing.

> +
> +	switch (data[0]) {
> +	case 0xb0:
> +		sd->headset_connected = (data[1] == 0x03);
> +		sd->battery_capacity = data[2];
> +		sd->battery_charging = (data[3] == 0x01);
> +		break;
> +	case 0xb7:
> +		sd->battery_capacity = data[1];
> +		break;
> +	case 0xb9:
> +		sd->headset_connected = (data[1] == 0x03);
> +		break;
> +	case 0xbb:
> +		sd->battery_charging = (data[1] == 0x01);
> +		break;
> +	}
> +}
> +
>  /*
>   * Device info definitions
>   */
> @@ -181,6 +212,14 @@ static const struct steelseries_device_info arctis_9_info = {
>  	.parse_status = steelseries_arctis_9_parse_status,
>  };
>  
> +static const struct steelseries_device_info arctis_nova_7_gen2_info = {
> +	.sync_interface = 3,
> +	.async_interface = 5,

[Severity: High]
This isn't a bug introduced by this patch, but since these devices use an
async interface, does the sibling interface lookup in 
steelseries_get_sibling_hdev() have adequate locking and validation?

When a device probes the async interface, it appears
steelseries_get_sibling_hdev() fetches intfdata from the sibling interface
via usb_get_intfdata() locklessly.

If the sibling interface (interface 3) is unbound via sysfs and bound to
another driver (like usbfs), or physically unplugged concurrently, could
this return a foreign private context or a soon-to-be-freed pointer?

Then in steelseries_arctis_probe(), this unvalidated pointer is cast and
dereferenced to get the driver data:

    sd = hid_get_drvdata(master_hdev);
    kref_get(&sd->refcnt);

Could this lead to type confusion or a use-after-free if the sibling driver
is no longer the expected usbhid driver?

> +	.capabilities = SS_CAP_BATTERY,
> +	.request_status = steelseries_arctis_nova_request_status,
> +	.parse_status = steelseries_arctis_nova_7_gen2_parse_status,
> +};
> +

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260623172310.272708-1-srimanachanta@gmail.com?part=10

^ permalink raw reply

* Re: [PATCH v4 05/10] HID: steelseries: Refactor Arctis driver to use device_info framework
From: sashiko-bot @ 2026-06-23 17:33 UTC (permalink / raw)
  To: Sriman Achanta; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260623172310.272708-6-srimanachanta@gmail.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:

New issues:
- [High] Missing report ID signature validation for Arctis 1 causes arbitrary raw events to corrupt headset state.
- [High] Battery status requests are incorrectly sent as Feature reports instead of Output reports, breaking battery polling.
- [Medium] Dropped logic for marking Arctis 9 headset as disconnected when it reports an unknown status.

Pre-existing issues:
- [High] The raw_event interrupt handler can dereference an ERR_PTR due to a TOCTOU race window when battery registration fails.
--

commit 0576cf59ec529dc31ed68f59a8d598bdb4ca4a82
Author: Sriman Achanta <srimanachanta@gmail.com>

HID: steelseries: Refactor Arctis driver to use device_info framework

Replace the per-product if/else quirk bitmap with a steelseries_device_info
struct. Each model provides its capabilities, sync_interface, and
request_status/parse_status callbacks.

> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> index 079504e6932a1..f00f4c5e6d9e4 100644
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> @@ -15,70 +16,95 @@
[ ... ]
> +static int steelseries_arctis_1_request_status(struct hid_device *hdev)
> +{
> +	const u8 data[] = { 0x06, 0x12 };
> +
> +	return steelseries_send_feature_report(hdev, data, sizeof(data));
> +}
> +
> +static int steelseries_arctis_9_request_status(struct hid_device *hdev)
> +{
> +	const u8 data[] = { 0x00, 0x20 };
> +
> +	return steelseries_send_feature_report(hdev, data, sizeof(data));
> +}

[Severity: High]
Do these devices expect feature reports instead of output reports for status
requests?

The original code sent the periodic battery status request to the device
using an output report via hid_hw_raw_request(..., HID_OUTPUT_REPORT, ...).
This refactoring switches it to use steelseries_send_feature_report()
instead.

Sending a feature report to a device endpoint expecting an output report
might result in a USB stall, which would break battery polling.

[ ... ]
> @@ -88,30 +114,96 @@ static int battery_capacity_to_level(int capacity)
[ ... ]
> +static void steelseries_arctis_1_parse_status(struct steelseries_device *sd,
> +					      u8 *data, int size)
> +{
> +	if (size < 4)
> +		return;
> +
> +	sd->headset_connected = (data[2] != 0x01);
> +	sd->battery_capacity = data[3];
> +}

[Severity: High]
Will this corrupt the battery state if other reports are received?

The original raw event handler verified that the incoming Arctis 1 report
matched the expected battery status signature using memcmp().

Since steelseries_arctis_raw_event() now invokes parse_status()
unconditionally for all incoming raw events, could a different report
(such as volume control) with a payload of at least 4 bytes be erroneously
parsed as battery data?

> +static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
> +					      u8 *data, int size)
> +{
> +	if (size < 5)
> +		return;
> +
> +	if (data[0] == 0xaa) {
> +		sd->headset_connected = (data[1] == 0x01);
> +		sd->battery_charging = (data[4] == 0x01);
> +		sd->battery_capacity = steelseries_map_capacity(data[3], 0x68, 0x9d);
> +	}
> +}

[Severity: Medium]
What happens if the device is turned off and sends the "no known status"
packet?

The original code explicitly handled the 0x55 response and used it to mark
the headset as disconnected.

By only processing 0xaa and dropping other responses without taking any
action, will we fail to update the connection state and leave the device
incorrectly reported as connected?

[ ... ]
> @@ -168,7 +245,26 @@ static enum power_supply_property steelseries_headset_battery_props[] = {
[ ... ]
> +static int steelseries_battery_register(struct steelseries_device *sd)
>  {
[ ... ]
>  	sd->battery = devm_power_supply_register(&sd->hdev->dev,
>  			&sd->battery_desc, &battery_cfg);
>  	if (IS_ERR(sd->battery)) {
>  		ret = PTR_ERR(sd->battery);
> +		sd->battery = NULL;

[Severity: High]
This isn't a bug introduced by this patch, but does assigning the return
value directly to sd->battery before checking for an error create a race
condition?

Since hid_hw_start() and hid_hw_open() are already called in the probe
function, hardware interrupts are active. If power_supply_register() fails,
sd->battery temporarily holds an error pointer.

If steelseries_arctis_raw_event() triggers during this small window, the
following check would evaluate to true because an error pointer is not NULL:

steelseries_arctis_raw_event() {
    ...
    if (sd->battery)
        power_supply_changed(sd->battery);
}

Could this lead to an invalid pointer dereference and a kernel panic?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260623172310.272708-1-srimanachanta@gmail.com?part=5

^ permalink raw reply

* [PATCH v4 10/10] HID: steelseries: Add support for Arctis Nova 7 Gen2 family
From: Sriman Achanta @ 2026-06-23 17:23 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: linux-input, linux-kernel, Simon Wood, Christian Mayer,
	Bastien Nocera, Sriman Achanta
In-Reply-To: <20260623172310.272708-1-srimanachanta@gmail.com>

The Arctis Nova 7 Gen2 headsets answer status polls, but they also send
unsolicited battery and connection updates on a second HID interface
(interface 5). Use that interface through async_interface so the driver
does not have to poll. Add request and parse helpers for the Gen2 status
format (0xb0/0xb7/0xb9/0xbb opcodes).

Add the eight USB product IDs that share this protocol:

  0x22a1  Arctis Nova 7 2026
  0x22a7  Arctis Nova 7P 2026
  0x22a5  Arctis Nova 7X 2026
  0x22a9  Arctis Nova 7 Diablo 2026
  0x227e  Arctis Nova 7 Gen 2
  0x2258  Arctis Nova 7X Gen 2
  0x229e  Arctis Nova 7X Gen 2 (alternate PID)
  0x22ad  Arctis Nova 7X Gen 2 (alternate PID)

Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
 drivers/hid/hid-ids.h                |  8 ++++
 drivers/hid/hid-quirks.c             |  8 ++++
 drivers/hid/hid-steelseries-arctis.c | 63 ++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 915e936cbf8b..6b5be86b1bdf 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1379,6 +1379,14 @@
 #define USB_DEVICE_ID_STEELSERIES_SRWS1	0x1410
 #define USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X	0x12b6
 #define USB_DEVICE_ID_STEELSERIES_ARCTIS_9	0x12c2
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026	0x22a1
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026	0x22a7
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026	0x22a5
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026	0x22a9
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2	0x227e
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2	0x2258
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2	0x229e
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3	0x22ad
 
 #define USB_VENDOR_ID_SUN		0x0430
 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE	0xcdab
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index f546179858c2..40a761b5df91 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -749,6 +749,14 @@ static const struct hid_device_id hid_have_special_driver[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_9) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3) },
 #endif
 #if IS_ENABLED(CONFIG_HID_SUNPLUS)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 2208d0e4cd2a..eecd384b1a33 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -114,6 +114,13 @@ static int steelseries_arctis_9_request_status(struct hid_device *hdev)
 	return steelseries_send_feature_report(hdev, data, sizeof(data));
 }
 
+static int steelseries_arctis_nova_request_status(struct hid_device *hdev)
+{
+	const u8 data[] = { 0x00, 0xb0 };
+
+	return steelseries_send_output_report(hdev, data, sizeof(data));
+}
+
 /*
  * Headset battery helpers
  */
@@ -163,6 +170,30 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
 	}
 }
 
+static void steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_device *sd,
+							u8 *data, int size)
+{
+	if (size < 4)
+		return;
+
+	switch (data[0]) {
+	case 0xb0:
+		sd->headset_connected = (data[1] == 0x03);
+		sd->battery_capacity = data[2];
+		sd->battery_charging = (data[3] == 0x01);
+		break;
+	case 0xb7:
+		sd->battery_capacity = data[1];
+		break;
+	case 0xb9:
+		sd->headset_connected = (data[1] == 0x03);
+		break;
+	case 0xbb:
+		sd->battery_charging = (data[1] == 0x01);
+		break;
+	}
+}
+
 /*
  * Device info definitions
  */
@@ -181,6 +212,14 @@ static const struct steelseries_device_info arctis_9_info = {
 	.parse_status = steelseries_arctis_9_parse_status,
 };
 
+static const struct steelseries_device_info arctis_nova_7_gen2_info = {
+	.sync_interface = 3,
+	.async_interface = 5,
+	.capabilities = SS_CAP_BATTERY,
+	.request_status = steelseries_arctis_nova_request_status,
+	.parse_status = steelseries_arctis_nova_7_gen2_parse_status,
+};
+
 /*
  * Headset wireless status and battery infrastructure
  */
@@ -548,6 +587,30 @@ static const struct hid_device_id steelseries_arctis_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
 			 USB_DEVICE_ID_STEELSERIES_ARCTIS_9),
 	  .driver_data = (unsigned long)&arctis_9_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+			 USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3),
+	  .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
 	{}
 };
 MODULE_DEVICE_TABLE(hid, steelseries_arctis_devices);
-- 
2.54.0


^ permalink raw reply related

* [PATCH v4 09/10] HID: steelseries: Add async status interface support
From: Sriman Achanta @ 2026-06-23 17:23 UTC (permalink / raw)
  To: Jiri Kosina, Benjamin Tissoires
  Cc: linux-input, linux-kernel, Simon Wood, Christian Mayer,
	Bastien Nocera, Sriman Achanta
In-Reply-To: <20260623172310.272708-1-srimanachanta@gmail.com>

Some headsets expose a second HID interface that sends battery and
connection updates on its own. Watching that interface lets the driver
stop polling the sync interface. Add a
steelseries_device_info::async_interface field and the code to handle
it:

  - The driver binds both the sync and async interfaces. The async
    interface shares the steelseries_device created by the sync
    interface. It finds the sibling with usb_ifnum_to_if(), takes a
    reference, and returns -EPROBE_DEFER until the sync interface has
    probed. If the sync interface never binds, the async interface
    defers forever, which is fine here.
  - raw_event() now holds sd->lock and re-checks sd->removed so events
    on either interface are serialised against removal.
  - status_work runs once for async devices instead of rearming. A
    single status request is sent when the headset connects to get the
    initial battery level.

No device sets async_interface yet. This is the infrastructure for the
next commit.

Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
 drivers/hid/hid-steelseries-arctis.c | 121 +++++++++++++++++++++------
 1 file changed, 97 insertions(+), 24 deletions(-)

diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 734cf1eb8789..2208d0e4cd2a 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -26,6 +26,7 @@ struct steelseries_device_info {
 	unsigned long capabilities;
 
 	u8 sync_interface;
+	u8 async_interface;
 
 	int (*request_status)(struct hid_device *hdev);
 	void (*parse_status)(struct steelseries_device *sd, u8 *data, int size);
@@ -272,7 +273,8 @@ static void steelseries_status_timer_work_handler(struct work_struct *work)
 	sd->info->request_status(sd->hdev);
 
 	spin_lock_irqsave(&sd->lock, flags);
-	if (!sd->removed)
+	/* Async devices push status events themselves; only poll once. */
+	if (!sd->removed && !sd->info->async_interface)
 		schedule_delayed_work(&sd->status_work,
 				msecs_to_jiffies(STEELSERIES_HEADSET_STATUS_TIMEOUT_MS));
 	spin_unlock_irqrestore(&sd->lock, flags);
@@ -316,6 +318,23 @@ static int steelseries_battery_register(struct steelseries_device *sd)
 	return 0;
 }
 
+static struct hid_device *steelseries_get_sibling_hdev(struct hid_device *hdev,
+						       int interface_num)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct usb_interface *sibling_intf;
+	struct hid_device *sibling_hdev;
+
+	sibling_intf = usb_ifnum_to_if(usb_dev, interface_num);
+	if (!sibling_intf)
+		return NULL;
+
+	sibling_hdev = usb_get_intfdata(sibling_intf);
+
+	return sibling_hdev;
+}
+
 static int steelseries_arctis_probe(struct hid_device *hdev,
 				    const struct hid_device_id *id)
 {
@@ -337,39 +356,76 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
 	if (ret)
 		return ret;
 
-	/* Let hid-generic handle non-sync interfaces */
-	if (interface_num != info->sync_interface)
+	/* Let hid-generic handle non-vendor or unknown interfaces */
+	if (interface_num != info->sync_interface &&
+	    (!info->async_interface || interface_num != info->async_interface))
 		return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 
-	sd = kzalloc_obj(*sd, GFP_KERNEL);
-	if (!sd)
-		return -ENOMEM;
+	if (interface_num == info->sync_interface) {
+		sd = kzalloc_obj(*sd, GFP_KERNEL);
+		if (!sd)
+			return -ENOMEM;
 
-	kref_init(&sd->refcnt);
-	sd->hdev = hdev;
-	sd->info = info;
-	spin_lock_init(&sd->lock);
+		kref_init(&sd->refcnt);
+		sd->hdev = hdev;
+		sd->info = info;
+		spin_lock_init(&sd->lock);
 
-	hid_set_drvdata(hdev, sd);
+		hid_set_drvdata(hdev, sd);
 
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret)
-		goto err_put;
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+		if (ret)
+			goto err_put;
 
-	ret = hid_hw_open(hdev);
-	if (ret)
-		goto err_stop;
+		ret = hid_hw_open(hdev);
+		if (ret)
+			goto err_stop;
+
+		if (info->capabilities & SS_CAP_BATTERY) {
+			ret = steelseries_battery_register(sd);
+			if (ret < 0)
+				hid_warn(hdev, "Failed to register battery: %d\n", ret);
+		}
 
-	if (info->capabilities & SS_CAP_BATTERY) {
-		ret = steelseries_battery_register(sd);
-		if (ret < 0)
-			hid_warn(hdev, "Failed to register battery: %d\n", ret);
+		INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
+		schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
+
+		return 0;
 	}
 
-	INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
-	schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
+	/*
+	 * The async interface shares the steelseries_device created by the
+	 * sync interface. Defer until the sync interface has probed and
+	 * published its drvdata.
+	 */
+	if (info->async_interface && interface_num == info->async_interface) {
+		struct hid_device *master_hdev;
 
-	return 0;
+		master_hdev = steelseries_get_sibling_hdev(hdev, info->sync_interface);
+
+		if (!master_hdev || !hid_get_drvdata(master_hdev))
+			return -EPROBE_DEFER;
+
+		sd = hid_get_drvdata(master_hdev);
+		kref_get(&sd->refcnt);
+		hid_set_drvdata(hdev, sd);
+
+		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+		if (ret) {
+			kref_put(&sd->refcnt, steelseries_device_release);
+			return ret;
+		}
+
+		ret = hid_hw_open(hdev);
+		if (ret) {
+			hid_hw_stop(hdev);
+			kref_put(&sd->refcnt, steelseries_device_release);
+			return ret;
+		}
+		return 0;
+	}
+
+	return -ENODEV;
 
 err_stop:
 	hid_hw_stop(hdev);
@@ -426,10 +482,21 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
 	u8 old_capacity;
 	bool old_connected;
 	bool old_charging;
+	bool is_async_interface;
+	unsigned long flags;
 
 	if (!sd)
 		return 0;
 
+	is_async_interface = (hdev != sd->hdev);
+
+	spin_lock_irqsave(&sd->lock, flags);
+
+	if (sd->removed) {
+		spin_unlock_irqrestore(&sd->lock, flags);
+		return 0;
+	}
+
 	old_capacity = sd->battery_capacity;
 	old_connected = sd->headset_connected;
 	old_charging = sd->battery_charging;
@@ -442,6 +509,10 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
 			old_connected ? "" : "not ",
 			sd->headset_connected ? "" : "not ");
 
+		if (sd->headset_connected && !old_connected &&
+		    sd->info->async_interface && is_async_interface)
+			schedule_delayed_work(&sd->status_work, 0);
+
 		if (sd->battery) {
 			steelseries_headset_set_wireless_status(sd->hdev,
 							       sd->headset_connected);
@@ -465,6 +536,8 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
 			power_supply_changed(sd->battery);
 	}
 
+	spin_unlock_irqrestore(&sd->lock, flags);
+
 	return 0;
 }
 
-- 
2.54.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox