* Re: [git pull] Input updates for v6.17-rc5
From: pr-tracker-bot @ 2025-09-14 15:43 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Linus Torvalds, linux-kernel, linux-input
In-Reply-To: <pr27r442uxseunxtnoko5fquveeb2qg7kxue7uht4marr45ais@ce4alsq7hatm>
The pull request you sent on Sat, 13 Sep 2025 18:20:39 -0700:
> git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.17-rc5
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/563b3f6ef521895045117055bf3ee08fbe27a8a7
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* Re: [RFC PATCH 0/2] Input: add fts2ba61y touchscreen driver
From: Ivaylo Ivanov @ 2025-09-14 14:53 UTC (permalink / raw)
To: Krzysztof Kozlowski, Eric Gonçalves, Dmitry Torokhov,
Henrik Rydberg, Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-input, devicetree, linux-kernel
In-Reply-To: <a700b0c4-cfaa-42a5-ac87-c2bec8d9bf2a@kernel.org>
On 9/14/25 17:47, Krzysztof Kozlowski wrote:
> On 11/09/2025 23:19, Eric Gonçalves wrote:
>> This patchset adds support for the ST-Microelectronics FTS2BA61Y,
>> a capacitive multi-touch touchscreen controller. this touchscreen
>> is used in many mobile devices, like ones from the Galaxy S22 series
>> and the Z Fold 5. Ivaylo Ivanov wrote the driver originally,
>> and I'm upstreaming it on his behalf.
>>
> RFC means patchset is not ready, so please always mention why it is not
> ready or what you expect here.
I'm not sure if naming the compatible as it is currently is correct.
The specific thing about this IC seems to be that it's flashed with
samsung-made firmware, so I need to confirm that:
- we don't want to match compatible with the IC name (the same IC may
be shipped with different fw on other devices)
- maintainers wouldn't want us to merge it with some other driver
Best regards,
Ivaylo
>
> Best regards,
> Krzysztof
^ permalink raw reply
* Re: [RFC PATCH 1/2] dt-bindings: input: add ST-Microelectronics FTS2BA61Y touchscreen binding
From: Krzysztof Kozlowski @ 2025-09-14 14:48 UTC (permalink / raw)
To: Eric Gonçalves, Dmitry Torokhov, Henrik Rydberg, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: Ivaylo Ivanov, linux-input, devicetree, linux-kernel
In-Reply-To: <20250911211910.45903-2-ghatto404@gmail.com>
On 11/09/2025 23:19, Eric Gonçalves wrote:
> Add the bindings for ST-Microelectronics FTS2BA61Y capacitive touchscreen.
Please wrap commit message according to Linux coding style / submission
process (neither too early nor over the limit):
https://elixir.bootlin.com/linux/v6.4-rc1/source/Documentation/process/submitting-patches.rst#L597
A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.17-rc3/source/Documentation/devicetree/bindings/submitting-patches.rst#L18
>
> Signed-off-by: Eric Gonçalves <ghatto404@gmail.com>
> +
> +properties:
> + compatible:
> + const: st,fts2ba61y
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + maxItems: 1
> +
> + avdd-supply: true
> + vdd-supply: true
> +
> +unevaluatedProperties: false
This goes after required: field.
Other than that - why isn't this finished (non RFC)? Code looks ok, but
I also did not look that thorough.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [RFC PATCH 0/2] Input: add fts2ba61y touchscreen driver
From: Krzysztof Kozlowski @ 2025-09-14 14:47 UTC (permalink / raw)
To: Eric Gonçalves, Dmitry Torokhov, Henrik Rydberg, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: Ivaylo Ivanov, linux-input, devicetree, linux-kernel
In-Reply-To: <20250911211910.45903-1-ghatto404@gmail.com>
On 11/09/2025 23:19, Eric Gonçalves wrote:
> This patchset adds support for the ST-Microelectronics FTS2BA61Y,
> a capacitive multi-touch touchscreen controller. this touchscreen
> is used in many mobile devices, like ones from the Galaxy S22 series
> and the Z Fold 5. Ivaylo Ivanov wrote the driver originally,
> and I'm upstreaming it on his behalf.
>
RFC means patchset is not ready, so please always mention why it is not
ready or what you expect here.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 3/5] dt-bindings: touchscreen: convert raspberrypi,firmware-ts bindings to json schema
From: Rob Herring (Arm) @ 2025-09-14 14:24 UTC (permalink / raw)
To: Dario Binacchi
Cc: linux-kernel, devicetree, linux-input, Florian Fainelli,
Dmitry Torokhov, Conor Dooley, linux-amarula,
Broadcom internal kernel review list, linux-rpi-kernel,
linux-arm-kernel, Krzysztof Kozlowski
In-Reply-To: <20250913092707.1005616-3-dario.binacchi@amarulasolutions.com>
On Sat, 13 Sep 2025 11:26:53 +0200, Dario Binacchi wrote:
> Convert Raspberry Pi firmware 7" touchscreen controller device tree
> binding to json-schema.
>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>
> ---
>
> Changes in v2:
> - Added in v2
>
> .../touchscreen/raspberrypi,firmware-ts.txt | 26 -----------
> .../touchscreen/raspberrypi,firmware-ts.yaml | 45 +++++++++++++++++++
> 2 files changed, 45 insertions(+), 26 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.txt
> create mode 100644 Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.example.dtb: firmware-rpi (raspberrypi,bcm2835-firmware): 'touchscreen' does not match any of the regexes: '^pinctrl-[0-9]+$'
from schema $id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml#
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/input/touchscreen/raspberrypi,firmware-ts.example.dtb: firmware-rpi (raspberrypi,bcm2835-firmware): compatible: ['raspberrypi,bcm2835-firmware'] is too short
from schema $id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml#
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20250913092707.1005616-3-dario.binacchi@amarulasolutions.com
The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.
^ permalink raw reply
* [PATCH v1 2/2] Input: s6sa552 - add a driver for the Samsung A552 touchscreen controller
From: Ivaylo Ivanov @ 2025-09-14 13:44 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Herring, Dmitry Torokhov, Conor Dooley,
Henrik Rydberg
Cc: linux-samsung-soc, linux-input, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <20250914134458.2624176-1-ivo.ivanov.ivanov1@gmail.com>
The S6SA552 touchscreen is a capacitive multi-touch controller for
mobile use. It connects via i2c at the address 0x48.
Introduce a basic driver, which can handle initialization, touch events
and power states.
At least the firmware for this IC on Galaxy S7 differs from S6SY761
in register layout and bits, as well as some missing registers/functions,
for example for retrieving the max X/Y coordinates and the amount
of TX/RX channels.
Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
---
Samsung almost completely didn't mention the IC name in the vendor
drivers.. I retrieved it from a fw-update function that checks a
firmware bit and matches it with an IC model string. Otherwise
everywhere else it's called sec_ts. I believe the main difference
between samsung touchscreen controllers is the firmware they're
running on, but this one is a bit different from s6sy761, featuring
different registers and bits, as well as some missing features. I
went with calling it s6sa552 to follow the "s6s" convention, because
as far as I know, s6sy661 also exists, and the important part is after
"s6s".
---
drivers/input/touchscreen/Kconfig | 11 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/s6sa552.c | 439 ++++++++++++++++++++++++++++
3 files changed, 451 insertions(+)
create mode 100644 drivers/input/touchscreen/s6sa552.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 196905162..2d65dd13e 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -505,6 +505,17 @@ config TOUCHSCREEN_IPROC
To compile this driver as a module, choose M here: the
module will be called bcm_iproc_tsc.
+config TOUCHSCREEN_S6SA552
+ tristate "Samsung S6SA552 Touchscreen driver"
+ depends on I2C
+ help
+ Say Y if you have the Samsung S6SA552 driver
+
+ If unsure, say N
+
+ To compile this driver as module, choose M here: the
+ module will be called s6sa552.
+
config TOUCHSCREEN_S6SY761
tristate "Samsung S6SY761 Touchscreen driver"
depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 97a025c6a..d3be3e21a 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_PIXCIR) += pixcir_i2c_ts.o
obj-$(CONFIG_TOUCHSCREEN_RM_TS) += raydium_i2c_ts.o
+obj-$(CONFIG_TOUCHSCREEN_S6SA552) += s6sa552.o
obj-$(CONFIG_TOUCHSCREEN_S6SY761) += s6sy761.o
obj-$(CONFIG_TOUCHSCREEN_SILEAD) += silead.o
obj-$(CONFIG_TOUCHSCREEN_SIS_I2C) += sis_i2c.o
diff --git a/drivers/input/touchscreen/s6sa552.c b/drivers/input/touchscreen/s6sa552.c
new file mode 100644
index 000000000..32ef338de
--- /dev/null
+++ b/drivers/input/touchscreen/s6sa552.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0
+// Samsung S6SA552 Touchscreen device driver
+//
+// Copyright (c) 2025 Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+//
+// Based on the s6sy761 driver:
+// Copyright (c) 2017 Samsung Electronics Co., Ltd.
+// Copyright (c) 2017 Andi Shyti <andi@etezian.org>
+
+#include <linux/unaligned.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input/mt.h>
+#include <linux/input/touchscreen.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+
+/* commands */
+#define S6SA552_SENSE_ON 0x40
+#define S6SA552_SENSE_OFF 0x41
+#define S6SA552_TOUCH_FUNCTION 0x63
+#define S6SA552_DEVICE_ID 0x52
+#define S6SA552_BOOT_STATUS 0x55
+#define S6SA552_READ_ONE_EVENT 0x71
+#define S6SA552_CLEAR_EVENT_STACK 0x60
+#define S6SA552_PANEL_INFO 0x23
+
+/* acknowledge events */
+#define S6SA552_EVENT_ACK_BOOT 0x0c
+
+/* status event types */
+#define S6SA552_EVENT_TYPE_ACK 0x01
+#define S6SA552_EVENT_TYPE_ERR 0x02
+#define S6SA552_EVENT_TYPE_INFO 0x03
+#define S6SA552_EVENT_TYPE_GEST 0x06
+#define S6SA552_EVENT_TYPE_SPONGE 0x5a
+
+/* boot status (BS) */
+#define S6SA552_BS_APPLICATION 0x20
+
+/* event id */
+#define S6SA552_EVENT_ID_COORDINATE 0x01
+#define S6SA552_EVENT_ID_STATUS 0x00
+
+/* event register masks */
+#define S6SA552_MASK_TID 0x0f /* byte 1, lower 4 bits */
+#define S6SA552_MASK_NT 0xf0 /* byte 1, upper 4 bits */
+#define S6SA552_MASK_EID 0xc0 /* byte 0, bits 6-7 */
+#define S6SA552_MASK_TOUCH_STATE 0x07 /* byte 0, bits 0-2 */
+#define S6SA552_MASK_TOUCH_TYPE 0x38 /* byte 0, bits 3-5 */
+
+/* touch states */
+#define S6SA552_TS_NONE 0x00
+#define S6SA552_TS_PRESS 0x01
+#define S6SA552_TS_MOVE 0x02
+#define S6SA552_TS_RELEASE 0x03
+
+#define S6SA552_EVENT_SIZE 8
+#define S6SA552_DEVID_SIZE 3
+#define S6SA552_PANEL_ID_SIZE 11
+#define S6SA552_MAX_FINGERS 10
+
+/*
+ * Hardcoded values, since at least on herolte, the subid register doesn't
+ * read/exist.
+ */
+#define S6SA552_MAX_X 4095
+#define S6SA552_MAX_Y 4095
+#define S6SA552_TX_CHANNELS 16
+
+#define S6SA552_DEV_NAME "s6sa552"
+
+enum s6sa552_regulators {
+ S6SA552_REGULATOR_VDD,
+ S6SA552_REGULATOR_AVDD,
+};
+
+struct s6sa552_data {
+ struct i2c_client *client;
+ struct regulator_bulk_data regulators[2];
+ struct input_dev *input;
+ struct touchscreen_properties prop;
+
+ u8 data[S6SA552_EVENT_SIZE];
+
+ u16 devid;
+ u8 tx_channel;
+};
+
+static void s6sa552_report_coordinates(struct s6sa552_data *sdata,
+ u8 *event, u8 tid)
+{
+ u8 major = event[6];
+ u8 minor = event[7];
+ u8 z = event[5];
+ u16 x = (event[2] << 4) | ((event[4] >> 4) & 0x0F);
+ u16 y = (event[3] << 4) | (event[4] & 0x0F);
+
+ input_mt_slot(sdata->input, tid);
+
+ input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, true);
+ input_report_abs(sdata->input, ABS_MT_POSITION_X, x);
+ input_report_abs(sdata->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MAJOR, major);
+ input_report_abs(sdata->input, ABS_MT_TOUCH_MINOR, minor);
+ input_report_abs(sdata->input, ABS_MT_PRESSURE, z);
+
+ input_sync(sdata->input);
+}
+
+static void s6sa552_report_release(struct s6sa552_data *sdata, u8 tid)
+{
+ input_mt_slot(sdata->input, tid);
+ input_mt_report_slot_state(sdata->input, MT_TOOL_FINGER, false);
+
+ input_sync(sdata->input);
+}
+
+static void s6sa552_handle_coordinates(struct s6sa552_data *sdata, u8 *event)
+{
+ u8 tid;
+ u8 touch_state;
+
+ if (unlikely(!(event[1] & S6SA552_MASK_TID)))
+ return;
+
+ tid = (event[1] & S6SA552_MASK_TID) - 1;
+ touch_state = event[0] & S6SA552_MASK_TOUCH_STATE;
+
+ switch (touch_state) {
+ case S6SA552_TS_PRESS:
+ case S6SA552_TS_MOVE:
+ s6sa552_report_coordinates(sdata, event, tid);
+ break;
+ case S6SA552_TS_RELEASE:
+ s6sa552_report_release(sdata, tid);
+ break;
+ case S6SA552_TS_NONE:
+ default:
+ break;
+ }
+}
+
+static irqreturn_t s6sa552_irq_handler(int irq, void *dev)
+{
+ struct s6sa552_data *sdata = dev;
+ int ret;
+ u8 event_id;
+
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SA552_READ_ONE_EVENT,
+ S6SA552_EVENT_SIZE,
+ sdata->data);
+ if (ret < 0) {
+ dev_err(&sdata->client->dev, "failed to read event\n");
+ return IRQ_HANDLED;
+ }
+
+ if (!sdata->data[0])
+ return IRQ_HANDLED;
+
+ event_id = sdata->data[0] >> 6;
+
+ switch (event_id) {
+ case S6SA552_EVENT_ID_COORDINATE:
+ s6sa552_handle_coordinates(sdata, sdata->data);
+ break;
+ case S6SA552_EVENT_ID_STATUS:
+ break;
+ default:
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int s6sa552_input_open(struct input_dev *dev)
+{
+ struct s6sa552_data *sdata = input_get_drvdata(dev);
+
+ return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_ON);
+}
+
+static void s6sa552_input_close(struct input_dev *dev)
+{
+ struct s6sa552_data *sdata = input_get_drvdata(dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_OFF);
+ if (ret)
+ dev_err(&sdata->client->dev, "failed to turn off sensing\n");
+}
+
+static ssize_t s6sa552_sysfs_devid(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct s6sa552_data *sdata = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%#x\n", sdata->devid);
+}
+
+static DEVICE_ATTR(devid, 0444, s6sa552_sysfs_devid, NULL);
+
+static struct attribute *s6sa552_sysfs_attrs[] = {
+ &dev_attr_devid.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(s6sa552_sysfs);
+
+static int s6sa552_power_on(struct s6sa552_data *sdata)
+{
+ u8 buffer[S6SA552_EVENT_SIZE];
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+ if (ret)
+ return ret;
+
+ msleep(140);
+
+ /* double check whether the touch is functional */
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SA552_READ_ONE_EVENT,
+ S6SA552_EVENT_SIZE,
+ buffer);
+ if (ret < 0)
+ return ret;
+
+ if (buffer[0] != S6SA552_EVENT_TYPE_ACK ||
+ buffer[1] != S6SA552_EVENT_ACK_BOOT) {
+ return -ENODEV;
+ }
+
+ ret = i2c_smbus_read_byte_data(sdata->client, S6SA552_BOOT_STATUS);
+ if (ret < 0)
+ return ret;
+
+ /* for some reasons the device might be stuck in the bootloader */
+ if (ret != S6SA552_BS_APPLICATION)
+ return -ENODEV;
+
+ /* enable touch functionality */
+ ret = i2c_smbus_write_byte_data(sdata->client,
+ S6SA552_TOUCH_FUNCTION, 0x01);
+ if (ret)
+ return ret;
+
+ mdelay(20); /* make sure everything is up */
+
+ return 0;
+}
+
+static int s6sa552_hw_init(struct s6sa552_data *sdata)
+{
+ u8 buffer[S6SA552_DEVID_SIZE];
+ int ret;
+
+ ret = s6sa552_power_on(sdata);
+ if (ret)
+ return ret;
+
+ ret = i2c_smbus_read_i2c_block_data(sdata->client,
+ S6SA552_DEVICE_ID,
+ S6SA552_DEVID_SIZE,
+ buffer);
+ if (ret < 0)
+ return ret;
+
+ sdata->devid = get_unaligned_be16(buffer + 1);
+
+ return 0;
+}
+
+static void s6sa552_power_off(void *data)
+{
+ struct s6sa552_data *sdata = data;
+
+ disable_irq(sdata->client->irq);
+ regulator_bulk_disable(ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+}
+
+static int s6sa552_probe(struct i2c_client *client)
+{
+ struct s6sa552_data *sdata;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
+
+ sdata = devm_kzalloc(&client->dev, sizeof(*sdata), GFP_KERNEL);
+ if (!sdata)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, sdata);
+ sdata->client = client;
+
+ sdata->regulators[S6SA552_REGULATOR_VDD].supply = "vdd";
+ sdata->regulators[S6SA552_REGULATOR_AVDD].supply = "avdd";
+ err = devm_regulator_bulk_get(&client->dev,
+ ARRAY_SIZE(sdata->regulators),
+ sdata->regulators);
+ if (err)
+ return err;
+
+ err = devm_add_action_or_reset(&client->dev, s6sa552_power_off, sdata);
+ if (err)
+ return err;
+
+ err = s6sa552_hw_init(sdata);
+ if (err)
+ return err;
+
+ sdata->input = devm_input_allocate_device(&client->dev);
+ if (!sdata->input)
+ return -ENOMEM;
+
+ sdata->input->name = S6SA552_DEV_NAME;
+ sdata->input->id.bustype = BUS_I2C;
+ sdata->input->open = s6sa552_input_open;
+ sdata->input->close = s6sa552_input_close;
+
+ input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, S6SA552_MAX_X,
+ 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, S6SA552_MAX_Y,
+ 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+ input_set_abs_params(sdata->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+ touchscreen_parse_properties(sdata->input, true, &sdata->prop);
+
+ if (!input_abs_get_max(sdata->input, ABS_X) ||
+ !input_abs_get_max(sdata->input, ABS_Y)) {
+ dev_warn(&client->dev, "the axis have not been set\n");
+ }
+
+ err = input_mt_init_slots(sdata->input, S6SA552_TX_CHANNELS,
+ INPUT_MT_DIRECT);
+ if (err)
+ return err;
+
+ input_set_drvdata(sdata->input, sdata);
+
+ err = input_register_device(sdata->input);
+ if (err)
+ return err;
+
+ err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ s6sa552_irq_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "s6sa552_irq", sdata);
+ if (err)
+ return err;
+
+ pm_runtime_enable(&client->dev);
+
+ return 0;
+}
+
+static void s6sa552_remove(struct i2c_client *client)
+{
+ pm_runtime_disable(&client->dev);
+}
+
+static int s6sa552_runtime_suspend(struct device *dev)
+{
+ struct s6sa552_data *sdata = dev_get_drvdata(dev);
+
+ return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_OFF);
+}
+
+static int s6sa552_runtime_resume(struct device *dev)
+{
+ struct s6sa552_data *sdata = dev_get_drvdata(dev);
+
+ return i2c_smbus_write_byte(sdata->client, S6SA552_SENSE_ON);
+}
+
+static int s6sa552_suspend(struct device *dev)
+{
+ struct s6sa552_data *sdata = dev_get_drvdata(dev);
+
+ s6sa552_power_off(sdata);
+
+ return 0;
+}
+
+static int s6sa552_resume(struct device *dev)
+{
+ struct s6sa552_data *sdata = dev_get_drvdata(dev);
+
+ enable_irq(sdata->client->irq);
+
+ return s6sa552_power_on(sdata);
+}
+
+static const struct dev_pm_ops s6sa552_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(s6sa552_suspend, s6sa552_resume)
+ RUNTIME_PM_OPS(s6sa552_runtime_suspend, s6sa552_runtime_resume, NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s6sa552_of_match[] = {
+ { .compatible = "samsung,s6sa552", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, s6sa552_of_match);
+#endif
+
+static const struct i2c_device_id s6sa552_id[] = {
+ { "s6sa552" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, s6sa552_id);
+
+static struct i2c_driver s6sa552_driver = {
+ .driver = {
+ .name = S6SA552_DEV_NAME,
+ .dev_groups = s6sa552_sysfs_groups,
+ .of_match_table = of_match_ptr(s6sa552_of_match),
+ .pm = pm_ptr(&s6sa552_pm_ops),
+ },
+ .probe = s6sa552_probe,
+ .remove = s6sa552_remove,
+ .id_table = s6sa552_id,
+};
+
+module_i2c_driver(s6sa552_driver);
+
+MODULE_AUTHOR("Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>");
+MODULE_DESCRIPTION("Samsung S6SA552 Touch Screen");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related
* [PATCH v1 1/2] dt-bindings: input: document Samsung A552 touchscreen controller
From: Ivaylo Ivanov @ 2025-09-14 13:44 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Herring, Dmitry Torokhov, Conor Dooley,
Henrik Rydberg
Cc: linux-samsung-soc, linux-input, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <20250914134458.2624176-1-ivo.ivanov.ivanov1@gmail.com>
Document the Samsung A552 touchscreen controller, present in devices like
the Samsung Galaxy S7.
Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
---
.../input/touchscreen/samsung,s6sa552.yaml | 54 +++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/samsung,s6sa552.yaml
diff --git a/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sa552.yaml b/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sa552.yaml
new file mode 100644
index 000000000..af151e245
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/samsung,s6sa552.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/samsung,s6sa552.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Samsung S6SA552 touchscreen controller
+
+maintainers:
+ - Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ const: samsung,s6sa552
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ avdd-supply: true
+ vdd-supply: true
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - avdd-supply
+ - vdd-supply
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@48 {
+ compatible = "samsung,s6sa552";
+ reg = <0x48>;
+ interrupt-parent = <&gpa1>;
+ interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+ avdd-supply = <&ldo30_reg>;
+ vdd-supply = <&ldo31_reg>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
+ };
+ };
--
2.43.0
^ permalink raw reply related
* [PATCH v1 0/2] Input: s6sa552 - add a driver for the Samsung A552
From: Ivaylo Ivanov @ 2025-09-14 13:44 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Herring, Dmitry Torokhov, Conor Dooley,
Henrik Rydberg
Cc: linux-samsung-soc, linux-input, devicetree, linux-arm-kernel,
linux-kernel
Hey folks,
This patchset adds support for the Samsung A552 touchscreen controller.
Naming is based on the current s6s* convention, used for Y761. The
IC is similar in functionality to 761, but has enough differences in
registers, bits and functionality to deserve its own driver.
Best regards,
Ivaylo
Ivaylo Ivanov (2):
dt-bindings: input: document Samsung A552 touchscreen controller
Input: s6sa552 - add a driver for the Samsung A552 touchscreen
controller
.../input/touchscreen/samsung,s6sa552.yaml | 54 +++
drivers/input/touchscreen/Kconfig | 11 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/s6sa552.c | 439 ++++++++++++++++++
4 files changed, 505 insertions(+)
create mode 100644 Documentation/devicetree/bindings/input/touchscreen/samsung,s6sa552.yaml
create mode 100644 drivers/input/touchscreen/s6sa552.c
--
2.43.0
^ permalink raw reply
* Re: [PATCH] HID: nintendo: enable HW LED blinking
From: Daniel Ogorchock @ 2025-09-14 4:40 UTC (permalink / raw)
To: Noa; +Cc: linux-input, linux-kernel
In-Reply-To: <20250214225826.154144-1-coolreader18@gmail.com>
Hi Noa,
I tried building with this version of the patch and hit the following error:
drivers/hid/hid-nintendo.c:2229:14: error: type defaults to ‘int’ in
declaration of ‘JC_LED_BLINK_DELAY_ON_MS’ [-Wimplicit-int]
2229 | static const JC_LED_BLINK_DELAY_ON_MS = 500;
| ^~~~~~~~~~~~~~~~~~~~~~~~
drivers/hid/hid-nintendo.c:2230:14: error: type defaults to ‘int’ in
declaration of ‘JC_LED_BLINK_DELAY_OFF_MS’ [-Wimplicit-int]
2230 | static const JC_LED_BLINK_DELAY_OFF_MS = 200;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
make[4]: *** [scripts/Makefile.build:287: drivers/hid/hid-nintendo.o] Error 1
make[3]: *** [scripts/Makefile.build:555: drivers/hid] Error 2
Making these 'static const unsigned long' fixed that issue. Probably
toolchain version dependent whether it succeeds or fails with the
implicit int.
I also noticed that the HW blink functionality only works in bluetooth
mode. In USB mode it forces the LEDs on.
That seems to match up with the note here:
https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/bluetooth_hid_subcommands_notes.md#subcommand-0x30-set-player-lights
I was able to modify your patch to gate the new HW logic to only be
active when using bluetooth.
Also please include the commit summary message/description above your
signed-off-by line like you did in v1 of the patch.
Below is my quick modification to your patch that seemed to get things
working right on my local setup. Please feel free to
incorporate it or make your own modifications in v3 to fix the USB
mode. It's probably also worth adding a comment describing
why it doesn't use the HW support for USB:
---
drivers/hid/hid-nintendo.c | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index 14aed2500a96..03f24e709949 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -2201,7 +2201,8 @@ static int joycon_update_player_leds(struct device *dev)
}
for (i = 0; i < JC_NUM_LEDS; i++) {
- if (ctlr->leds[i].blink_delay_on || ctlr->leds[i].blink_delay_off)
+ if ((ctlr->leds[i].blink_delay_on || ctlr->leds[i].blink_delay_off) &&
+ !joycon_using_usb(ctlr))
flash |= 1 << i;
else if (ctlr->leds[i].brightness)
val |= 1 << i;
@@ -2217,17 +2218,26 @@ static int joycon_update_player_leds(struct device *dev)
static int joycon_player_led_brightness_set(struct led_classdev *led,
enum led_brightness brightness)
{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct joycon_ctlr *ctlr;
+
+ ctlr = hid_get_drvdata(hdev);
+ if (!ctlr) {
+ hid_err(hdev, "No controller data\n");
+ return -ENODEV;
+ }
+
led->brightness = brightness;
- if (!brightness)
+ if (!brightness && !joycon_using_usb(ctlr))
led->blink_delay_on = led->blink_delay_off = 0;
return joycon_update_player_leds(led->dev->parent);
}
/* the blink period of the leds can't be changed, and is always these values */
-static const JC_LED_BLINK_DELAY_ON_MS = 500;
-static const JC_LED_BLINK_DELAY_OFF_MS = 200;
+static const unsigned long JC_LED_BLINK_DELAY_ON_MS = 500;
+static const unsigned long JC_LED_BLINK_DELAY_OFF_MS = 200;
/* the different leds on a joycon can't actually be set to hw blink
independently
* of each other, since they all use the same one subcommand, so this function
* actually resets the cycle of all the leds */
@@ -2299,7 +2309,8 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
led->max_brightness = 1;
led->brightness_set_blocking =
joycon_player_led_brightness_set;
- led->blink_set = joycon_player_led_blink_set;
+ if (!joycon_using_usb(ctlr))
+ led->blink_set = joycon_player_led_blink_set;
led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
led_val |= joycon_player_led_patterns[player_led_pattern][i] << i;
--
2.51.0
On Fri, Feb 14, 2025 at 5:58 PM Noa <coolreader18@gmail.com> wrote:
>
> Updated with proper commit title and clearer constant names.
>
> Signed-off-by: Noa <coolreader18@gmail.com>
> ---
> drivers/hid/hid-nintendo.c | 45 ++++++++++++++++++++++++++++++++------
> 1 file changed, 38 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
> index 11ac246176ae..f4cdd35eef2a 100644
> --- a/drivers/hid/hid-nintendo.c
> +++ b/drivers/hid/hid-nintendo.c
> @@ -2183,14 +2183,13 @@ static int joycon_input_create(struct joycon_ctlr *ctlr)
> return 0;
> }
>
> -/* Because the subcommand sets all the leds at once, the brightness argument is ignored */
> -static int joycon_player_led_brightness_set(struct led_classdev *led,
> - enum led_brightness brightness)
> +/* Update the on/flash status of the leds according to their led_classdev fields */
> +static int joycon_update_player_leds(struct device *dev)
> {
> - struct device *dev = led->dev->parent;
> struct hid_device *hdev = to_hid_device(dev);
> struct joycon_ctlr *ctlr;
> int val = 0;
> + int flash = 0;
> int i;
> int ret;
>
> @@ -2200,16 +2199,47 @@ static int joycon_player_led_brightness_set(struct led_classdev *led,
> return -ENODEV;
> }
>
> - for (i = 0; i < JC_NUM_LEDS; i++)
> - val |= ctlr->leds[i].brightness << i;
> + for (i = 0; i < JC_NUM_LEDS; i++) {
> + if (ctlr->leds[i].blink_delay_on || ctlr->leds[i].blink_delay_off)
> + flash |= 1 << i;
> + else if (ctlr->leds[i].brightness)
> + val |= 1 << i;
> + }
>
> mutex_lock(&ctlr->output_mutex);
> - ret = joycon_set_player_leds(ctlr, 0, val);
> + ret = joycon_set_player_leds(ctlr, flash, val);
> mutex_unlock(&ctlr->output_mutex);
>
> return ret;
> }
>
> +static int joycon_player_led_brightness_set(struct led_classdev *led,
> + enum led_brightness brightness)
> +{
> + led->brightness = brightness;
> +
> + if (!brightness)
> + led->blink_delay_on = led->blink_delay_off = 0;
> +
> + return joycon_update_player_leds(led->dev->parent);
> +}
> +
> +/* the blink period of the leds can't be changed, and is always these values */
> +static const JC_LED_BLINK_DELAY_ON_MS = 500;
> +static const JC_LED_BLINK_DELAY_OFF_MS = 200;
> +/* the different leds on a joycon can't actually be set to hw blink independently
> + * of each other, since they all use the same one subcommand, so this function
> + * actually resets the cycle of all the leds */
> +static int joycon_player_led_blink_set(struct led_classdev *led,
> + unsigned long *delay_on,
> + unsigned long *delay_off)
> +{
> + led->blink_delay_on = *delay_on = JC_LED_BLINK_DELAY_ON_MS;
> + led->blink_delay_off = *delay_off = JC_LED_BLINK_DELAY_OFF_MS;
> +
> + return joycon_update_player_leds(led->dev->parent);
> +}
> +
> static int joycon_home_led_brightness_set(struct led_classdev *led,
> enum led_brightness brightness)
> {
> @@ -2268,6 +2298,7 @@ static int joycon_leds_create(struct joycon_ctlr *ctlr)
> led->max_brightness = 1;
> led->brightness_set_blocking =
> joycon_player_led_brightness_set;
> + led->blink_set = joycon_player_led_blink_set;
> led->flags = LED_CORE_SUSPENDRESUME | LED_HW_PLUGGABLE;
>
> led_val |= joycon_player_led_patterns[player_led_pattern][i] << i;
> --
> 2.48.1
>
Thanks,
Daniel
^ permalink raw reply related
* Re: [PATCH 0/5] platform/chrome: Fix a race when probing drivers
From: Tzung-Bi Shih @ 2025-09-14 3:47 UTC (permalink / raw)
To: Dmitry Torokhov, Benson Leung; +Cc: linux-input, chrome-platform
In-Reply-To: <20250828083601.856083-1-tzungbi@kernel.org>
On Thu, Aug 28, 2025 at 08:35:56AM +0000, Tzung-Bi Shih wrote:
> A race is observed when cros_ec_lpc and cros-ec-keyb are all built as
> modules. cros_ec_lpc is cros-ec-keyb's parent. However, they can be
> probed at the same time.
>
> Example:
>
> + -----------------------------------------------------------------+
> | Some init process (e.g. udevd) | deferred_probe_work_func worker |
> + -----------------------------------------------------------------+
> | Probe cros-ec-keyb. | |
> | - Decide to defer[1]. | |
> | | A device bound to a driver[2]. |
> | Probe cros_ec_lpc. | |
> | - Init the struct[3]. | |
> | | Retry cros-ec-keyb from the |
> | | deferred list[4]. |
> | | - Won't defer again as [3]. |
> | | - Access uninitialized data in |
> | | the struct. |
> | - Register the device. | |
> + -----------------------------------------------------------------+
> [...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git for-next
[1/5] platform/chrome: Centralize cros_ec_device allocation
commit: 918856986014142271a70a334d300994b9c41720
[2/5] platform/chrome: Centralize common cros_ec_device initialization
commit: e19ceeb1c0f63e3e15b197c5f34797134b51ba0e
[3/5] platform/chrome: cros_ec: Separate initialization from cros_ec_register()
commit: 7a79b0bfd8b3995a39d25bffcf57273635c0e542
[4/5] platform/chrome: cros_ec: Add a flag to track registration state
commit: 56cb557279d70397cefb497e0f06bdd6fd685f8e
[5/5] Input: cros_ec_keyb - Defer probe until parent EC device is registered
commit: 48633acccf38d706d7b368400647bb9db9caf1ae
Thanks!
^ permalink raw reply
* Re: [PATCH 0/5] platform/chrome: Fix a race when probing drivers
From: Tzung-Bi Shih @ 2025-09-14 3:26 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Benson Leung, linux-input, chrome-platform
In-Reply-To: <vt2xibzzfbq2aq4kuyl3557kqazqusnxe75ps6idn6xpcxhous@u562qeztmaqb>
On Sat, Sep 13, 2025 at 06:08:48PM -0700, Dmitry Torokhov wrote:
> On Fri, Sep 05, 2025 at 08:38:10AM +0000, Tzung-Bi Shih wrote:
> > On Thu, Sep 04, 2025 at 07:06:23AM -0700, Dmitry Torokhov wrote:
> > > On Tue, Sep 02, 2025 at 09:18:47PM +0800, Tzung-Bi Shih wrote:
> > > > On Fri, Aug 29, 2025 at 08:50:01PM +0800, Tzung-Bi Shih wrote:
> > > > > On Fri, Aug 29, 2025 at 11:28:55AM +0000, Dmitry Torokhov wrote:
> > > > > > On Thu, Aug 28, 2025 at 08:35:56AM +0000, Tzung-Bi Shih wrote:
> > > > > > > A race is observed when cros_ec_lpc and cros-ec-keyb are all built as
> > > > > > > modules. cros_ec_lpc is cros-ec-keyb's parent. However, they can be
> > > > > > > probed at the same time.
> > > > > > >
> > > > > > > Example:
> > > > > > >
> > > > > > > + -----------------------------------------------------------------+
> > > > > > > | Some init process (e.g. udevd) | deferred_probe_work_func worker |
> > > > > > > + -----------------------------------------------------------------+
> > > > > > > | Probe cros-ec-keyb. | |
> > > > > > > | - Decide to defer[1]. | |
> > > > > > > | | A device bound to a driver[2]. |
> > > > > > > | Probe cros_ec_lpc. | |
> > > > > > > | - Init the struct[3]. | |
> > > > > > > | | Retry cros-ec-keyb from the |
> > > > > > > | | deferred list[4]. |
> > > > > > > | | - Won't defer again as [3]. |
> > > > > > > | | - Access uninitialized data in |
> > > > > > > | | the struct. |
> > > > > > > | - Register the device. | |
> > > > > > > + -----------------------------------------------------------------+
> > > > > > >
> > > > > > > [1] https://elixir.bootlin.com/linux/v6.16/source/drivers/input/keyboard/cros_ec_keyb.c#L707
> > > > > > > [2] https://elixir.bootlin.com/linux/v6.16/source/drivers/base/dd.c#L405
> > > > > > > [3] https://elixir.bootlin.com/linux/v6.16/source/drivers/platform/chrome/cros_ec_lpc.c#L644
> > > > > > > [4] https://elixir.bootlin.com/linux/v6.16/source/drivers/base/dd.c#L418
> > > > > > >
> > > > > > > Note that the device link[5] can't help as in the observed environment,
> > > > > > > the devices are already added via device_add()[6].
> > > > > > >
> > > > > > > [5] https://www.kernel.org/doc/html/latest/driver-api/device_link.html#usage
> > > > > > > [6] https://elixir.bootlin.com/linux/v6.16/source/drivers/acpi/acpi_platform.c#L177
> > > > > > >
> > > > > > > The series fixes the issue by ensuring the struct is ready for accessing
> > > > > > > before continuing to probe cros-ec-keyb.
> > > > > >
> > > > > > Why is the keyboard platform device instantiated before the transport
> > > > > > (cros_ec_lpc) is done initializing? I think this is the root of the
> > > > > > issue...
> > > > >
> > > > > I may misunderstand but it seems to me:
> > > > >
> > > > > - The ACPI bus enumerated and instantiated the platform devices[6] first.
> > > > >
> > > > > - The keyboard platform device was probed when `cros_ec_keyb_driver`
> > > > > registered. It deferred as its parent's drvdata was NULL[1].
> > > > >
> > > > > - The transport platform device was probed when `cros_ec_lpc_driver`
> > > > > registered. It set the drvdata[3].
> > > > >
> > > > > - The keyboard platform device was probed again from retrying the deferred
> > > > > list, by another thread `deferred_probe_work_func`. The parent's drvdata
> > > > > wasn't NULL and cros_ec_register() for the transport device weren't
> > > > > finished. The race happened.
> > > >
> > > > Hi Dmitry,
> > > >
> > > > Does it make sense to you?
> > >
> > > I'll have to research how MFD mixes up statically described and
> > > DT-described platform devices and makes sure that children are not
> > > probed before the parent is ready - I think we need to make cros_ec
> > > behave the same way.
> >
> > I may misunderstand but FWIW:
> >
> > I failed to find relevant code in MFD [7] that guarantees the probe order.
> > Also, I'm curious about wouldn't code at [7] results in duplicate platform
> > devices? E.g., 1 populated from OF; 1 created by MFD.
> >
> > Note: current cros_ec_dev.c doesn't use `of_compatible` in struct mfd_cell.
> >
> > If we're looking at how cros_ec_dev.c guarantees the order:
> >
> > - The transport platfrom device is probed first. It calls cros_ec_register().
> > - In cros_ec_register(), it registers the MFD device "cros-ec-dev". And the
> > children devices are added via mfd_add_devices().
> >
> >
> > Back to the issue we observed:
> >
> > - The platform devices are created when it scans the tree in ACPI[6]. We
> > probably have no way to prevent the devices from adding unless specifying
> > `enumeration_by_parent`[8].
> >
> > - When some of them are modules, the driver registrations are tied to the
> > module insertion. They can be arrived by anytime unless we use something
> > similar to soft dependency[9]. A Kconfig dependency will also
> > be needed to prevent cros_ec_lpcs=m but cros_ec_keyb=y. However,
> > cros_ec_keyb would need to specify 2 possible dependencies "cros_ec_lpcs"
> > and "cros_ec_spi"[10]. I'm not sure what would be happening if a system
> > has no cros_ec_spi module at all.
>
> Sorry for the delay. I think we need to figure out how to delay device
> registration until after the transport device is registered and probed.
> Unfortunately I have not had time to look at this properly so I acked
> the changes to cros_ec_keyb so that we can close the hole for now and
> later we can try to see if there is a reasonable better solution.
Thanks. Let's move forward with the current fix, even though we know it's
suboptimal.
My suspicion is that we lack a proper in-kernel dependency mechanism. This
is on my radar, and I'll investigate a better approach.
^ permalink raw reply
* [git pull] Input updates for v6.17-rc5
From: Dmitry Torokhov @ 2025-09-14 1:20 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, linux-input
Hi Linus,
Please pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git tags/input-for-v6.17-rc5
to receive updates for the input subsystem. You will get:
- a quirk to i8042 for yet another TUXEDO laptop
- a fix to mtk-pmic-keys driver to properly handle MT6359
- a fix to iqs7222 driver to only enable proximity interrupt if it is
mapper to a key or a switch event
- an update to xpad controller driver to recognize Flydigi Apex 5
controller
- an update to maintainers file to drop bounding entry for Melfas touch
controller.
Changelog:
---------
Antheas Kapenekakis (1):
Input: xpad - add support for Flydigi Apex 5
Christoffer Sandberg (1):
Input: i8042 - add TUXEDO InfinityBook Pro Gen10 AMD to i8042 quirk table
Jeff LaBundy (1):
Input: iqs7222 - avoid enabling unused interrupts
Julien Massot (1):
Input: mtk-pmic-keys - MT6359 has a specific release irq
Krzysztof Kozlowski (1):
MAINTAINERS: Input: Drop melfas-mip4 section
Diffstat:
--------
MAINTAINERS | 7 -------
drivers/input/joystick/xpad.c | 2 ++
drivers/input/keyboard/mtk-pmic-keys.c | 5 ++++-
drivers/input/misc/iqs7222.c | 3 +++
drivers/input/serio/i8042-acpipnpio.h | 14 ++++++++++++++
5 files changed, 23 insertions(+), 8 deletions(-)
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 0/5] platform/chrome: Fix a race when probing drivers
From: Dmitry Torokhov @ 2025-09-14 1:08 UTC (permalink / raw)
To: Tzung-Bi Shih; +Cc: Benson Leung, linux-input, chrome-platform
In-Reply-To: <aLqhcu-zjpyeYMly@google.com>
On Fri, Sep 05, 2025 at 08:38:10AM +0000, Tzung-Bi Shih wrote:
> On Thu, Sep 04, 2025 at 07:06:23AM -0700, Dmitry Torokhov wrote:
> > On Tue, Sep 02, 2025 at 09:18:47PM +0800, Tzung-Bi Shih wrote:
> > > On Fri, Aug 29, 2025 at 08:50:01PM +0800, Tzung-Bi Shih wrote:
> > > > On Fri, Aug 29, 2025 at 11:28:55AM +0000, Dmitry Torokhov wrote:
> > > > > On Thu, Aug 28, 2025 at 08:35:56AM +0000, Tzung-Bi Shih wrote:
> > > > > > A race is observed when cros_ec_lpc and cros-ec-keyb are all built as
> > > > > > modules. cros_ec_lpc is cros-ec-keyb's parent. However, they can be
> > > > > > probed at the same time.
> > > > > >
> > > > > > Example:
> > > > > >
> > > > > > + -----------------------------------------------------------------+
> > > > > > | Some init process (e.g. udevd) | deferred_probe_work_func worker |
> > > > > > + -----------------------------------------------------------------+
> > > > > > | Probe cros-ec-keyb. | |
> > > > > > | - Decide to defer[1]. | |
> > > > > > | | A device bound to a driver[2]. |
> > > > > > | Probe cros_ec_lpc. | |
> > > > > > | - Init the struct[3]. | |
> > > > > > | | Retry cros-ec-keyb from the |
> > > > > > | | deferred list[4]. |
> > > > > > | | - Won't defer again as [3]. |
> > > > > > | | - Access uninitialized data in |
> > > > > > | | the struct. |
> > > > > > | - Register the device. | |
> > > > > > + -----------------------------------------------------------------+
> > > > > >
> > > > > > [1] https://elixir.bootlin.com/linux/v6.16/source/drivers/input/keyboard/cros_ec_keyb.c#L707
> > > > > > [2] https://elixir.bootlin.com/linux/v6.16/source/drivers/base/dd.c#L405
> > > > > > [3] https://elixir.bootlin.com/linux/v6.16/source/drivers/platform/chrome/cros_ec_lpc.c#L644
> > > > > > [4] https://elixir.bootlin.com/linux/v6.16/source/drivers/base/dd.c#L418
> > > > > >
> > > > > > Note that the device link[5] can't help as in the observed environment,
> > > > > > the devices are already added via device_add()[6].
> > > > > >
> > > > > > [5] https://www.kernel.org/doc/html/latest/driver-api/device_link.html#usage
> > > > > > [6] https://elixir.bootlin.com/linux/v6.16/source/drivers/acpi/acpi_platform.c#L177
> > > > > >
> > > > > > The series fixes the issue by ensuring the struct is ready for accessing
> > > > > > before continuing to probe cros-ec-keyb.
> > > > >
> > > > > Why is the keyboard platform device instantiated before the transport
> > > > > (cros_ec_lpc) is done initializing? I think this is the root of the
> > > > > issue...
> > > >
> > > > I may misunderstand but it seems to me:
> > > >
> > > > - The ACPI bus enumerated and instantiated the platform devices[6] first.
> > > >
> > > > - The keyboard platform device was probed when `cros_ec_keyb_driver`
> > > > registered. It deferred as its parent's drvdata was NULL[1].
> > > >
> > > > - The transport platform device was probed when `cros_ec_lpc_driver`
> > > > registered. It set the drvdata[3].
> > > >
> > > > - The keyboard platform device was probed again from retrying the deferred
> > > > list, by another thread `deferred_probe_work_func`. The parent's drvdata
> > > > wasn't NULL and cros_ec_register() for the transport device weren't
> > > > finished. The race happened.
> > >
> > > Hi Dmitry,
> > >
> > > Does it make sense to you?
> >
> > I'll have to research how MFD mixes up statically described and
> > DT-described platform devices and makes sure that children are not
> > probed before the parent is ready - I think we need to make cros_ec
> > behave the same way.
>
> I may misunderstand but FWIW:
>
> I failed to find relevant code in MFD [7] that guarantees the probe order.
> Also, I'm curious about wouldn't code at [7] results in duplicate platform
> devices? E.g., 1 populated from OF; 1 created by MFD.
>
> Note: current cros_ec_dev.c doesn't use `of_compatible` in struct mfd_cell.
>
> If we're looking at how cros_ec_dev.c guarantees the order:
>
> - The transport platfrom device is probed first. It calls cros_ec_register().
> - In cros_ec_register(), it registers the MFD device "cros-ec-dev". And the
> children devices are added via mfd_add_devices().
>
>
> Back to the issue we observed:
>
> - The platform devices are created when it scans the tree in ACPI[6]. We
> probably have no way to prevent the devices from adding unless specifying
> `enumeration_by_parent`[8].
>
> - When some of them are modules, the driver registrations are tied to the
> module insertion. They can be arrived by anytime unless we use something
> similar to soft dependency[9]. A Kconfig dependency will also
> be needed to prevent cros_ec_lpcs=m but cros_ec_keyb=y. However,
> cros_ec_keyb would need to specify 2 possible dependencies "cros_ec_lpcs"
> and "cros_ec_spi"[10]. I'm not sure what would be happening if a system
> has no cros_ec_spi module at all.
Sorry for the delay. I think we need to figure out how to delay device
registration until after the transport device is registered and probed.
Unfortunately I have not had time to look at this properly so I acked
the changes to cros_ec_keyb so that we can close the hole for now and
later we can try to see if there is a reasonable better solution.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH 5/5] Input: cros_ec_keyb - Defer probe until parent EC device is registered
From: Dmitry Torokhov @ 2025-09-14 1:06 UTC (permalink / raw)
To: Tzung-Bi Shih; +Cc: Benson Leung, linux-input, chrome-platform
In-Reply-To: <20250828083601.856083-6-tzungbi@kernel.org>
On Thu, Aug 28, 2025 at 08:36:01AM +0000, Tzung-Bi Shih wrote:
> The `cros_ec_keyb` driver can be probed before the cros_ec_device has
> completed the registration. This creates a race condition where
> `cros_ec_keyb` might access uninitialized data.
>
> Fix this by calling `cros_ec_device_registered()` to check the parent's
> status. If the device is not yet ready, return -EPROBE_DEFER to ensure
> the probe is retried later.
>
> Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3 00/11] HID: Implement haptic touchpad support
From: Dmitry Torokhov @ 2025-09-14 1:05 UTC (permalink / raw)
To: Jiri Kosina
Cc: Jonathan Denose, Jonathan Corbet, Henrik Rydberg, linux-input,
linux-kernel, linux-doc, Angela Czubak, Sean O'Brien,
Benjamin Tissoires
In-Reply-To: <4267074p-78q9-54p9-8q43-2ro1n03259os@xreary.bet>
On Fri, Sep 12, 2025 at 05:28:03PM +0200, Jiri Kosina wrote:
> On Thu, 4 Sep 2025, Benjamin Tissoires wrote:
>
> > > > Angela Czubak (11):
> > > > HID: add haptics page defines
> > > > Input: add FF_HAPTIC effect type
> > > > Input: add INPUT_PROP_HAPTIC_TOUCHPAD
> > > > HID: haptic: introduce hid_haptic_device
> > > > HID: input: allow mapping of haptic output
> > > > HID: haptic: initialize haptic device
> > > > HID: input: calculate resolution for pressure
> > > > HID: haptic: add functions handling events
> > > > Input: MT - add INPUT_MT_TOTAL_FORCE flags
> > > > HID: haptic: add hid_haptic_switch_mode
> > > > HID: multitouch: add haptic multitouch support
> > > >
> > > > Documentation/input/event-codes.rst | 14 +
> > > > drivers/hid/Kconfig | 11 +
> > > > drivers/hid/Makefile | 1 +
> > > > drivers/hid/hid-haptic.c | 580 +++++++++++++++++++++++++++++++++
> > > > drivers/hid/hid-haptic.h | 127 ++++++++
> > > > drivers/hid/hid-input.c | 18 +-
> > > > drivers/hid/hid-multitouch.c | 47 +++
> > > > drivers/input/input-mt.c | 14 +-
> > > > include/linux/hid.h | 29 ++
> > > > include/linux/input/mt.h | 1 +
> > > > include/uapi/linux/input-event-codes.h | 1 +
> > > > include/uapi/linux/input.h | 22 +-
> > > > 12 files changed, 858 insertions(+), 7 deletions(-)
> > > > ---
> > > > base-commit: 86731a2a651e58953fc949573895f2fa6d456841
> > > > change-id: 20250625-support-forcepads-0b4f74fd3d0a
> > > >
> > > > Best regards,
> > > > --
> > > > Jonathan Denose <jdenose@google.com>
> > > >
> > > Hi all,
> > >
> > > Please let me know if there is anything else needed from me.
> > >
> >
> > Dmitry, I've just re-reviewed and tested this series. I'm fine with it.
> > Can you give us your ack on the input bits?
>
> Dmitry, did you have time to review the input bits, please?
Sorry was traveling. I acked the relevant patches, please merge with the
rest through HID.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3 09/11] Input: MT - add INPUT_MT_TOTAL_FORCE flags
From: Dmitry Torokhov @ 2025-09-14 1:04 UTC (permalink / raw)
To: Jonathan Denose
Cc: Jiri Kosina, Benjamin Tissoires, Jonathan Corbet, Henrik Rydberg,
linux-input, linux-kernel, linux-doc, Angela Czubak,
Sean O'Brien
In-Reply-To: <20250818-support-forcepads-v3-9-e4f9ab0add84@google.com>
On Mon, Aug 18, 2025 at 11:08:50PM +0000, Jonathan Denose wrote:
> From: Angela Czubak <aczubak@google.com>
>
> Add a flag to generate ABS_PRESSURE as sum of ABS_MT_PRESSURE across
> all slots.
> This flag should be set if one knows a device reports true force and would
> like to report total force to the userspace.
>
> Signed-off-by: Angela Czubak <aczubak@google.com>
> Co-developed-by: Jonathan Denose <jdenose@google.com>
> Signed-off-by: Jonathan Denose <jdenose@google.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3 03/11] Input: add INPUT_PROP_HAPTIC_TOUCHPAD
From: Dmitry Torokhov @ 2025-09-14 1:03 UTC (permalink / raw)
To: Jonathan Denose
Cc: Jiri Kosina, Benjamin Tissoires, Jonathan Corbet, Henrik Rydberg,
linux-input, linux-kernel, linux-doc, Angela Czubak,
Sean O'Brien
In-Reply-To: <20250818-support-forcepads-v3-3-e4f9ab0add84@google.com>
On Mon, Aug 18, 2025 at 11:08:44PM +0000, Jonathan Denose wrote:
> From: Angela Czubak <aczubak@google.com>
>
> INPUT_PROP_HAPTIC_TOUCHPAD property is to be set for a device with simple
> haptic capabilities.
>
> Signed-off-by: Angela Czubak <aczubak@google.com>
> Co-developed-by: Jonathan Denose <jdenose@google.com>
> Signed-off-by: Jonathan Denose <jdenose@google.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v3 02/11] Input: add FF_HAPTIC effect type
From: Dmitry Torokhov @ 2025-09-14 1:02 UTC (permalink / raw)
To: Jonathan Denose
Cc: Jiri Kosina, Benjamin Tissoires, Jonathan Corbet, Henrik Rydberg,
linux-input, linux-kernel, linux-doc, Angela Czubak,
Sean O'Brien
In-Reply-To: <20250818-support-forcepads-v3-2-e4f9ab0add84@google.com>
On Mon, Aug 18, 2025 at 11:08:43PM +0000, Jonathan Denose wrote:
> From: Angela Czubak <aczubak@google.com>
>
> FF_HAPTIC effect type can be used to trigger haptic feedback with HID
> simple haptic usages.
>
> Signed-off-by: Angela Czubak <aczubak@google.com>
> Co-developed-by: Jonathan Denose <jdenose@google.com>
> Signed-off-by: Jonathan Denose <jdenose@google.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: Input: Drop melfas-mip4 section
From: Dmitry Torokhov @ 2025-09-14 0:55 UTC (permalink / raw)
To: Krzysztof Kozlowski; +Cc: linux-input, linux-kernel
In-Reply-To: <20250910142526.105286-2-krzysztof.kozlowski@linaro.org>
On Wed, Sep 10, 2025 at 04:25:27PM +0200, Krzysztof Kozlowski wrote:
> Emails to the sole melfas-mip4 driver maintainer bounce:
>
> 550 <jeesw@melfas.com> No such user here (connected from melfas.com)
>
> so clearly this is not a supported driver anymore.
>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Applied, thank you.
--
Dmitry
^ permalink raw reply
* [PATCH v3 RESEND RESEND 3/3] rust: hid: Glorious PC Gaming Race Model O and O- mice reference driver
From: Rahul Rameshbabu @ 2025-09-13 16:13 UTC (permalink / raw)
To: linux-input, linux-kernel, rust-for-linux
Cc: Jiri Kosina, a.hindborg, alex.gaynor, aliceryhl, benno.lossin,
Benjamin Tissoires, bjorn3_gh, boqun.feng, dakr, db48x, gary,
ojeda, tmgross, peter.hutterer, Rahul Rameshbabu
In-Reply-To: <20250913161222.3889-1-sergeantsagara@protonmail.com>
Demonstrate how to perform a report fixup from a Rust HID driver. The mice
specify the const flag incorrectly in the consumer input report descriptor,
which leads to inputs being ignored. Correctly patch the report descriptor
for the Model O and O- mice.
Portions of the HID report post-fixup:
device 0:0
...
0x81, 0x06, // Input (Data,Var,Rel) 84
...
0x81, 0x06, // Input (Data,Var,Rel) 112
...
0x81, 0x06, // Input (Data,Var,Rel) 140
Signed-off-by: Rahul Rameshbabu <sergeantsagara@protonmail.com>
---
Notes:
Changelog:
v2->v3:
* Fixed docstring formatting
* Updated MAINTAINERS file based on v1 and v2 discussion
v1->v2:
* Use vendor id and device id from drivers/hid/hid-ids.h bindings
* Make use for dev_err! as appropriate
MAINTAINERS | 7 ++++
drivers/hid/Kconfig | 8 +++++
drivers/hid/Makefile | 1 +
drivers/hid/hid-glorious.c | 2 ++
drivers/hid/hid_glorious_rust.rs | 60 ++++++++++++++++++++++++++++++++
5 files changed, 78 insertions(+)
create mode 100644 drivers/hid/hid_glorious_rust.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index 6c60765f2aaa..eee9a33914ef 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10200,6 +10200,13 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/gigabyte-wmi.c
+GLORIOUS RUST DRIVER [RUST]
+M: Rahul Rameshbabu <sergeantsagara@protonmail.com>
+L: linux-input@vger.kernel.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git rust
+F: drivers/hid/hid_glorious_rust.rs
+
GNSS SUBSYSTEM
M: Johan Hovold <johan@kernel.org>
S: Maintained
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 922e76e18af2..b8ef750fb8b6 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -406,6 +406,14 @@ config HID_GLORIOUS
Support for Glorious PC Gaming Race mice such as
the Glorious Model O, O- and D.
+config HID_GLORIOUS_RUST
+ tristate "Glorious O and O- mice Rust reference driver"
+ depends on USB_HID
+ depends on RUST_HID_ABSTRACTIONS
+ help
+ Support for Glorious PC Gaming Race O and O- mice
+ in Rust.
+
config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index 10ae5dedbd84..bd86b3db5d88 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_HID_FT260) += hid-ft260.o
obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o
obj-$(CONFIG_HID_GFRM) += hid-gfrm.o
obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o
+obj-$(CONFIG_HID_GLORIOUS_RUST) += hid_glorious_rust.o
obj-$(CONFIG_HID_VIVALDI_COMMON) += hid-vivaldi-common.o
obj-$(CONFIG_HID_GOODIX_SPI) += hid-goodix-spi.o
obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o
diff --git a/drivers/hid/hid-glorious.c b/drivers/hid/hid-glorious.c
index 5bbd81248053..d7362852c20f 100644
--- a/drivers/hid/hid-glorious.c
+++ b/drivers/hid/hid-glorious.c
@@ -76,8 +76,10 @@ static int glorious_probe(struct hid_device *hdev,
}
static const struct hid_device_id glorious_devices[] = {
+#if !IS_ENABLED(CONFIG_HID_GLORIOUS_RUST)
{ HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
USB_DEVICE_ID_GLORIOUS_MODEL_O) },
+#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_SINOWEALTH,
USB_DEVICE_ID_GLORIOUS_MODEL_D) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LAVIEW,
diff --git a/drivers/hid/hid_glorious_rust.rs b/drivers/hid/hid_glorious_rust.rs
new file mode 100644
index 000000000000..8cffc1c605dd
--- /dev/null
+++ b/drivers/hid/hid_glorious_rust.rs
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Rahul Rameshbabu <sergeantsagara@protonmail.com>
+
+//! Rust reference HID driver for Glorious Model O and O- mice.
+
+use kernel::{self, bindings, device, hid, prelude::*};
+
+struct GloriousRust;
+
+kernel::hid_device_table!(
+ HID_TABLE,
+ MODULE_HID_TABLE,
+ <GloriousRust as hid::Driver>::IdInfo,
+ [(
+ hid::DeviceId::new_usb(
+ hid::Group::Generic,
+ bindings::USB_VENDOR_ID_SINOWEALTH,
+ bindings::USB_DEVICE_ID_GLORIOUS_MODEL_O,
+ ),
+ (),
+ )]
+);
+
+#[vtable]
+impl hid::Driver for GloriousRust {
+ type IdInfo = ();
+ const ID_TABLE: hid::IdTable<Self::IdInfo> = &HID_TABLE;
+
+ /// Fix the Glorious Model O and O- consumer input report descriptor to use
+ /// the variable and relative flag, while clearing the const flag.
+ ///
+ /// Without this fixup, inputs from the mice will be ignored.
+ fn report_fixup<'a, 'b: 'a>(hdev: &hid::Device<device::Core>, rdesc: &'b mut [u8]) -> &'a [u8] {
+ if rdesc.len() == 213
+ && (rdesc[84] == 129 && rdesc[85] == 3)
+ && (rdesc[112] == 129 && rdesc[113] == 3)
+ && (rdesc[140] == 129 && rdesc[141] == 3)
+ {
+ dev_info!(
+ hdev.as_ref(),
+ "patching Glorious Model O consumer control report descriptor\n"
+ );
+
+ rdesc[85] = hid::MAIN_ITEM_VARIABLE | hid::MAIN_ITEM_RELATIVE;
+ rdesc[113] = hid::MAIN_ITEM_VARIABLE | hid::MAIN_ITEM_RELATIVE;
+ rdesc[141] = hid::MAIN_ITEM_VARIABLE | hid::MAIN_ITEM_RELATIVE;
+ }
+
+ rdesc
+ }
+}
+
+kernel::module_hid_driver! {
+ type: GloriousRust,
+ name: "GloriousRust",
+ authors: ["Rahul Rameshbabu <sergeantsagara@protonmail.com>"],
+ description: "Rust reference HID driver for Glorious Model O and O- mice",
+ license: "GPL",
+}
--
2.47.2
^ permalink raw reply related
* [PATCH v3 RESEND RESEND 2/3] rust: core abstractions for HID drivers
From: Rahul Rameshbabu @ 2025-09-13 16:13 UTC (permalink / raw)
To: linux-input, linux-kernel, rust-for-linux
Cc: Jiri Kosina, a.hindborg, alex.gaynor, aliceryhl, benno.lossin,
Benjamin Tissoires, bjorn3_gh, boqun.feng, dakr, db48x, gary,
ojeda, tmgross, peter.hutterer, Rahul Rameshbabu
In-Reply-To: <20250913161222.3889-1-sergeantsagara@protonmail.com>
These abstractions enable the development of HID drivers in Rust by binding
with the HID core C API. They provide Rust types that map to the
equivalents in C. In this initial draft, only hid_device and hid_device_id
are provided direct Rust type equivalents. hid_driver is specially wrapped
with a custom Driver type. The module_hid_driver! macro provides analogous
functionality to its C equivalent. Only the .report_fixup callback is
binded to Rust so far.
Future work for these abstractions would include more bindings for common
HID-related types, such as hid_field, hid_report_enum, and hid_report as
well as more bus callbacks. Providing Rust equivalents to useful core HID
functions will also be necessary for HID driver development in Rust.
Signed-off-by: Rahul Rameshbabu <sergeantsagara@protonmail.com>
---
Notes:
Some points I did not address from the last review cycle:
* I did not look into autogenerating all the getter functions for various
fields exported from the binded C structures.
- I would be interested in hearing opinions from folks actively involved
with Rust for Linux on this topic.
Changelog:
v2->v3:
* Implemented AlwaysRefCounted trait using embedded struct device's
reference counts instead of the separate reference counter in struct
hid_device
* Used &raw mut as appropriate
* Binded include/linux/device.h for get_device and put_device
* Cleaned up various comment related formatting
* Minified dev_err! format string
* Updated Group enum to be repr(u16)
* Implemented From<u16> trait for Group
* Added TODO comment when const_trait_impl stabilizes
* Made group getter functions return a Group variant instead of a raw
number
* Made sure example code builds
v1->v2:
* Binded drivers/hid/hid-ids.h for use in Rust drivers
* Remove pre-emptive referencing of a C HID driver instance before
it is fully initialized in the driver registration path
* Moved static getters to generic Device trait implementation, so
they can be used by all device::DeviceContext
* Use core macros for supporting DeviceContext transitions
* Implemented the AlwaysRefCounted and AsRef traits
* Make use for dev_err! as appropriate
RFC->v1:
* Use Danilo's core infrastructure
* Account for HID device groups
* Remove probe and remove callbacks
* Implement report_fixup support
* Properly comment code including SAFETY comments
MAINTAINERS | 9 +
drivers/hid/Kconfig | 8 +
rust/bindings/bindings_helper.h | 3 +
rust/kernel/hid.rs | 503 ++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 2 +
5 files changed, 525 insertions(+)
create mode 100644 rust/kernel/hid.rs
diff --git a/MAINTAINERS b/MAINTAINERS
index dd810da5261b..6c60765f2aaa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10686,6 +10686,15 @@ F: include/uapi/linux/hid*
F: samples/hid/
F: tools/testing/selftests/hid/
+HID CORE LAYER [RUST]
+M: Rahul Rameshbabu <sergeantsagara@protonmail.com>
+R: Benjamin Tissoires <bentiss@kernel.org>
+L: linux-input@vger.kernel.org
+S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git rust
+F: drivers/hid/*.rs
+F: rust/kernel/hid.rs
+
HID LOGITECH DRIVERS
R: Filipe Laíns <lains@riseup.net>
L: linux-input@vger.kernel.org
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 43859fc75747..922e76e18af2 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -744,6 +744,14 @@ config HID_MEGAWORLD_FF
Say Y here if you have a Mega World based game controller and want
to have force feedback support for it.
+config RUST_HID_ABSTRACTIONS
+ bool "Rust HID abstractions support"
+ depends on RUST
+ depends on HID=y
+ help
+ Adds support needed for HID drivers written in Rust. It provides a
+ wrapper around the C hid core.
+
config HID_REDRAGON
tristate "Redragon keyboards"
default !EXPERT
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 8cbb660e2ec2..7145fb1cdff1 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -45,6 +45,7 @@
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
#include <linux/cred.h>
+#include <linux/device.h>
#include <linux/device/faux.h>
#include <linux/dma-mapping.h>
#include <linux/errname.h>
@@ -52,6 +53,8 @@
#include <linux/file.h>
#include <linux/firmware.h>
#include <linux/fs.h>
+#include <linux/hid.h>
+#include "../../drivers/hid/hid-ids.h"
#include <linux/jiffies.h>
#include <linux/jump_label.h>
#include <linux/mdio.h>
diff --git a/rust/kernel/hid.rs b/rust/kernel/hid.rs
new file mode 100644
index 000000000000..a93804af8b78
--- /dev/null
+++ b/rust/kernel/hid.rs
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Rahul Rameshbabu <sergeantsagara@protonmail.com>
+
+//! Abstractions for the HID interface.
+//!
+//! C header: [`include/linux/hid.h`](srctree/include/linux/hid.h)
+
+use crate::{device, device_id::RawDeviceId, driver, error::*, prelude::*, types::Opaque};
+use core::{
+ marker::PhantomData,
+ ptr::{addr_of_mut, NonNull},
+};
+
+/// Indicates the item is static read-only.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_CONSTANT: u8 = bindings::HID_MAIN_ITEM_CONSTANT as u8;
+
+/// Indicates the item represents data from a physical control.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_VARIABLE: u8 = bindings::HID_MAIN_ITEM_VARIABLE as u8;
+
+/// Indicates the item should be treated as a relative change from the previous
+/// report.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_RELATIVE: u8 = bindings::HID_MAIN_ITEM_RELATIVE as u8;
+
+/// Indicates the item should wrap around when reaching the extreme high or
+/// extreme low values.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_WRAP: u8 = bindings::HID_MAIN_ITEM_WRAP as u8;
+
+/// Indicates the item should wrap around when reaching the extreme high or
+/// extreme low values.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_NONLINEAR: u8 = bindings::HID_MAIN_ITEM_NONLINEAR as u8;
+
+/// Indicates whether the control has a preferred state it will physically
+/// return to without user intervention.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_NO_PREFERRED: u8 = bindings::HID_MAIN_ITEM_NO_PREFERRED as u8;
+
+/// Indicates whether the control has a physical state where it will not send
+/// any reports.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_NULL_STATE: u8 = bindings::HID_MAIN_ITEM_NULL_STATE as u8;
+
+/// Indicates whether the control requires host system logic to change state.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_VOLATILE: u8 = bindings::HID_MAIN_ITEM_VOLATILE as u8;
+
+/// Indicates whether the item is fixed size or a variable buffer of bytes.
+///
+/// Refer to [Device Class Definition for HID 1.11]
+/// Section 6.2.2.5 Input, Output, and Feature Items.
+///
+/// [Device Class Definition for HID 1.11]: https://www.usb.org/sites/default/files/hid1_11.pdf
+pub const MAIN_ITEM_BUFFERED_BYTE: u8 = bindings::HID_MAIN_ITEM_BUFFERED_BYTE as u8;
+
+/// HID device groups are intended to help categories HID devices based on a set
+/// of common quirks and logic that they will require to function correctly.
+#[repr(u16)]
+pub enum Group {
+ /// Used to match a device against any group when probing.
+ Any = bindings::HID_GROUP_ANY as u16,
+
+ /// Indicates a generic device that should need no custom logic from the
+ /// core HID stack.
+ Generic = bindings::HID_GROUP_GENERIC as u16,
+
+ /// Maps multitouch devices to hid-multitouch instead of hid-generic.
+ Multitouch = bindings::HID_GROUP_MULTITOUCH as u16,
+
+ /// Used for autodetecing and mapping of HID sensor hubs to
+ /// hid-sensor-hub.
+ SensorHub = bindings::HID_GROUP_SENSOR_HUB as u16,
+
+ /// Used for autodetecing and mapping Win 8 multitouch devices to set the
+ /// needed quirks.
+ MultitouchWin8 = bindings::HID_GROUP_MULTITOUCH_WIN_8 as u16,
+
+ // Vendor-specific device groups.
+ /// Used to distinguish Synpatics touchscreens from other products. The
+ /// touchscreens will be handled by hid-multitouch instead, while everything
+ /// else will be managed by hid-rmi.
+ RMI = bindings::HID_GROUP_RMI as u16,
+
+ /// Used for hid-core handling to automatically identify Wacom devices and
+ /// have them probed by hid-wacom.
+ Wacom = bindings::HID_GROUP_WACOM as u16,
+
+ /// Used by logitech-djreceiver and logitech-djdevice to autodetect if
+ /// devices paied to the DJ receivers are DJ devices and handle them with
+ /// the device driver.
+ LogitechDJDevice = bindings::HID_GROUP_LOGITECH_DJ_DEVICE as u16,
+
+ /// Since the Valve Steam Controller only has vendor-specific usages,
+ /// prevent hid-generic from parsing its reports since there would be
+ /// nothing hid-generic could do for the device.
+ Steam = bindings::HID_GROUP_STEAM as u16,
+
+ /// Used to differentiate 27 Mhz frequency Logitech DJ devices from other
+ /// Logitech DJ devices.
+ Logitech27MHzDevice = bindings::HID_GROUP_LOGITECH_27MHZ_DEVICE as u16,
+
+ /// Used for autodetecting and mapping Vivaldi devices to hid-vivaldi.
+ Vivaldi = bindings::HID_GROUP_VIVALDI as u16,
+}
+
+// TODO: use `const_trait_impl` once stabilized:
+//
+// ```
+// impl const From<Group> for u16 {
+// /// [`Group`] variants are represented by [`u16`] values.
+// fn from(value: Group) -> Self {
+// value as Self
+// }
+// }
+// ```
+impl Group {
+ /// Internal function used to convert [`Group`] variants into [`u16`].
+ const fn into(self) -> u16 {
+ self as u16
+ }
+}
+
+impl From<u16> for Group {
+ /// [`u16`] values can be safely converted to [`Group`] variants.
+ fn from(value: u16) -> Self {
+ match value.into() {
+ bindings::HID_GROUP_GENERIC => Group::Generic,
+ bindings::HID_GROUP_MULTITOUCH => Group::Multitouch,
+ bindings::HID_GROUP_SENSOR_HUB => Group::SensorHub,
+ bindings::HID_GROUP_MULTITOUCH_WIN_8 => Group::MultitouchWin8,
+ bindings::HID_GROUP_RMI => Group::RMI,
+ bindings::HID_GROUP_WACOM => Group::Wacom,
+ bindings::HID_GROUP_LOGITECH_DJ_DEVICE => Group::LogitechDJDevice,
+ bindings::HID_GROUP_STEAM => Group::Steam,
+ bindings::HID_GROUP_LOGITECH_27MHZ_DEVICE => Group::Logitech27MHzDevice,
+ bindings::HID_GROUP_VIVALDI => Group::Vivaldi,
+ _ => Group::Any,
+ }
+ }
+}
+
+/// The HID device representation.
+///
+/// This structure represents the Rust abstraction for a C `struct hid_device`.
+/// The implementation abstracts the usage of an already existing C `struct
+/// hid_device` within Rust code that we get passed from the C side.
+///
+/// # Invariants
+///
+/// A [`Device`] instance represents a valid `struct hid_device` created by the
+/// C portion of the kernel.
+#[repr(transparent)]
+pub struct Device<Ctx: device::DeviceContext = device::Normal>(
+ Opaque<bindings::hid_device>,
+ PhantomData<Ctx>,
+);
+
+impl<Ctx: device::DeviceContext> Device<Ctx> {
+ fn as_raw(&self) -> *mut bindings::hid_device {
+ self.0.get()
+ }
+
+ /// Returns the HID transport bus ID.
+ pub fn bus(&self) -> u16 {
+ // SAFETY: `self.as_raw` is a valid pointer to a `struct hid_device`
+ unsafe { *self.as_raw() }.bus
+ }
+
+ /// Returns the HID report group.
+ pub fn group(&self) -> Group {
+ // SAFETY: `self.as_raw` is a valid pointer to a `struct hid_device`
+ unsafe { *self.as_raw() }.group.into()
+ }
+
+ /// Returns the HID vendor ID.
+ pub fn vendor(&self) -> u32 {
+ // SAFETY: `self.as_raw` is a valid pointer to a `struct hid_device`
+ unsafe { *self.as_raw() }.vendor
+ }
+
+ /// Returns the HID product ID.
+ pub fn product(&self) -> u32 {
+ // SAFETY: `self.as_raw` is a valid pointer to a `struct hid_device`
+ unsafe { *self.as_raw() }.product
+ }
+}
+
+// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
+// argument.
+kernel::impl_device_context_deref!(unsafe { Device });
+kernel::impl_device_context_into_aref!(Device);
+
+// SAFETY: Instances of `Device` are always reference-counted.
+unsafe impl crate::types::AlwaysRefCounted for Device {
+ fn inc_ref(&self) {
+ // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero.
+ unsafe { bindings::get_device(&raw mut (*self.as_raw()).dev) };
+ }
+
+ unsafe fn dec_ref(obj: NonNull<Self>) {
+ // SAFETY: The safety requirements guarantee that the refcount is non-zero.
+ unsafe { bindings::put_device(&raw mut (*obj.cast::<bindings::hid_device>().as_ptr()).dev) }
+ }
+}
+
+impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> {
+ fn as_ref(&self) -> &device::Device<Ctx> {
+ // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid
+ // `struct hid_device`.
+ let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) };
+
+ // SAFETY: `dev` points to a valid `struct device`.
+ unsafe { device::Device::as_ref(dev) }
+ }
+}
+
+/// Abstraction for the HID device ID structure `struct hid_device_id`.
+#[repr(transparent)]
+#[derive(Clone, Copy)]
+pub struct DeviceId(bindings::hid_device_id);
+
+impl DeviceId {
+ /// Equivalent to C's `HID_USB_DEVICE` macro.
+ ///
+ /// Create a new `hid::DeviceId` from a group, vendor ID, and device ID
+ /// number.
+ pub const fn new_usb(group: Group, vendor: u32, product: u32) -> Self {
+ Self(bindings::hid_device_id {
+ bus: 0x3, // BUS_USB
+ group: group.into(),
+ vendor,
+ product,
+ driver_data: 0,
+ })
+ }
+
+ /// Returns the HID transport bus ID.
+ pub fn bus(&self) -> u16 {
+ self.0.bus
+ }
+
+ /// Returns the HID report group.
+ pub fn group(&self) -> Group {
+ self.0.group.into()
+ }
+
+ /// Returns the HID vendor ID.
+ pub fn vendor(&self) -> u32 {
+ self.0.vendor
+ }
+
+ /// Returns the HID product ID.
+ pub fn product(&self) -> u32 {
+ self.0.product
+ }
+}
+
+// SAFETY:
+// * `DeviceId` is a `#[repr(transparent)` wrapper of `hid_device_id` and does not add
+// additional invariants, so it's safe to transmute to `RawType`.
+// * `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field.
+unsafe impl RawDeviceId for DeviceId {
+ type RawType = bindings::hid_device_id;
+
+ const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::hid_device_id, driver_data);
+
+ fn index(&self) -> usize {
+ self.0.driver_data
+ }
+}
+
+/// [`IdTable`] type for HID.
+pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>;
+
+/// Create a HID [`IdTable`] with its alias for modpost.
+#[macro_export]
+macro_rules! hid_device_table {
+ ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => {
+ const $table_name: $crate::device_id::IdArray<
+ $crate::hid::DeviceId,
+ $id_info_type,
+ { $table_data.len() },
+ > = $crate::device_id::IdArray::new($table_data);
+
+ $crate::module_device_table!("hid", $module_table_name, $table_name);
+ };
+}
+
+/// The HID driver trait.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::{bindings, device, hid};
+///
+/// struct MyDriver;
+///
+/// kernel::hid_device_table!(
+/// HID_TABLE,
+/// MODULE_HID_TABLE,
+/// <MyDriver as hid::Driver>::IdInfo,
+/// [(
+/// hid::DeviceId::new_usb(
+/// hid::Group::Steam,
+/// bindings::USB_VENDOR_ID_VALVE,
+/// bindings::USB_DEVICE_ID_STEAM_DECK,
+/// ),
+/// (),
+/// )]
+/// );
+///
+/// #[vtable]
+/// impl hid::Driver for MyDriver {
+/// type IdInfo = ();
+/// const ID_TABLE: hid::IdTable<Self::IdInfo> = &HID_TABLE;
+///
+/// /// This function is optional to implement.
+/// fn report_fixup<'a, 'b: 'a>(_hdev: &hid::Device<device::Core>, rdesc: &'b mut [u8]) -> &'a [u8] {
+/// // Perform some report descriptor fixup.
+/// rdesc
+/// }
+/// }
+/// ```
+/// Drivers must implement this trait in order to get a HID driver registered.
+/// Please refer to the `Adapter` documentation for an example.
+#[vtable]
+pub trait Driver: Send {
+ /// The type holding information about each device id supported by the driver.
+ // TODO: Use `associated_type_defaults` once stabilized:
+ //
+ // ```
+ // type IdInfo: 'static = ();
+ // ```
+ type IdInfo: 'static;
+
+ /// The table of device ids supported by the driver.
+ const ID_TABLE: IdTable<Self::IdInfo>;
+
+ /// Called before report descriptor parsing. Can be used to mutate the
+ /// report descriptor before the core HID logic processes the descriptor.
+ /// Useful for problematic report descriptors that prevent HID devices from
+ /// functioning correctly.
+ ///
+ /// Optional to implement.
+ fn report_fixup<'a, 'b: 'a>(_hdev: &Device<device::Core>, _rdesc: &'b mut [u8]) -> &'a [u8] {
+ build_error!(VTABLE_DEFAULT_ERROR)
+ }
+}
+
+/// An adapter for the registration of HID drivers.
+pub struct Adapter<T: Driver>(T);
+
+// SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if
+// a preceding call to `register` has been successful.
+unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> {
+ type RegType = bindings::hid_driver;
+
+ unsafe fn register(
+ hdrv: &Opaque<Self::RegType>,
+ name: &'static CStr,
+ module: &'static ThisModule,
+ ) -> Result {
+ // SAFETY: It's safe to set the fields of `struct hid_driver` on initialization.
+ unsafe {
+ (*hdrv.get()).name = name.as_char_ptr();
+ (*hdrv.get()).id_table = T::ID_TABLE.as_ptr();
+ (*hdrv.get()).report_fixup = if T::HAS_REPORT_FIXUP {
+ Some(Self::report_fixup_callback)
+ } else {
+ None
+ };
+ }
+
+ // SAFETY: `hdrv` is guaranteed to be a valid `RegType`
+ to_result(unsafe {
+ bindings::__hid_register_driver(hdrv.get(), module.0, name.as_char_ptr())
+ })
+ }
+
+ unsafe fn unregister(hdrv: &Opaque<Self::RegType>) {
+ // SAFETY: `hdrv` is guaranteed to be a valid `RegType`
+ unsafe { bindings::hid_unregister_driver(hdrv.get()) }
+ }
+}
+
+impl<T: Driver + 'static> Adapter<T> {
+ extern "C" fn report_fixup_callback(
+ hdev: *mut bindings::hid_device,
+ buf: *mut u8,
+ size: *mut kernel::ffi::c_uint,
+ ) -> *const u8 {
+ // SAFETY: The HID subsystem only ever calls the report_fixup callback
+ // with a valid pointer to a `struct hid_device`.
+ //
+ // INVARIANT: `hdev` is valid for the duration of
+ // `report_fixup_callback()`.
+ let hdev = unsafe { &*hdev.cast::<Device<device::Core>>() };
+
+ // SAFETY: The HID subsystem only ever calls the report_fixup callback
+ // with a valid pointer to a `kernel::ffi::c_uint`.
+ //
+ // INVARIANT: `size` is valid for the duration of
+ // `report_fixup_callback()`.
+ let buf_len: usize = match unsafe { *size }.try_into() {
+ Ok(len) => len,
+ Err(e) => {
+ dev_err!(
+ hdev.as_ref(),
+ "Cannot fix report description due to {}!\n",
+ e
+ );
+
+ return buf;
+ }
+ };
+
+ // Build a mutable Rust slice from `buf` and `size`.
+ //
+ // SAFETY: The HID subsystem only ever calls the `report_fixup callback`
+ // with a valid pointer to a `u8` buffer.
+ //
+ // INVARIANT: `buf` is valid for the duration of
+ // `report_fixup_callback()`.
+ let rdesc_slice = unsafe { core::slice::from_raw_parts_mut(buf, buf_len) };
+ let rdesc_slice = T::report_fixup(hdev, rdesc_slice);
+
+ match rdesc_slice.len().try_into() {
+ // SAFETY: The HID subsystem only ever calls the report_fixup
+ // callback with a valid pointer to a `kernel::ffi::c_uint`.
+ //
+ // INVARIANT: `size` is valid for the duration of
+ // `report_fixup_callback()`.
+ Ok(len) => unsafe { *size = len },
+ Err(e) => {
+ dev_err!(
+ hdev.as_ref(),
+ "Fixed report description will not be used due to {}!\n",
+ e
+ );
+
+ return buf;
+ }
+ }
+
+ rdesc_slice.as_ptr()
+ }
+}
+
+/// Declares a kernel module that exposes a single HID driver.
+///
+/// # Examples
+///
+/// ```ignore
+/// kernel::module_hid_driver! {
+/// type: MyDriver,
+/// name: "Module name",
+/// authors: ["Author name"],
+/// description: "Description",
+/// license: "GPL",
+/// }
+/// ```
+#[macro_export]
+macro_rules! module_hid_driver {
+ ($($f:tt)*) => {
+ $crate::module_driver!(<T>, $crate::hid::Adapter<T>, { $($f)* });
+ };
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index e88bc4b27d6e..44c107f20174 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -80,6 +80,8 @@
pub mod firmware;
pub mod fmt;
pub mod fs;
+#[cfg(CONFIG_RUST_HID_ABSTRACTIONS)]
+pub mod hid;
pub mod init;
pub mod io;
pub mod ioctl;
--
2.47.2
^ permalink raw reply related
* [PATCH v3 RESEND RESEND 0/3] Initial work for Rust abstraction for HID device driver development
From: Rahul Rameshbabu @ 2025-09-13 16:12 UTC (permalink / raw)
To: linux-input, linux-kernel, rust-for-linux
Cc: Jiri Kosina, a.hindborg, alex.gaynor, aliceryhl, benno.lossin,
Benjamin Tissoires, bjorn3_gh, boqun.feng, dakr, db48x, gary,
ojeda, tmgross, peter.hutterer, Rahul Rameshbabu
Hello again,
I am doing another resend. Let me know if it makes sense to start sending out
work I have on top of these changes. I wanted to wait till these changes got
merged first but maybe that is not the right strategy?
https://lore.kernel.org/rust-for-linux/20250721020211.196394-2-sergeantsagara@protonmail.com/
I incorporated Danilo's and Miguel's feedback from my v2. Additionally, I
noticed I had basic formatting issues when running scripts/checkpatch.pl.
I made sure to check the generated rustdocs and that the Rust examples
compile as part of the kunit infrastructure. I dropped the kref bindings
as they are no longer needed for this series.
Link: https://lore.kernel.org/rust-for-linux/20250808061223.3770-1-sergeantsagara@protonmail.com/
Link: https://lore.kernel.org/rust-for-linux/20250721020211.196394-2-sergeantsagara@protonmail.com/
Link: https://lore.kernel.org/rust-for-linux/20250713211012.101476-4-sergeantsagara@protonmail.com/
Link: https://lore.kernel.org/rust-for-linux/20250629045031.92358-2-sergeantsagara@protonmail.com/
Link: https://lore.kernel.org/rust-for-linux/20250313160220.6410-2-sergeantsagara@protonmail.com/
Link: https://binary-eater.github.io/tags/usb-monitor-control/
Rahul Rameshbabu (3):
HID: core: Change hid_driver to use a const char* for name
rust: core abstractions for HID drivers
rust: hid: Glorious PC Gaming Race Model O and O- mice reference
driver
MAINTAINERS | 16 +
drivers/hid/Kconfig | 16 +
drivers/hid/Makefile | 1 +
drivers/hid/hid-glorious.c | 2 +
drivers/hid/hid_glorious_rust.rs | 60 ++++
include/linux/hid.h | 2 +-
rust/bindings/bindings_helper.h | 3 +
rust/kernel/hid.rs | 503 +++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 2 +
9 files changed, 604 insertions(+), 1 deletion(-)
create mode 100644 drivers/hid/hid_glorious_rust.rs
create mode 100644 rust/kernel/hid.rs
base-commit: 1523590203786bf4e1d29b7d08a7100c783f20ba
--
2.47.2
^ permalink raw reply
* [PATCH v3 RESEND RESEND 1/3] HID: core: Change hid_driver to use a const char* for name
From: Rahul Rameshbabu @ 2025-09-13 16:12 UTC (permalink / raw)
To: linux-input, linux-kernel, rust-for-linux
Cc: Jiri Kosina, a.hindborg, alex.gaynor, aliceryhl, benno.lossin,
Benjamin Tissoires, bjorn3_gh, boqun.feng, dakr, db48x, gary,
ojeda, tmgross, peter.hutterer, Rahul Rameshbabu
In-Reply-To: <20250913161222.3889-1-sergeantsagara@protonmail.com>
name is never mutated by the core HID stack. Making name a const char*
simplifies passing the string from Rust to C. Otherwise, it becomes
difficult to pass a 'static lifetime CStr from Rust to a char*, rather than
a const char*, due to lack of guarantee that the underlying data of the
CStr will not be mutated by the C code.
Signed-off-by: Rahul Rameshbabu <sergeantsagara@protonmail.com>
---
include/linux/hid.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 568a9d8c749b..d65c202783da 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -816,7 +816,7 @@ struct hid_usage_id {
* zero from them.
*/
struct hid_driver {
- char *name;
+ const char *name;
const struct hid_device_id *id_table;
struct list_head dyn_list;
--
2.47.2
^ permalink raw reply related
* Re: [regression] 1a8953f4f774 ("HID: Add IGNORE quirk for SMARTLINKTECHNOLOGY") causes issue with ID 4c4a:4155 Jieli Technology USB Composite Device
From: Staffan Melin @ 2025-09-13 13:11 UTC (permalink / raw)
To: Salvatore Bonaccorso
Cc: zhangheng, Jiri Kosina, Benjamin Tissoires, linux-input,
linux-kernel, regressions, stable, 1114557
In-Reply-To: <aMUxg6FLqDetwiGu@eldamar.lan>
Ah, thanks, I get it now :)
So I got 6.16.7, and the patch applied without problems.
But no luck, the same results as before: touchscreen not working, xinput
--list not showing the Jieli touchscreen. dmesg shows the same as
before, too.
Best regards,
Staffan
On 2025-09-13 10:55, Salvatore Bonaccorso wrote:
> Hi Staffan,
>
> chiming in hopefully it is of help.
>
> Now really with the patch ...
>
> On Fri, Sep 12, 2025 at 09:57:04PM +0200, Staffan Melin wrote:
>> Thank you,
>>
>> I tried to apply this patch to 6.12.39, the first problematic kernel,
>> as
>> well as 6.12.41, the first bad I tried, and on both I got an error
>> message:
>>
>> Applying: HID: quirks: Add device descriptor for 4c4a:4155
>> error: patch failed: drivers/hid/hid-quirks.c:1068
>> error: drivers/hid/hid-quirks.c: patch does not apply
>> Patch failed at 0001 HID: quirks: Add device descriptor for 4c4a:4155
>>
>> To which kernel version should I apply the patch?
>
> As the deveopment goes from mainline then down to stable series, the
> fix needs to be developed first for mainline. So the patch is targeted
> there.
>
> But please find attached an updated patch which hopefully should work
> which resolved the context changes on top of 6.12.47.
>
> But ideally you can provide a Tested-by on zhangheng's mainline patch
> to get things rolling as needed.
>
> Regards,
> Salvatore
^ permalink raw reply
* Re: [regression] 1a8953f4f774 ("HID: Add IGNORE quirk for SMARTLINKTECHNOLOGY") causes issue with ID 4c4a:4155 Jieli Technology USB Composite Device
From: Salvatore Bonaccorso @ 2025-09-13 8:55 UTC (permalink / raw)
To: Staffan Melin
Cc: zhangheng, Jiri Kosina, Benjamin Tissoires, linux-input,
linux-kernel, regressions, stable, 1114557
In-Reply-To: <aMUxHZF-7p7--1qS@eldamar.lan>
[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]
Hi Staffan,
chiming in hopefully it is of help.
Now really with the patch ...
On Fri, Sep 12, 2025 at 09:57:04PM +0200, Staffan Melin wrote:
> Thank you,
>
> I tried to apply this patch to 6.12.39, the first problematic kernel, as
> well as 6.12.41, the first bad I tried, and on both I got an error message:
>
> Applying: HID: quirks: Add device descriptor for 4c4a:4155
> error: patch failed: drivers/hid/hid-quirks.c:1068
> error: drivers/hid/hid-quirks.c: patch does not apply
> Patch failed at 0001 HID: quirks: Add device descriptor for 4c4a:4155
>
> To which kernel version should I apply the patch?
As the deveopment goes from mainline then down to stable series, the
fix needs to be developed first for mainline. So the patch is targeted
there.
But please find attached an updated patch which hopefully should work
which resolved the context changes on top of 6.12.47.
But ideally you can provide a Tested-by on zhangheng's mainline patch
to get things rolling as needed.
Regards,
Salvatore
[-- Attachment #2: 0001-HID-quirks-Add-device-descriptor-for-4c4a-4155.patch --]
[-- Type: text/x-diff, Size: 2181 bytes --]
From 16b03e802a858ebf3eafcfdb22e3025e1a840afd Mon Sep 17 00:00:00 2001
From: Zhang Heng <zhangheng@kylinos.cn>
Date: Fri, 12 Sep 2025 20:38:18 +0800
Subject: [PATCH] HID: quirks: Add device descriptor for 4c4a:4155
Two USB devices use the same ID. To avoid affecting functionality,
device descriptors are added to distinguish between them
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
---
drivers/hid/hid-quirks.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index 64f9728018b8..cbb658c2c60d 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -898,6 +898,17 @@ static const struct hid_device_id hid_ignore_list[] = {
#endif
{ HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_HP_5MP_CAMERA_5473) },
+ { }
+};
+/*
+ * hid_ignore_mic - Microphone devices do not require HID core processing
+ *
+ * Now there are two USB devices using the same ID, one is the microphone and the other
+ * is the touch screen. The touch screen requires hid core processing, but the
+ * microphone does not. The two have different bcdIDs, which will be used to
+ * distinguish them in the future
+ */
+static const struct hid_device_id hid_ignore_mic[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SMARTLINKTECHNOLOGY, USB_DEVICE_ID_SMARTLINKTECHNOLOGY_4155) },
{ }
};
@@ -1061,6 +1072,9 @@ bool hid_ignore(struct hid_device *hdev)
hid_match_id(hdev, hid_mouse_ignore_list))
return true;
+ if(hid_match_id(hdev, hid_ignore_mic) && (hdev->version > 1.1))
+ return true;
+
return !!hid_match_id(hdev, hid_ignore_list);
}
EXPORT_SYMBOL_GPL(hid_ignore);
@@ -1259,7 +1273,8 @@ static unsigned long hid_gets_squirk(const struct hid_device *hdev)
const struct hid_device_id *bl_entry;
unsigned long quirks = hdev->initial_quirks;
- if (hid_match_id(hdev, hid_ignore_list))
+ if (hid_match_id(hdev, hid_ignore_list) ||
+ (hid_match_id(hdev, hid_ignore_mic) && (hdev->version > 1.1)))
quirks |= HID_QUIRK_IGNORE;
if (hid_match_id(hdev, hid_have_special_driver))
--
2.51.0
^ permalink raw reply related
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