* [PATCH 2/2] Input: rmi4 - fix num_subpackets overflow in register descriptor
From: Dmitry Torokhov @ 2026-04-28 1:09 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
In-Reply-To: <20260428010917.1320927-1-dmitry.torokhov@gmail.com>
RMI_REG_DESC_SUBPACKET_BITS is defined as 296 (37 * BITS_PER_BYTE). This
may overflow num_subpackets in struct rmi_register_desc_item which is
defined as a u8.
Fix this by changing the type of num_subpackets to u16.
Pack the structure by rearranging the members to avoid holes, change
reg_size from unsigned long to u32 to save space and ensure consistent
size across 32-bit and 64-bit architectures, and use DECLARE_BITMAP()
for subpacket_map.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.h | 8 ++++----
drivers/input/rmi4/rmi_f12.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index e84495caab15..865ffc7882f3 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -11,6 +11,7 @@
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include <linux/input.h>
+#include <linux/types.h>
#include "rmi_bus.h"
#define SYNAPTICS_INPUT_DEVICE_NAME "Synaptics RMI4 Touch Sensor"
@@ -52,10 +53,9 @@ struct pdt_entry {
/* describes a single packet register */
struct rmi_register_desc_item {
u16 reg;
- unsigned long reg_size;
- u8 num_subpackets;
- unsigned long subpacket_map[BITS_TO_LONGS(
- RMI_REG_DESC_SUBPACKET_BITS)];
+ u16 num_subpackets;
+ u32 reg_size;
+ DECLARE_BITMAP(subpacket_map, RMI_REG_DESC_SUBPACKET_BITS);
};
/*
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8246fe77114b..9bcc27e9d308 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -88,7 +88,7 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
if (item->reg_size > sizeof(buf)) {
dev_err(&fn->dev,
- "F12 control8 should be no bigger than %zd bytes, not: %ld\n",
+ "F12 control8 should be no bigger than %zd bytes, not: %d\n",
sizeof(buf), item->reg_size);
return -ENODEV;
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related
* [PATCH] hwmon: prevent packets from going to driver for probe
From: Edward Adam Davis @ 2026-04-28 4:12 UTC (permalink / raw)
To: syzbot+9eebf5f6544c5e873858
Cc: bentiss, jikos, linux-input, linux-kernel, linux-usb,
syzkaller-bugs
In-Reply-To: <69eed7e0.a00a0220.7773.0026.GAE@google.com>
A race condition exists between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
corsairpsu_probe(). If the probe operation fails after "io start" has
been initiated, this race condition will result in a uaf vulnerability
[1].
CPU0 CPU1
==== ====
corsairpsu_probe()
hid_device_io_start()
... unlock driver_input_lock
hid_hw_stop()
kfree(hidraw) __hid_input_report()
... acquire driver_input_lock
hid_report_raw_event()
hidraw_report_event()
... access hidraw's list_lock // trigger uaf
Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to
be executed, the io_started flag is first cleared while holding the
driver_input_lock to prevent potential race conditions involving input
reports.
[1]
BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56
Call Trace:
hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577
hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076
__hid_input_report drivers/hid/hid-core.c:2152 [inline]
hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174
hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286
__usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657
dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005
Allocated by task 10:
hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606
hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277
hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387
corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782
Freed by task 10:
hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662
hid_disconnect drivers/hid/hid-core.c:2362 [inline]
hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407
corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826
Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver")
Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858
Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
drivers/hwmon/corsair-psu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
index dddbd2463f8d..4e766bf32189 100644
--- a/drivers/hwmon/corsair-psu.c
+++ b/drivers/hwmon/corsair-psu.c
@@ -823,6 +823,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id
fail_and_close:
hid_hw_close(hdev);
fail_and_stop:
+ hid_device_io_stop(hdev);
hid_hw_stop(hdev);
return ret;
}
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] [v2] input: gpio-keys: make legacy gpiolib optional
From: Dmitry Torokhov @ 2026-04-28 4:14 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Matti Vaittinen, Lee Jones, Arnd Bergmann, Gatien Chevallier,
Marco Crivellari, Fabrice Gasnier, Andreas Kemnade,
Krzysztof Kozlowski, Charles Keepax, Christophe JAILLET,
linux-input, linux-kernel
In-Reply-To: <20260427143406.3020992-1-arnd@kernel.org>
On Mon, Apr 27, 2026 at 04:33:49PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> Most users of gpio-keys and gpio-keys-polled use modern gpiolib
> interfaces, but there are still number of ancient sh, arm32 and x86
> machines that have never been converted.
>
> Add an #ifdef block for the parts of the driver that are only used on
> those legacy machines.
>
> The two Rohm PMIC drivers use a gpio-keys device without an actual GPIO,
> passing an IRQ number instead. In order to keep this working both with
> and with CONFIG_GPIOLIB_LEGACY, change the gpio-keys driver to ignore
> the gpio number if an IRQ is passed.
>
> Link: https://lore.kernel.org/all/b3c94552-c104-42e3-be15-7e8362e8039e@gmail.com/
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> v2: skip the fake GPIO number passing from mfd
> ---
> drivers/input/keyboard/gpio_keys.c | 7 ++++---
> drivers/input/keyboard/gpio_keys_polled.c | 2 ++
> drivers/mfd/rohm-bd71828.c | 1 -
> drivers/mfd/rohm-bd718x7.c | 1 -
Let's see if my patches to rohm drivers will get accepted and then maybe
we can remove legacy gpio API from gpio-keys altogether.
Thanks.
--
Dmitry
^ permalink raw reply
* [bug report] Potential order bug in 'drivers/input/misc', particularly 'ati_remote2.c', 'cm109.c', 'keyspan_remote.c'
From: Ginger @ 2026-04-28 4:18 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input
Dear Linux kernel maintainers,
My research-based static analyzer found a potential order bug within
the ' drivers/input/misc' subsystem. I will use the potential bug
found in 'drivers/input/misc/ati_remote2.c' as the typical example.
The similar potential bug patterns are also observed in 'cm109.c' and
'keyspan_remote.c'.
Kernel version: long-term kernel v6.18.9
Potential issue:
T0:
ati_remote2_disconnect
--> ar2 = usb_get_intfdata(interface);
--> usb_set_intfdata(interface, NULL);
--> input_unregister_device(ar2->idev);
--> usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
--> kfree(ar2)
T1:
ati_remote2_store_channel_mask (registered as the device attribute
function and exposed via the sysfs)
--> struct ati_remote2 *ar2 = usb_get_intfdata(intf);
--> ar2->mode_mask = mask;
In T0, the interface is nullified before its get deregistered. Thus,
it is possible for T1 to still get the usb dev and access it via the
interface, which, however, has been already nullified or even freed.
This similar pattern is also observed in 'cm109_usb_disconnect()' of
file 'cm109.c' and 'keyspan_disconnect()' of file 'keyspan_remote.c'.
Thank you for your time and consideration.
Sincerely,
Ginger
^ permalink raw reply
* Re: [PATCH] [v2] input: gpio-keys: make legacy gpiolib optional
From: Arnd Bergmann @ 2026-04-28 6:12 UTC (permalink / raw)
To: Dmitry Torokhov, Arnd Bergmann
Cc: Matti Vaittinen, Lee Jones, Gatien Chevallier, Marco Crivellari,
Fabrice GASNIER, Andreas Kemnade, Krzysztof Kozlowski,
Charles Keepax, Christophe JAILLET, linux-input, linux-kernel
In-Reply-To: <afAz-UQY0aCaThV3@google.com>
On Tue, Apr 28, 2026, at 06:14, Dmitry Torokhov wrote:
> On Mon, Apr 27, 2026 at 04:33:49PM +0200, Arnd Bergmann wrote:
>>
>> The two Rohm PMIC drivers use a gpio-keys device without an actual GPIO,
>> passing an IRQ number instead. In order to keep this working both with
>> and with CONFIG_GPIOLIB_LEGACY, change the gpio-keys driver to ignore
>> the gpio number if an IRQ is passed.
>>
>> Link: https://lore.kernel.org/all/b3c94552-c104-42e3-be15-7e8362e8039e@gmail.com/
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> ---
>> v2: skip the fake GPIO number passing from mfd
>> ---
>> drivers/input/keyboard/gpio_keys.c | 7 ++++---
>> drivers/input/keyboard/gpio_keys_polled.c | 2 ++
>> drivers/mfd/rohm-bd71828.c | 1 -
>> drivers/mfd/rohm-bd718x7.c | 1 -
>
> Let's see if my patches to rohm drivers will get accepted and then maybe
> we can remove legacy gpio API from gpio-keys altogether.
I think it would be good to still merge the drivers/input
parts of my patch. Since CONFIG_GPIOLIB_LEGACY is still set
unconditionally at the moment, that should work fine as long
as your patches for the rohm drivers get merged before
we turn off CONFIG_GPIOLIB_LEGACY for modern platforms.
In linux-next, I see these users of the legacy gpio-keys platform
data remaining:
arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
arch/arm/mach-orion5x/dns323-setup.c
arch/arm/mach-orion5x/mv2120-setup.c
arch/arm/mach-orion5x/net2big-setup.c
arch/arm/mach-orion5x/ts209-setup.c
arch/arm/mach-orion5x/ts409-setup.c
arch/arm/mach-s3c/mach-crag6410.c
arch/arm/mach-sa1100/assabet.c
arch/arm/mach-sa1100/collie.c
arch/arm/mach-sa1100/h3xxx.c
arch/mips/alchemy/devboards/db1300.c
arch/mips/bcm47xx/buttons.c
arch/sh/boards/mach-rsk/devices-rsk7203.c
arch/sh/boards/mach-x3proto/setup.c
drivers/input/misc/soc_button_array.c
drivers/mfd/ucb1x00-assabet.c
Do you already have patches for more of these? I would like to
kill off mv78xx0, orion5x and sa1100 board files (including
the ucb1x00-assabet mfd driver) soon, but that still leaves s3c,
alchemy, bcm47xx, rsk and x3proto. These platforms are in
varying states of disrepair, maybe a few more of those
can be removed instead of converted. I know that Mark
Brown is still using the s3c board, and Waldemar Brodkorb
was recently working on restoring bcm47xx into a usable
state.
I assume you'll take care of the soc_button_array one.
Arnd
^ permalink raw reply
* [PATCH 00/10] iio: drop redundant iio_dev argument from hid_sensor_remove_trigger()
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
The iio_dev argument has been unused since buffer cleanup moved out of
hid_sensor_remove_trigger(). All required resources are tracked via
hid_sensor_common, making the extra argument redundant and allowing
future devm conversion.
This is a mechanical change with no functional impact.
Testing:
- Compiled with W=1
- Build-tested on QEMU x86_64
Feedback and reviews are very welcome.
Thanks,
Sanjay Chitroda
Sanjay Chitroda (10):
iio: hid-sensors: drop redundant iio_dev argument
iio: orientation: adapt to hid_sensor_remove_trigger() API change
iio: gyro: adapt to hid_sensor_remove_trigger() API change
iio: pressure: adapt to hid_sensor_remove_trigger() API change
iio: temperature: adapt to hid_sensor_remove_trigger() API change
iio: humidity: adapt to hid_sensor_remove_trigger() API change
iio: light: adapt to hid_sensor_remove_trigger() API change
iio: magnetometer: adapt to hid_sensor_remove_trigger() API change
iio: position: adapt to hid_sensor_remove_trigger() API change
iio: accel: adapt to hid_sensor_remove_trigger() API change
drivers/iio/accel/hid-sensor-accel-3d.c | 4 ++--
drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 3 +--
drivers/iio/common/hid-sensors/hid-sensor-trigger.h | 3 +--
drivers/iio/gyro/hid-sensor-gyro-3d.c | 4 ++--
drivers/iio/humidity/hid-sensor-humidity.c | 4 ++--
drivers/iio/light/hid-sensor-als.c | 4 ++--
drivers/iio/light/hid-sensor-prox.c | 4 ++--
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 ++--
drivers/iio/orientation/hid-sensor-incl-3d.c | 4 ++--
drivers/iio/orientation/hid-sensor-rotation.c | 4 ++--
drivers/iio/position/hid-sensor-custom-intel-hinge.c | 4 ++--
drivers/iio/pressure/hid-sensor-press.c | 4 ++--
drivers/iio/temperature/hid-sensor-temperature.c | 4 ++--
13 files changed, 24 insertions(+), 26 deletions(-)
base-commit: eade2b843d9b1f668fc1775f15611bb0a1999cd9
--
2.34.1
^ permalink raw reply
* [PATCH 01/10] iio: hid-sensors: drop redundant iio_dev argument
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
hid_sensor_remove_trigger() uses struct hid_sensor_common to release
resources acquired during trigger setup.
Earlier implementations required struct iio_dev to clean up buffers,
but with the current code this argument is no longer used and is
redundant.
Removing it simplifies the API and is a preparatory step toward
converting the trigger handling to a devm-based API.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/common/hid-sensors/hid-sensor-trigger.c | 3 +--
drivers/iio/common/hid-sensors/hid-sensor-trigger.h | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index 417c4ab8c1b2..28d050b45c74 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -218,8 +218,7 @@ static const struct iio_buffer_setup_ops hid_sensor_buffer_ops = {
.predisable = buffer_predisable,
};
-void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
- struct hid_sensor_common *attrb)
+void hid_sensor_remove_trigger(struct hid_sensor_common *attrb)
{
if (atomic_read(&attrb->runtime_pm_enable))
pm_runtime_disable(&attrb->pdev->dev);
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
index f94fca4f1edf..afec46ecbe71 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.h
@@ -16,8 +16,7 @@ extern const struct dev_pm_ops hid_sensor_pm_ops;
int hid_sensor_setup_trigger(struct iio_dev *indio_dev, const char *name,
struct hid_sensor_common *attrb);
-void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
- struct hid_sensor_common *attrb);
+void hid_sensor_remove_trigger(struct hid_sensor_common *attrb);
int hid_sensor_power_state(struct hid_sensor_common *st, bool state);
#endif
--
2.34.1
^ permalink raw reply related
* [PATCH 02/10] iio: orientation: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/orientation/hid-sensor-incl-3d.c | 4 ++--
drivers/iio/orientation/hid-sensor-rotation.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 4e23a598a3fb..56fd9c53dfc2 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -378,7 +378,7 @@ static int hid_incl_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
+ hid_sensor_remove_trigger(&incl_state->common_attributes);
return ret;
}
@@ -391,7 +391,7 @@ static void hid_incl_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_INCLINOMETER_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &incl_state->common_attributes);
+ hid_sensor_remove_trigger(&incl_state->common_attributes);
}
static const struct platform_device_id hid_incl_3d_ids[] = {
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 4a11e4555099..56fdb3412fe3 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -353,7 +353,7 @@ static int hid_dev_rot_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
+ hid_sensor_remove_trigger(&rot_state->common_attributes);
return ret;
}
@@ -366,7 +366,7 @@ static void hid_dev_rot_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &rot_state->common_attributes);
+ hid_sensor_remove_trigger(&rot_state->common_attributes);
}
static const struct platform_device_id hid_dev_rot_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 03/10] iio: gyro: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/gyro/hid-sensor-gyro-3d.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index c340cc899a7c..fe663b19e902 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -354,7 +354,7 @@ static int hid_gyro_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
+ hid_sensor_remove_trigger(&gyro_state->common_attributes);
return ret;
}
@@ -367,7 +367,7 @@ static void hid_gyro_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_GYRO_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &gyro_state->common_attributes);
+ hid_sensor_remove_trigger(&gyro_state->common_attributes);
}
static const struct platform_device_id hid_gyro_3d_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 04/10] iio: pressure: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/pressure/hid-sensor-press.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 5f1d6abda3e4..2bf5d055e175 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -319,7 +319,7 @@ static int hid_press_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
+ hid_sensor_remove_trigger(&press_state->common_attributes);
return ret;
}
@@ -332,7 +332,7 @@ static void hid_press_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_PRESSURE);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &press_state->common_attributes);
+ hid_sensor_remove_trigger(&press_state->common_attributes);
}
static const struct platform_device_id hid_press_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 05/10] iio: temperature: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/temperature/hid-sensor-temperature.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 9f628a8e5cfb..60d4fcc8043b 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -253,7 +253,7 @@ static int hid_temperature_probe(struct platform_device *pdev)
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
+ hid_sensor_remove_trigger(&temp_st->common_attributes);
return ret;
}
@@ -265,7 +265,7 @@ static void hid_temperature_remove(struct platform_device *pdev)
struct temperature_state *temp_st = iio_priv(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TEMPERATURE);
- hid_sensor_remove_trigger(indio_dev, &temp_st->common_attributes);
+ hid_sensor_remove_trigger(&temp_st->common_attributes);
}
static const struct platform_device_id hid_temperature_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 06/10] iio: humidity: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/humidity/hid-sensor-humidity.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index be2338d5f407..e580a2af9562 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -255,7 +255,7 @@ static int hid_humidity_probe(struct platform_device *pdev)
error_remove_callback:
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
+ hid_sensor_remove_trigger(&humid_st->common_attributes);
return ret;
}
@@ -268,7 +268,7 @@ static void hid_humidity_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_HUMIDITY);
- hid_sensor_remove_trigger(indio_dev, &humid_st->common_attributes);
+ hid_sensor_remove_trigger(&humid_st->common_attributes);
}
static const struct platform_device_id hid_humidity_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 07/10] iio: light: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/light/hid-sensor-als.c | 4 ++--
drivers/iio/light/hid-sensor-prox.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 384572844162..9b57cdced18a 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -432,7 +432,7 @@ static int hid_als_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
+ hid_sensor_remove_trigger(&als_state->common_attributes);
return ret;
}
@@ -445,7 +445,7 @@ static void hid_als_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &als_state->common_attributes);
+ hid_sensor_remove_trigger(&als_state->common_attributes);
}
static const struct platform_device_id hid_als_ids[] = {
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index efa904a70d0e..473c45626487 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -340,7 +340,7 @@ static int hid_prox_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
+ hid_sensor_remove_trigger(&prox_state->common_attributes);
return ret;
}
@@ -353,7 +353,7 @@ static void hid_prox_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &prox_state->common_attributes);
+ hid_sensor_remove_trigger(&prox_state->common_attributes);
}
static const struct platform_device_id hid_prox_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 08/10] iio: magnetometer: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index b01dd53eb100..8be3dfe4dd58 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -542,7 +542,7 @@ static int hid_magn_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
+ hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
return ret;
}
@@ -555,7 +555,7 @@ static void hid_magn_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_COMPASS_3D);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &magn_state->magn_flux_attributes);
+ hid_sensor_remove_trigger(&magn_state->magn_flux_attributes);
}
static const struct platform_device_id hid_magn_3d_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 09/10] iio: position: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/position/hid-sensor-custom-intel-hinge.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
index a26d391661fd..5288b63f4e21 100644
--- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
+++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
@@ -337,7 +337,7 @@ static int hid_hinge_probe(struct platform_device *pdev)
error_remove_callback:
sensor_hub_remove_callback(hsdev, hsdev->usage);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &st->common_attributes);
+ hid_sensor_remove_trigger(&st->common_attributes);
return ret;
}
@@ -350,7 +350,7 @@ static void hid_hinge_remove(struct platform_device *pdev)
iio_device_unregister(indio_dev);
sensor_hub_remove_callback(hsdev, hsdev->usage);
- hid_sensor_remove_trigger(indio_dev, &st->common_attributes);
+ hid_sensor_remove_trigger(&st->common_attributes);
}
static const struct platform_device_id hid_hinge_ids[] = {
--
2.34.1
^ permalink raw reply related
* [PATCH 10/10] iio: accel: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 7:16 UTC (permalink / raw)
To: jikos, jic23, srinivas.pandruvada
Cc: dlechner, nuno.sa, andy, sakari.ailus, sanjayembeddedse,
linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-1-sanjayembedded@gmail.com>
From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
Update the driver to match the updated hid_sensor_remove_trigger()
prototype, which no longer requires struct iio_dev.
Signed-off-by: Sanjay Chitroda <sanjayembeddedse@gmail.com>
---
drivers/iio/accel/hid-sensor-accel-3d.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 2ff591b3458f..a63dae90dadc 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -416,7 +416,7 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
error_iio_unreg:
iio_device_unregister(indio_dev);
error_remove_trigger:
- hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
+ hid_sensor_remove_trigger(&accel_state->common_attributes);
return ret;
}
@@ -429,7 +429,7 @@ static void hid_accel_3d_remove(struct platform_device *pdev)
sensor_hub_remove_callback(hsdev, hsdev->usage);
iio_device_unregister(indio_dev);
- hid_sensor_remove_trigger(indio_dev, &accel_state->common_attributes);
+ hid_sensor_remove_trigger(&accel_state->common_attributes);
}
static const struct platform_device_id hid_accel_3d_ids[] = {
--
2.34.1
^ permalink raw reply related
* Re: [PATCH 02/10] iio: orientation: adapt to hid_sensor_remove_trigger() API change
From: Andy Shevchenko @ 2026-04-28 8:22 UTC (permalink / raw)
To: Sanjay Chitroda
Cc: jikos, jic23, srinivas.pandruvada, dlechner, nuno.sa, andy,
sakari.ailus, linux-input, linux-iio, linux-kernel
In-Reply-To: <20260428071613.1134053-3-sanjayembedded@gmail.com>
On Tue, Apr 28, 2026 at 12:46:05PM +0530, Sanjay Chitroda wrote:
> Update the driver to match the updated hid_sensor_remove_trigger()
> prototype, which no longer requires struct iio_dev.
You haven't compiled the previous patch, right?
This is not the way how all this should be done.
Also NAK to the patch 1 as even unused parameter is there for the sake of
consistency. The prototype to allocate and other in the similar group all
have it.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH] HID: uclogic: Fix regression of input name assignment
From: Takashi Iwai @ 2026-04-28 8:33 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Henry Martin, linux-input, linux-kernel
The previous fix for adding the devm_kasprintf() return check in the
commit bd07f751208b ("HID: uclogic: Add NULL check in
uclogic_input_configured()") changed the condition of hi->input->name
assignment, and it resulted in missing the proper input device name
when no custom suffix is defined.
Restore the conditional to the original content to address the
regression.
Fixes: bd07f751208b ("HID: uclogic: Add NULL check in uclogic_input_configured()")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
drivers/hid/hid-uclogic-core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c
index bd7f93e96e4e..b73f09d26688 100644
--- a/drivers/hid/hid-uclogic-core.c
+++ b/drivers/hid/hid-uclogic-core.c
@@ -184,7 +184,9 @@ static int uclogic_input_configured(struct hid_device *hdev,
suffix = "System Control";
break;
}
- } else {
+ }
+
+ if (suffix) {
hi->input->name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
"%s %s", hdev->name, suffix);
if (!hi->input->name)
--
2.54.0
^ permalink raw reply related
* [PATCH v2 0/2] input: misc: add support for Imagis ISA1200 haptic motor driver
From: Svyatoslav Ryhel @ 2026-04-28 11:43 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
The ISA1200 is a haptic feedback unit from Imagis Technology using two
motors for haptic feedback in mobile phones. Used in many mobile devices
c. 2012 including Samsung Galxy S Advance GT-I9070 (Janice), Samsung Beam
GT-I8350 (Gavini), LG Optimus 4X P880 and LG Optimus Vu P895.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
---
Changes in v2:
- imagis,clk-div switched to accept actual divider value
- dropped DT header
- adjusted imagis,period-ns range
- initiated hctrl0 and hctrl1 values in isa1200_start
- fixed situation when PWM might return -EPROBE_DEFER to be
treated properly
- added chech a clock or PWM is available
- fixed regulator voltages check being off by 10
- added chech if state.period is not zero
- added action call to disable clock and gpios on error
- used managed version of work init
- added work cancel on suspend
- PW calls are done under mutex lock
---
Linus Walleij (1):
Input: isa1200 - new driver for Imagis ISA1200
Svyatoslav Ryhel (1):
dt-bindings: input: Document Imagis ISA1200 haptic motor driver
.../bindings/input/imagis,isa1200.yaml | 140 +++++
drivers/input/misc/Kconfig | 11 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/isa1200.c | 507 ++++++++++++++++++
4 files changed, 659 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/imagis,isa1200.yaml
create mode 100644 drivers/input/misc/isa1200.c
--
2.51.0
^ permalink raw reply
* [PATCH v2 1/2] dt-bindings: input: Document Imagis ISA1200 haptic motor driver
From: Svyatoslav Ryhel @ 2026-04-28 11:43 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
In-Reply-To: <20260428114308.113253-1-clamor95@gmail.com>
Document the Imagis ISA1200 haptic motor driver, used primarily in mobile
handheld devices and capable of supporting up to two motors.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
.../bindings/input/imagis,isa1200.yaml | 140 ++++++++++++++++++
1 file changed, 140 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/imagis,isa1200.yaml
diff --git a/Documentation/devicetree/bindings/input/imagis,isa1200.yaml b/Documentation/devicetree/bindings/input/imagis,isa1200.yaml
new file mode 100644
index 000000000000..40a4c7fd78bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/imagis,isa1200.yaml
@@ -0,0 +1,140 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/imagis,isa1200.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagis ISA1200 haptic motor driver
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+ - Linus Walleij <linusw@kernel.org>
+
+description:
+ The ISA1200 is a high-performance enhanced haptic motor driver designed
+ for mobile hand-held devices. It supports various voltages for both ERM
+ (Eccentric Rotating Mass) and LRA (Linear Resonant Actuator) type
+ actuators. Thanks to an embedded LDO, battery power can be used directly
+ in handheld applications.
+
+properties:
+ compatible:
+ const: imagis,isa1200
+
+ reg:
+ maxItems: 1
+
+ control-gpios:
+ description:
+ One or two GPIOs flagged as active high linked to HEN and LEN pins
+ maxItems: 2
+
+ clocks:
+ maxItems: 1
+
+ pwms:
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Regulator for 2.4V - 5.5V power supply
+
+ vddp-supply:
+ description:
+ Regulator for 2.4V - 3.6V IO power supply
+
+ imagis,clk-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Divider for the external input clock/PWM
+ enum: [128, 256, 512, 1024]
+ default: 128
+
+ imagis,pll-div:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Divider for the internal PLL clock
+ minimum: 1
+ maximum: 15
+ default: 1
+
+ imagis,mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Defines the motor type isa1200 drives
+ 0 - LRA (Linear Resonant Actuator)
+ 1 - ERM (Eccentric Rotating Mass)
+ enum: [0, 1]
+ default: 0
+
+ imagis,period-ns:
+ description:
+ Period of the internal PWM channel in nanoseconds.
+ minimum: 12800
+ maximum: 25400
+
+ imagis,duty-cycle-ns:
+ description:
+ Duty cycle of the external/internal PWM channel in nanoseconds,
+ defaults to 50% of the channel's period
+
+ ldo:
+ $ref: /schemas/regulator/regulator.yaml#
+ type: object
+ description:
+ Embedded LDO regulator with voltage range 2.3V - 3.8V
+ unevaluatedProperties: false
+
+ required:
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+required:
+ - compatible
+ - reg
+ - ldo
+
+anyOf:
+ - required:
+ - clocks
+ - imagis,period-ns
+ - required:
+ - pwms
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ haptic-engine@49 {
+ compatible = "imagis,isa1200";
+ reg = <0x49>;
+
+ clocks = <&isa1200_refclk>;
+
+ control-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>,
+ <&gpio 23 GPIO_ACTIVE_HIGH>;
+
+ vdd-supply = <&vdd_3v3_vbat>;
+ vddp-supply = <&vdd_2v8_vvib>;
+
+ imagis,clk-div = <256>;
+ imagis,pll-div = <2>;
+
+ imagis,mode = <0>; /* LRA_MODE */
+
+ imagis,period-ns = <13400>;
+ imagis,duty-cycle-ns = <100>;
+
+ ldo {
+ regulator-name = "vdd_vib";
+ regulator-min-microvolt = <2300000>;
+ regulator-max-microvolt = <2300000>;
+ };
+ };
+ };
--
2.51.0
^ permalink raw reply related
* [PATCH v2 2/2] Input: isa1200 - new driver for Imagis ISA1200
From: Svyatoslav Ryhel @ 2026-04-28 11:43 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Linus Walleij, Svyatoslav Ryhel
Cc: linux-input, devicetree, linux-kernel
In-Reply-To: <20260428114308.113253-1-clamor95@gmail.com>
From: Linus Walleij <linusw@kernel.org>
The ISA1200 is a haptic feedback unit from Imagis Technology using two
motors for haptic feedback in mobile phones. Used in many mobile devices
c. 2012 including Samsung Galxy S Advance GT-I9070 (Janice), Samsung Beam
GT-I8350 (Gavini), LG Optimus 4X P880 and LG Optimus Vu P895.
The exact datasheet for the ISA1200 is not available; all data was modeled
based on available downstream kernel sources for various devices and
fragments of information scattered across the internet.
Signed-off-by: Linus Walleij <linusw@kernel.org>
Co-developed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/input/misc/Kconfig | 11 +
drivers/input/misc/Makefile | 1 +
drivers/input/misc/isa1200.c | 507 +++++++++++++++++++++++++++++++++++
3 files changed, 519 insertions(+)
create mode 100644 drivers/input/misc/isa1200.c
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 94a753fcb64f..5e5d46f44b91 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -852,6 +852,17 @@ config INPUT_IQS7222
To compile this driver as a module, choose M here: the
module will be called iqs7222.
+config INPUT_ISA1200_HAPTIC
+ tristate "Imagis ISA1200 haptic feedback unit"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say Y to enable support for the Imagis ISA1200 haptic
+ feedback unit.
+
+ To compile this driver as a module, choose M here: the
+ module will be called isa1200.
+
config INPUT_CMA3000
tristate "VTI CMA3000 Tri-axis accelerometer"
help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415fc4e2918b..d62bf2e9d85f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o
obj-$(CONFIG_INPUT_IQS269A) += iqs269a.o
obj-$(CONFIG_INPUT_IQS626A) += iqs626a.o
obj-$(CONFIG_INPUT_IQS7222) += iqs7222.o
+obj-$(CONFIG_INPUT_ISA1200_HAPTIC) += isa1200.o
obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o
diff --git a/drivers/input/misc/isa1200.c b/drivers/input/misc/isa1200.c
new file mode 100644
index 000000000000..9a9d980ae47f
--- /dev/null
+++ b/drivers/input/misc/isa1200.c
@@ -0,0 +1,507 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/array_size.h>
+#include <linux/bitmap.h>
+#include <linux/bits.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/devm-helpers.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+/*
+ * System control (LDO regulator)
+ *
+ * LDO voltage to register mapping is linear, but it is split in two parts:
+ * 2.3V - 3.0V map to 0x08 - 0x0f; 3.1V - 3.8V map to 0x00 - 0x7
+ */
+
+#define ISA1200_SCTRL 0x00
+#define ISA1200_LDO_VOLTAGE_BASE 0x08
+#define ISA1200_LDO_VOLTAGE_STEP 100000
+#define ISA1200_LDO_VOLTAGE_2V3 23
+#define ISA1200_LDO_VOLTAGE_3V1 31
+
+/*
+ * The output frequency is calculated with this formula:
+ *
+ * base clock frequency
+ * fout = -----------------------------------------
+ * (128 - PWM_FREQ) * 2 * PLLDIV * PWM_PERIOD
+ *
+ * The base clock frequency is the clock frequency provided on the
+ * clock input to the chip, divided by the value in HCTRL0
+ *
+ * PWM_FREQ is configured in register HCTRL4, it is common to set this
+ * to 0 to get only two variables to calculate.
+ *
+ * PLLDIV is configured in register HCTRL3 (bits 7..4, so 0..15)
+ * PWM_PERIOD is configured in register HCTRL6
+ * Further the duty cycle can be configured in HCTRL5
+ */
+
+/*
+ * HCTRL0 configures clock or PWM input and selects the divider for
+ * the clock input.
+ */
+#define ISA1200_HCTRL0 0x30
+#define ISA1200_HCTRL0_HAP_ENABLE BIT(7)
+#define ISA1200_HCTRL0_PWM_GEN_MODE BIT(4)
+#define ISA1200_HCTRL0_PWM_INPUT_MODE BIT(3)
+#define ISA1200_HCTRL0_CLKDIV_128 128
+
+/*
+ * HCTRL1 configures the motor type and clock sourse
+ */
+#define ISA1200_HCTRL1 0x31
+#define ISA1200_HCTRL1_EXT_CLOCK BIT(7)
+#define ISA1200_HCTRL1_DAC_INVERT BIT(6)
+#define ISA1200_HCTRL1_MODE(n) ((n) << 5)
+
+/* HCTRL2 controls software reset of the chip */
+#define ISA1200_HCTRL2 0x32
+#define ISA1200_HCTRL2_SW_RESET BIT(0)
+
+/*
+ * HCTRL3 controls the PLL divisor
+ *
+ * Bits [0,1] are always set to 1 (we don't know what they are
+ * used for) and bit 4 and upward control the PLL divisor.
+ */
+#define ISA1200_HCTRL3 0x33
+#define ISA1200_HCTRL3_DEFAULT 0x03
+#define ISA1200_HCTRL3_PLLDIV(n) (((n) & 0xf) << 4)
+
+/* HCTRL4 controls the PWM frequency of external channel */
+#define ISA1200_HCTRL4 0x34
+
+/* HCTRL5 controls the PWM high duty cycle of internal channel */
+#define ISA1200_HCTRL5 0x35
+
+/* HCTRL6 controls the PWM period of internal channel */
+#define ISA1200_HCTRL6 0x36
+#define ISA1200_HCTRL6_PERIOD_SCALE 100
+
+/* The use for these registers is unknown but they exist */
+#define ISA1200_HCTRL7 0x37
+#define ISA1200_HCTRL8 0x38
+#define ISA1200_HCTRL9 0x39
+#define ISA1200_HCTRLA 0x3a
+#define ISA1200_HCTRLB 0x3b
+#define ISA1200_HCTRLC 0x3c
+#define ISA1200_HCTRLD 0x3d
+
+#define ISA1200_EN_PINS_MAX 2
+
+struct isa1200_config {
+ u32 ldo_voltage;
+ u32 mode;
+ u32 clkdiv;
+ u32 plldiv;
+ u32 freq;
+ u32 period;
+ u32 duty;
+};
+
+struct isa1200 {
+ struct input_dev *input;
+ struct regmap *map;
+
+ struct clk *clk;
+ struct pwm_device *pwm;
+ struct gpio_descs *enable_gpios;
+
+ struct work_struct play_work;
+ struct isa1200_config config;
+
+ int level;
+};
+
+static const struct regmap_config isa1200_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = ISA1200_HCTRLD,
+};
+
+static void isa1200_start(struct isa1200 *isa)
+{
+ struct isa1200_config *config = &isa->config;
+ struct pwm_state state;
+ u8 hctrl0 = 0, hctrl1 = 0;
+ DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
+
+ clk_prepare_enable(isa->clk);
+
+ bitmap_fill(values, ISA1200_EN_PINS_MAX);
+ gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
+
+ usleep_range(200, 300);
+
+ regmap_write(isa->map, ISA1200_SCTRL, config->ldo_voltage);
+
+ if (isa->clk) {
+ hctrl0 = ISA1200_HCTRL0_PWM_GEN_MODE;
+ hctrl1 = ISA1200_HCTRL1_EXT_CLOCK;
+ }
+
+ if (isa->pwm) {
+ hctrl0 = ISA1200_HCTRL0_PWM_INPUT_MODE;
+ hctrl1 = 0;
+ }
+
+ hctrl0 |= __ffs(config->clkdiv / ISA1200_HCTRL0_CLKDIV_128);
+ hctrl1 |= ISA1200_HCTRL1_DAC_INVERT;
+ hctrl1 |= ISA1200_HCTRL1_MODE(config->mode);
+
+ regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
+ regmap_write(isa->map, ISA1200_HCTRL1, hctrl1);
+
+ /* Make sure to de-assert software reset */
+ regmap_write(isa->map, ISA1200_HCTRL2, 0x00);
+
+ /* PLL divisor */
+ regmap_write(isa->map, ISA1200_HCTRL3,
+ ISA1200_HCTRL3_PLLDIV(config->plldiv) |
+ ISA1200_HCTRL3_DEFAULT);
+
+ /* Frequency */
+ regmap_write(isa->map, ISA1200_HCTRL4, config->freq);
+ /* Duty cycle */
+ regmap_write(isa->map, ISA1200_HCTRL5, config->period >> 1);
+ /* Period */
+ regmap_write(isa->map, ISA1200_HCTRL6, config->period);
+
+ hctrl0 |= ISA1200_HCTRL0_HAP_ENABLE;
+ regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
+
+ if (isa->clk)
+ regmap_write(isa->map, ISA1200_HCTRL5, config->duty);
+
+ if (isa->pwm) {
+ pwm_get_state(isa->pwm, &state);
+ state.duty_cycle = config->duty;
+ state.enabled = true;
+ pwm_apply_might_sleep(isa->pwm, &state);
+ }
+}
+
+static void isa1200_power_off(void *data)
+{
+ struct isa1200 *isa = data;
+
+ DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
+
+ bitmap_zero(values, ISA1200_EN_PINS_MAX);
+ gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
+
+ clk_disable_unprepare(isa->clk);
+}
+
+static void isa1200_stop(struct isa1200 *isa)
+{
+ struct pwm_state state;
+
+ if (isa->pwm) {
+ pwm_get_state(isa->pwm, &state);
+ state.duty_cycle = 0;
+ state.enabled = false;
+ pwm_apply_might_sleep(isa->pwm, &state);
+ }
+
+ regmap_write(isa->map, ISA1200_HCTRL0, 0x00);
+ isa1200_power_off(isa);
+}
+
+static void isa1200_play_work(struct work_struct *work)
+{
+ struct isa1200 *isa =
+ container_of(work, struct isa1200, play_work);
+
+ if (isa->level)
+ isa1200_start(isa);
+ else
+ isa1200_stop(isa);
+}
+
+static int isa1200_vibrator_play_effect(struct input_dev *input, void *data,
+ struct ff_effect *effect)
+{
+ struct isa1200 *isa = input_get_drvdata(input);
+ int level;
+
+ /*
+ * TODO: we currently only support rumble.
+ * The ISA1200 can control two motors and some devices
+ * also have two motors mounted.
+ */
+ level = effect->u.rumble.strong_magnitude;
+ if (!level)
+ level = effect->u.rumble.weak_magnitude;
+
+ dev_dbg(&input->dev, "FF effect type %d level %d\n",
+ effect->type, level);
+
+ if (isa->level != level) {
+ isa->level = level;
+ schedule_work(&isa->play_work);
+ }
+
+ return 0;
+}
+
+static void isa1200_vibrator_close(struct input_dev *input)
+{
+ struct isa1200 *isa = input_get_drvdata(input);
+
+ cancel_work_sync(&isa->play_work);
+
+ if (isa->level)
+ isa1200_stop(isa);
+
+ isa->level = 0;
+}
+
+static int isa1200_of_probe(struct i2c_client *client)
+{
+ static const char * const isa1200_supplies[] = { "vdd", "vddp" };
+ struct isa1200 *isa = i2c_get_clientdata(client);
+ struct isa1200_config *config = &isa->config;
+ struct device *dev = &client->dev;
+ struct fwnode_handle *ldo_node;
+ int ret;
+
+ isa->clk = devm_clk_get_optional(dev, NULL);
+ if (IS_ERR(isa->clk))
+ return dev_err_probe(dev, PTR_ERR(isa->clk),
+ "failed to get clock\n");
+
+ isa->pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(isa->pwm)) {
+ ret = PTR_ERR(isa->pwm);
+ if (ret == -ENODEV || ret == -EINVAL)
+ isa->pwm = NULL;
+ else
+ return dev_err_probe(dev, ret, "getting PWM\n");
+ }
+
+ if (!isa->clk && !isa->pwm)
+ return dev_err_probe(dev, -EINVAL,
+ "clock or PWM are required, none were provided\n");
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(isa1200_supplies),
+ isa1200_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to set up supplies\n");
+
+ isa->enable_gpios = devm_gpiod_get_array_optional(dev, "control",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(isa->enable_gpios))
+ return dev_err_probe(dev, PTR_ERR(isa->enable_gpios),
+ "failed to get enable gpios\n");
+
+ ldo_node = device_get_named_child_node(dev, "ldo");
+ if (!ldo_node)
+ return dev_err_probe(dev, -ENODEV,
+ "failed to get embedded LDO node\n");
+
+ config->ldo_voltage = 2300000;
+ ret = fwnode_property_read_u32(ldo_node, "regulator-min-microvolt",
+ &config->ldo_voltage);
+ fwnode_handle_put(ldo_node);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get ldo voltage\n");
+
+ /* Device supports only 2.3V - 3.8V range */
+ if (config->ldo_voltage < 2300000 || config->ldo_voltage > 3800000)
+ return dev_err_probe(dev, -EINVAL,
+ "voltage is out of 2.3V - 3.8V range\n");
+
+ config->ldo_voltage /= ISA1200_LDO_VOLTAGE_STEP;
+ if (config->ldo_voltage < ISA1200_LDO_VOLTAGE_3V1)
+ config->ldo_voltage = config->ldo_voltage -
+ ISA1200_LDO_VOLTAGE_2V3 +
+ ISA1200_LDO_VOLTAGE_BASE;
+ else
+ config->ldo_voltage -= ISA1200_LDO_VOLTAGE_3V1;
+
+ config->mode = 0; /* LRA_MODE */
+ device_property_read_u32(dev, "imagis,mode", &config->mode);
+
+ config->clkdiv = ISA1200_HCTRL0_CLKDIV_128;
+ device_property_read_u32(dev, "imagis,clk-div", &config->clkdiv);
+ if (!config->clkdiv)
+ return dev_err_probe(dev, -EINVAL, "clk-div cannot be zero\n");
+
+ config->plldiv = 1;
+ device_property_read_u32(dev, "imagis,pll-div", &config->plldiv);
+
+ config->period = 0;
+ config->freq = 0;
+ config->duty = 0;
+
+ if (isa->clk) {
+ ret = device_property_read_u32(dev, "imagis,period-ns",
+ &config->period);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get period\n");
+
+ config->period /= ISA1200_HCTRL6_PERIOD_SCALE;
+ config->duty = config->period >> 1;
+ }
+
+ if (isa->pwm) {
+ struct pwm_state state;
+
+ pwm_init_state(isa->pwm, &state);
+
+ if (!state.period)
+ return dev_err_probe(dev, -EINVAL,
+ "PWM period cannot be zero\n");
+
+ config->freq = div64_u64(NANO, state.period * config->clkdiv);
+ config->duty = state.period >> 1;
+
+ ret = pwm_apply_might_sleep(isa->pwm, &state);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to apply initial PWM state\n");
+ }
+
+ device_property_read_u32(dev, "imagis,duty-cycle-ns", &config->duty);
+
+ return 0;
+}
+
+static int isa1200_probe(struct i2c_client *client)
+{
+ struct isa1200 *isa;
+ struct device *dev = &client->dev;
+ DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
+ u32 val;
+ int ret;
+
+ isa = devm_kzalloc(dev, sizeof(*isa), GFP_KERNEL);
+ if (!isa)
+ return -ENOMEM;
+
+ isa->input = devm_input_allocate_device(dev);
+ if (!isa->input)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, isa);
+
+ ret = isa1200_of_probe(client);
+ if (ret)
+ return ret;
+
+ isa->map = devm_regmap_init_i2c(client, &isa1200_regmap_config);
+ if (IS_ERR(isa->map))
+ return dev_err_probe(dev, PTR_ERR(isa->map),
+ "failed to initialize register map\n");
+
+ clk_prepare_enable(isa->clk);
+
+ bitmap_fill(values, ISA1200_EN_PINS_MAX);
+ gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
+
+ ret = devm_add_action_or_reset(dev, isa1200_power_off, isa);
+ if (ret)
+ return ret;
+
+ usleep_range(200, 300);
+
+ /* Read a register so we know that regmap and I2C transport works */
+ ret = regmap_read(isa->map, ISA1200_SCTRL, &val);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to read SCTRL\n");
+
+ ret = devm_work_autocancel(dev, &isa->play_work, isa1200_play_work);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init work\n");
+
+ isa->input->name = "isa1200-haptic";
+ isa->input->id.bustype = BUS_HOST;
+ isa->input->dev.parent = dev;
+ isa->input->close = isa1200_vibrator_close;
+
+ input_set_drvdata(isa->input, isa);
+
+ /* TODO: this hardware can likely support more than rumble */
+ input_set_capability(isa->input, EV_FF, FF_RUMBLE);
+
+ ret = input_ff_create_memless(isa->input, NULL,
+ isa1200_vibrator_play_effect);
+ if (ret)
+ return dev_err_probe(dev, ret, "couldn't create FF dev\n");
+
+ ret = input_register_device(isa->input);
+ if (ret)
+ return dev_err_probe(dev, ret, "couldn't register input dev\n");
+
+ return ret;
+}
+
+static int isa1200_suspend(struct device *dev)
+{
+ struct isa1200 *isa = dev_get_drvdata(dev);
+ struct input_dev *input_dev = isa->input;
+
+ guard(mutex)(&input_dev->mutex);
+
+ if (input_device_enabled(input_dev)) {
+ cancel_work_sync(&isa->play_work);
+ if (isa->level)
+ isa1200_stop(isa);
+ }
+
+ return 0;
+}
+
+static int isa1200_resume(struct device *dev)
+{
+ struct isa1200 *isa = dev_get_drvdata(dev);
+ struct input_dev *input_dev = isa->input;
+
+ guard(mutex)(&input_dev->mutex);
+
+ if (input_device_enabled(input_dev))
+ if (isa->level)
+ isa1200_start(isa);
+
+ return 0;
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(isa1200_pm_ops, isa1200_suspend, isa1200_resume);
+
+static const struct of_device_id isa1200_of_match[] = {
+ { .compatible = "imagis,isa1200" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, isa1200_of_match);
+
+static struct i2c_driver isa1200_i2c_driver = {
+ .driver = {
+ .name = "isa1200",
+ .of_match_table = isa1200_of_match,
+ .pm = pm_sleep_ptr(&isa1200_pm_ops),
+ },
+ .probe = isa1200_probe,
+};
+module_i2c_driver(isa1200_i2c_driver);
+
+MODULE_AUTHOR("Linus Walleij <linusw@kernel.org>");
+MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
+MODULE_DESCRIPTION("Imagis ISA1200 haptic feedback unit");
+MODULE_LICENSE("GPL");
--
2.51.0
^ permalink raw reply related
* Re: [PATCH 02/10] iio: orientation: adapt to hid_sensor_remove_trigger() API change
From: Sanjay Chitroda @ 2026-04-28 12:06 UTC (permalink / raw)
To: Andy Shevchenko
Cc: jikos, jic23, srinivas.pandruvada, dlechner, nuno.sa, andy,
sakari.ailus, linux-input, linux-iio, linux-kernel
In-Reply-To: <afBuWAElmx7t7FcB@ashevche-desk.local>
On 28 April 2026 1:52:48 pm IST, Andy Shevchenko <andriy.shevchenko@intel.com> wrote:
>On Tue, Apr 28, 2026 at 12:46:05PM +0530, Sanjay Chitroda wrote:
>
>> Update the driver to match the updated hid_sensor_remove_trigger()
>> prototype, which no longer requires struct iio_dev.
>
>You haven't compiled the previous patch, right?
>This is not the way how all this should be done.
>
>Also NAK to the patch 1 as even unused parameter is there for the sake of
>consistency. The prototype to allocate and other in the similar group all
>have it.
Hi Andy,
Thank for the review comment.
I agree your point for consistency.
However primary object of this pre-series is to prepare the drivers for devm_ conversation.
I would prepare devm_ wrapper for the hid_sensor_setup_trigger() and respective resource release hid_sensor_remove_trigger().
... devm_hid_sensor_setup_trigger( ... )
{
...
.. hid_sensor_setup_trigger();
....
devm_add_action_or_release(dev, hid_sensor_remove_trigger, attrb)
......
}
I observed that many HID IIO drivers are not covered fully with managed API.
This devm_* sensor setup trigger would use across multiple HID IIO sensors and will go step forward for managed API support.
>
^ permalink raw reply
* Re: [PATCH] platform/x86/lenovo: Add Yoga Book 9 keyboard dock detection driver
From: Ilpo Järvinen @ 2026-04-28 14:39 UTC (permalink / raw)
To: Dave Carey, Hans de Goede, Pit Henrich
Cc: platform-driver-x86, LKML, linux-input
In-Reply-To: <20260425132323.82809-1-carvsdriver@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 14388 bytes --]
On Sat, 25 Apr 2026, Dave Carey wrote:
> The Lenovo Yoga Book 9 14IAH10 ships with a detachable Bluetooth keyboard
> that magnetically attaches to the bottom (secondary) screen in one of two
> positions.
> The Embedded Controller tracks the attachment state in a 2-bit
> field called BKBD and signals changes via WMI event GUID
> 806BD2A2-177B-481D-BFB5-3BA0BB4A2285 (notify ID 0xEB on the WM10 ACPI
> device).
Please put this in depth explanation in own paragraph.
> The current BKBD state is read via WMI query GUID
> E7F300FA-21CD-4003-ADAC-2696135982E6 (WQAF method),
This seems mostly duplicate of what was said previously.
>which returns an
> 8-byte buffer: bytes [0..3] hold the LFID constant 0x00060000 and bytes
> [4..7] hold the BKBD value.
>
> BKBD encoding:
> 0 = keyboard detached
> 1 = keyboard docked on top half of bottom screen
> 2 = keyboard docked on bottom half of bottom screen
> 3 = reserved (not observed in practice)
These two can be combined with the in depth explanation paragraph.
> This driver:
> - Registers as a WMI driver on the event GUID.
Unnecessary / obvious.
> - Queries BKBD state on probe and on each WMI notification.
> - Reports SW_TABLET_MODE=1 when detached, SW_TABLET_MODE=0 when docked
> in either position (a physical keyboard is present in both cases).
> - Exposes the raw BKBD value via a read-only sysfs attribute
> "keyboard_position" for use by userspace (e.g. to distinguish between
> the two docked positions for different UI layouts).
Please write this without bullet points. Bullet points usually break
relationships between sentences.
> Tested on: Lenovo Yoga Book 9 14IAH10 (model 83KJ), kernel 6.19.
>
> Signed-off-by: Dave Carey <carvsdriver@gmail.com>
> ---
> .../testing/sysfs-driver-lenovo-yb9-kbdock | 21 ++
> MAINTAINERS | 6 +
> drivers/platform/x86/lenovo/Kconfig | 14 ++
> drivers/platform/x86/lenovo/Makefile | 1 +
> drivers/platform/x86/lenovo/yb9-kbdock.c | 216 ++++++++++++++++++
> 5 files changed, 258 insertions(+)
> create mode 100644 Documentation/ABI/testing/sysfs-driver-lenovo-yb9-kbdock
> create mode 100644 MAINTAINERS
> create mode 100644 drivers/platform/x86/lenovo/yb9-kbdock.c
>
> diff --git a/Documentation/ABI/testing/sysfs-driver-lenovo-yb9-kbdock b/Documentation/ABI/testing/sysfs-driver-lenovo-yb9-kbdock
> new file mode 100644
> index 0000000..bb57690
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-driver-lenovo-yb9-kbdock
> @@ -0,0 +1,21 @@
> +What: /sys/bus/wmi/drivers/lenovo-yb9-kbdock/<guid>/keyboard_position
> +Date: April 2026
> +KernelVersion: 6.10
> +Contact: Dave Carey <carvsdriver@gmail.com>
> +Description:
> + Read-only attribute reporting the current keyboard dock position
> + as reported by the Embedded Controller on the Lenovo Yoga Book 9
> + 14IAH10.
> +
> + Possible values:
> +
> + == ============================================================
> + 0 detached — keyboard is not docked to any screen
> + 1 top-half — keyboard docked on the top half of the bottom screen
> + 2 bottom-half — keyboard docked on the bottom half of the bottom screen
> + == ============================================================
Interesting, I wonder if this is similar physically to what is being added
here:
https://lore.kernel.org/all/20260419102724.91451-1-pithenrich2d@gmail.com/
?
If yes, we may have to take another look at how to create the interface
for this.
You didn't document unknown but return it (maybe it should return some
-Exx code instead?).
> + The value is formatted as "<n> (<name>)\n", e.g. "1 (top-half)\n".
> +
> + SW_TABLET_MODE input events are also emitted: 0 when the keyboard
> + is docked (either position), 1 when detached.
> diff --git a/MAINTAINERS b/MAINTAINERS
> new file mode 100644
> index 0000000..cb765b4
> --- /dev/null
> +++ b/MAINTAINERS
> @@ -0,0 +1,6 @@
> +LENOVO YOGA BOOK 9 KEYBOARD DOCK DRIVER
> +M: Dave Carey <carvsdriver@gmail.com>
> +L: platform-driver-x86@vger.kernel.org
> +S: Maintained
> +F: Documentation/ABI/testing/sysfs-driver-lenovo-yb9-kbdock
> +F: drivers/platform/x86/lenovo/yb9-kbdock.c
> diff --git a/drivers/platform/x86/lenovo/Kconfig b/drivers/platform/x86/lenovo/Kconfig
> index 9c48487..938b361 100644
> --- a/drivers/platform/x86/lenovo/Kconfig
> +++ b/drivers/platform/x86/lenovo/Kconfig
> @@ -43,6 +43,20 @@ config LENOVO_WMI_CAMERA
> To compile this driver as a module, choose M here: the module
> will be called lenovo-wmi-camera.
>
> +config LENOVO_YB9_KBDOCK
> + tristate "Lenovo Yoga Book 9 keyboard dock detection"
> + depends on ACPI_WMI
> + depends on DMI
> + depends on INPUT
> + help
> + Say Y here to enable keyboard dock detection on the Lenovo Yoga Book 9
> + 14IAH10. The detachable Bluetooth keyboard magnetically attaches to
> + either screen; this driver reports SW_TABLET_MODE input events based
> + on the attachment state and exposes the raw position in sysfs.
> +
> + To compile this driver as a module, choose M here: the module will be
> + called lenovo-yb9-kbdock.
> +
> config LENOVO_YMC
> tristate "Lenovo Yoga Tablet Mode Control"
> depends on ACPI_WMI
> diff --git a/drivers/platform/x86/lenovo/Makefile b/drivers/platform/x86/lenovo/Makefile
> index 7b2128e..2842d7d 100644
> --- a/drivers/platform/x86/lenovo/Makefile
> +++ b/drivers/platform/x86/lenovo/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_THINKPAD_LMI) += think-lmi.o
> obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
>
> lenovo-target-$(CONFIG_LENOVO_WMI_HOTKEY_UTILITIES) += wmi-hotkey-utilities.o
> +lenovo-target-$(CONFIG_LENOVO_YB9_KBDOCK) += yb9-kbdock.o
> lenovo-target-$(CONFIG_LENOVO_YMC) += ymc.o
> lenovo-target-$(CONFIG_YOGABOOK) += yogabook.o
> lenovo-target-$(CONFIG_YT2_1380) += yoga-tab2-pro-1380-fastcharger.o
> diff --git a/drivers/platform/x86/lenovo/yb9-kbdock.c b/drivers/platform/x86/lenovo/yb9-kbdock.c
> new file mode 100644
> index 0000000..693e287
> --- /dev/null
> +++ b/drivers/platform/x86/lenovo/yb9-kbdock.c
> @@ -0,0 +1,216 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Lenovo Yoga Book 9 keyboard-dock detection
> + *
> + * The Yoga Book 9 ships with a detachable Bluetooth keyboard that magnetically
> + * attaches to the bottom screen in one of two positions. The EC tracks
> + * attachment state in a 2-bit field called BKBD and signals changes via WMI
> + * event 0xEB on the WM10 ACPI device.
> + *
> + * BKBD values:
> + * 0 = keyboard detached
> + * 1 = keyboard docked on the top half of the bottom screen
> + * 2 = keyboard docked on the bottom half of the bottom screen
> + * 3 = reserved / not observed
>
> + * This driver registers for the WMI event GUID, queries BKBD on probe and on
> + * each event, reports SW_TABLET_MODE=0 when the keyboard is docked (either
> + * position) and SW_TABLET_MODE=1 when detached, and exposes the raw BKBD
> + * value in sysfs as "keyboard_position".
I don't think the functional description on this level is warranted in the
top comment (may place it below where you define things but if naming is
obvious, some comments may not even be necessary).
> + * Copyright (C) 2026 Dave Carey <carvsdriver@gmail.com>
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/dmi.h>
> +#include <linux/input.h>
> +#include <linux/module.h>
> +#include <linux/wmi.h>
> +
> +/*
> + * WM10 ACPI device (_UID "GMZN"):
> + * Event GUID — notify ID 0xEB fires on keyboard attachment change.
> + * Query GUID — object "AF", maps to WQAF(); returns 8-byte buffer
> + * {LFID=0x00060000, BKBD[31:0]}.
> + */
> +#define YB9_KBDOCK_EVENT_GUID "806BD2A2-177B-481D-BFB5-3BA0BB4A2285"
> +#define YB9_KBDOCK_QUERY_GUID "E7F300FA-21CD-4003-ADAC-2696135982E6"
> +
> +#define YB9_KBDOCK_QUERY_INSTANCE 0
> +
> +/* BKBD encoding — keyboard always docks on the bottom screen */
> +#define BKBD_DETACHED 0
> +#define BKBD_TOP_HALF 1 /* docked on top half of bottom screen */
> +#define BKBD_BOTTOM_HALF 2 /* docked on bottom half of bottom screen */
> +
> +static const struct dmi_system_id yb9_kbdock_dmi_table[] = {
> + {
> + /* Lenovo Yoga Book 9 14IAH10 */
> + .matches = {
> + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
> + DMI_MATCH(DMI_PRODUCT_NAME, "83KJ"),
> + },
> + },
> + { }
> +};
Normally these appear towards the end of the file.
> +
> +struct yb9_kbdock_priv {
> + struct input_dev *input_dev;
> + unsigned int bkbd; /* last read BKBD value (0-3) */
> +};
> +
> +/* Read current BKBD state via WQAF. Returns 0-3 or -errno. */
> +static int yb9_kbdock_query(struct wmi_device *wdev)
> +{
> + struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
> + union acpi_object *obj;
> + acpi_status status;
> + u32 bkbd;
> +
> + status = wmi_query_block(YB9_KBDOCK_QUERY_GUID,
> + YB9_KBDOCK_QUERY_INSTANCE, &out);
This interface has been deprecated.
> + if (ACPI_FAILURE(status)) {
> + dev_warn(&wdev->dev, "WQAF query failed: %s\n",
> + acpi_format_exception(status));
> + return -EIO;
> + }
> +
> + obj = out.pointer;
> + if (!obj) {
> + dev_warn(&wdev->dev, "WQAF returned NULL\n");
> + return -EIO;
> + }
> +
> + /*
> + * WQAF returns an 8-byte buffer: bytes [0..3] = LFID (0x00060000),
> + * bytes [4..7] = BKBD value. Guard against short buffers.
One space is enough.
> + */
> + if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length >= 8) {
> + memcpy(&bkbd, obj->buffer.pointer + 4, sizeof(bkbd));
> + bkbd &= 0x3;
Can this literal be named with a define? Should it use FIELD_GET()
(don't forget the header if you start to use FIELD_GET())?
> + } else if (obj->type == ACPI_TYPE_INTEGER) {
> + bkbd = obj->integer.value & 0x3;
Same question here.
> + } else {
> + dev_warn(&wdev->dev,
> + "WQAF: unexpected result type %d len %u\n",
> + obj->type,
> + obj->type == ACPI_TYPE_BUFFER
> + ? obj->buffer.length : 0);
Put the last two lines to one line.
> + kfree(obj);
> + return -EIO;
> + }
> +
> + kfree(obj);
Please use __free() instead of duplicating kfree()s.
When converting to __free(), don't use ... = NULL; pattern, instead place
the variable declaration mid-function as instructed in the long comment in
cleanup.h.
> + return (int)bkbd;
Unnecessary cast. And your types are a major mess between int and
unsigned types.
> +}
> +
> +static void yb9_kbdock_update(struct wmi_device *wdev)
> +{
> + struct yb9_kbdock_priv *priv = dev_get_drvdata(&wdev->dev);
> + int bkbd;
> + int tablet_mode;
Please use reverse-xmas tree order where there are no internal
dependencies between local variables that prevent usinbg it.
> +
> + bkbd = yb9_kbdock_query(wdev);
> + if (bkbd < 0)
> + return;
> +
> + priv->bkbd = bkbd;
> +
> + /*
> + * Report tablet mode only when the keyboard is fully detached.
> + * Both docked positions (top-half and bottom-half of the bottom screen)
> + * indicate a physical keyboard is present — report laptop mode.
> + */
> + tablet_mode = (bkbd == BKBD_DETACHED) ? 1 : 0;
> +
> + input_report_switch(priv->input_dev, SW_TABLET_MODE, tablet_mode);
> + input_sync(priv->input_dev);
> +
> + dev_dbg(&wdev->dev, "BKBD=%u tablet_mode=%d\n", bkbd, tablet_mode);
Missing include.
> +}
> +
> +static void yb9_kbdock_notify(struct wmi_device *wdev, union acpi_object *data)
> +{
> + yb9_kbdock_update(wdev);
> +}
> +
> +/* sysfs: keyboard_position — exposes raw BKBD value */
> +static ssize_t keyboard_position_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct yb9_kbdock_priv *priv = dev_get_drvdata(dev);
> + static const char * const names[] = {
> + "detached", "top-half", "bottom-half", "unknown"
Use comma for all non-terminating entries.
> + };
> + unsigned int bkbd = priv->bkbd;
> +
> + if (bkbd > 3)
How can this happen without it being bug in the driver? Didn't you mask it
when reading the value?
So maybe
if (WARN_ON_ONCE(bkbd > 3))
return -EINVAL;
> + bkbd = 3;
> + return sysfs_emit(buf, "%u (%s)\n", bkbd, names[bkbd]);
> +}
> +static DEVICE_ATTR_RO(keyboard_position);
> +
> +static struct attribute *yb9_kbdock_attrs[] = {
> + &dev_attr_keyboard_position.attr,
> + NULL,
> +};
> +ATTRIBUTE_GROUPS(yb9_kbdock);
> +
> +static int yb9_kbdock_probe(struct wmi_device *wdev, const void *ctx)
> +{
> + struct yb9_kbdock_priv *priv;
> + struct input_dev *input_dev;
> + int err;
> +
> + if (!dmi_check_system(yb9_kbdock_dmi_table)) {
> + dev_dbg(&wdev->dev, "not a Yoga Book 9, skipping\n");
> + return -ENODEV;
> + }
> +
> + priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + input_dev = devm_input_allocate_device(&wdev->dev);
> + if (!input_dev)
> + return -ENOMEM;
> +
> + input_dev->name = "Lenovo Yoga Book 9 keyboard dock switch";
> + input_dev->phys = YB9_KBDOCK_EVENT_GUID "/input0";
> + input_dev->id.bustype = BUS_HOST;
> + input_set_capability(input_dev, EV_SW, SW_TABLET_MODE);
> +
> + err = input_register_device(input_dev);
> + if (err) {
> + dev_err(&wdev->dev, "failed to register input device: %d\n", err);
> + return err;
> + }
> +
> + priv->input_dev = input_dev;
> + dev_set_drvdata(&wdev->dev, priv);
> +
> + /* Report initial state */
> + yb9_kbdock_update(wdev);
> + return 0;
> +}
> +
> +static const struct wmi_device_id yb9_kbdock_wmi_id_table[] = {
> + { .guid_string = YB9_KBDOCK_EVENT_GUID },
> + { }
> +};
> +MODULE_DEVICE_TABLE(wmi, yb9_kbdock_wmi_id_table);
> +
> +static struct wmi_driver yb9_kbdock_driver = {
> + .driver = {
> + .name = "lenovo-yb9-kbdock",
> + .dev_groups = yb9_kbdock_groups,
> + },
> + .id_table = yb9_kbdock_wmi_id_table,
> + .probe = yb9_kbdock_probe,
> + .notify = yb9_kbdock_notify,
> +};
> +module_wmi_driver(yb9_kbdock_driver);
> +
> +MODULE_AUTHOR("Dave Carey <carvsdriver@gmail.com>");
> +MODULE_DESCRIPTION("Lenovo Yoga Book 9 keyboard dock detection");
> +MODULE_LICENSE("GPL");
>
--
i.
^ permalink raw reply
* Re: [bug report] Potential order bug in 'drivers/input/misc', particularly 'ati_remote2.c', 'cm109.c', 'keyspan_remote.c'
From: Dmitry Torokhov @ 2026-04-28 15:01 UTC (permalink / raw)
To: Ginger; +Cc: linux-input
In-Reply-To: <CAGp+u1aFTivN-EC5QQaQ=j21GaGHktunHEzWQ9e2uASsE40svQ@mail.gmail.com>
Hi Ginger,
On Tue, Apr 28, 2026 at 12:18:46PM +0800, Ginger wrote:
> Dear Linux kernel maintainers,
>
> My research-based static analyzer found a potential order bug within
> the ' drivers/input/misc' subsystem. I will use the potential bug
> found in 'drivers/input/misc/ati_remote2.c' as the typical example.
> The similar potential bug patterns are also observed in 'cm109.c' and
> 'keyspan_remote.c'.
>
> Kernel version: long-term kernel v6.18.9
>
> Potential issue:
> T0:
> ati_remote2_disconnect
> --> ar2 = usb_get_intfdata(interface);
> --> usb_set_intfdata(interface, NULL);
> --> input_unregister_device(ar2->idev);
> --> usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]);
> --> kfree(ar2)
>
> T1:
> ati_remote2_store_channel_mask (registered as the device attribute
> function and exposed via the sysfs)
> --> struct ati_remote2 *ar2 = usb_get_intfdata(intf);
> --> ar2->mode_mask = mask;
>
> In T0, the interface is nullified before its get deregistered. Thus,
> it is possible for T1 to still get the usb dev and access it via the
> interface, which, however, has been already nullified or even freed.
> This similar pattern is also observed in 'cm109_usb_disconnect()' of
> file 'cm109.c' and 'keyspan_disconnect()' of file 'keyspan_remote.c'.
Driver core is supposed to remove sysfs attributes before calling
remove() or disconnect() (see drivers/base/dd.c::device_remove()) and
sysfs ensures that all threads leave sysfs show() and store() methods
before the call to delete the attributes returns.
Thanks.
--
Dmitry
^ permalink raw reply
* [PATCH v4 0/6 RESEND] mfd: cpcap: convert documentation to schema and add Mot board support
From: Svyatoslav Ryhel @ 2026-04-28 15:36 UTC (permalink / raw)
To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Lee Jones, Pavel Machek, Svyatoslav Ryhel, David Lechner,
Tony Lindgren
Cc: linux-input, devicetree, linux-kernel, linux-leds
The initial goal was only to add support for the CPCAP used in the Mot
Tegra20 board; however, since the documentation was already partially
converted, I decided to complete the conversion to schema too.
The CPCAP regulator, leds, rtc, pwrbutton and core files were converted
from TXT to YAML while preserving the original structure. Mot board
compatibility was added to the regulator and core schema. Since these
were one-line patches, they were not separated into dedicated commits;
however, the commit message notes this for both cases.
Finally, the CPCAP MFD was slightly refactored to improve support for
multiple subcell compositions.
---
Changes in v2:
- fixed code style
- rtc conversion was picked, so patch dropped
- added audio ports description into mfd schema
- splitted schema conversion and compatible addition
- minor style improvements and typo fixes
Changes in v3:
- added regulator node names list into pattern
- filled spi_device_id with driver data
- ADC patches were picked, so changes dropped
Changes in v4:
- dropped regulator patches (applied)
---
Svyatoslav Ryhel (6):
dt-bindings: leds: leds-cpcap: convert to DT schema
dt-bindings: input: cpcap-pwrbutton: convert to DT schema
dt-bindings: mfd: motorola-cpcap: convert to DT schema
dt-bindings: mfd: motorola-cpcap: document Mapphone and Mot CPCAP
mfd: motorola-cpcap: diverge configuration per-board
mfd: motorola-cpcap: add support for Mot CPCAP composition
.../bindings/input/cpcap-pwrbutton.txt | 20 -
.../input/motorola,cpcap-pwrbutton.yaml | 32 ++
.../devicetree/bindings/leds/leds-cpcap.txt | 29 --
.../bindings/leds/motorola,cpcap-leds.yaml | 42 ++
.../bindings/mfd/motorola,cpcap.yaml | 419 ++++++++++++++++++
.../bindings/mfd/motorola-cpcap.txt | 78 ----
drivers/mfd/motorola-cpcap.c | 151 ++++++-
7 files changed, 626 insertions(+), 145 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt
create mode 100644 Documentation/devicetree/bindings/input/motorola,cpcap-pwrbutton.yaml
delete mode 100644 Documentation/devicetree/bindings/leds/leds-cpcap.txt
create mode 100644 Documentation/devicetree/bindings/leds/motorola,cpcap-leds.yaml
create mode 100644 Documentation/devicetree/bindings/mfd/motorola,cpcap.yaml
delete mode 100644 Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
--
2.51.0
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox