* [PATCH v5 5/9] HID: steelseries: Report POWER_SUPPLY_STATUS_FULL when full
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
Report POWER_SUPPLY_STATUS_FULL when the headset is connected, not
charging, and at 100% capacity. It reported DISCHARGING in that case
before.
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index c54c56db9ddd..ce5875c03e73 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -215,6 +215,8 @@ static int steelseries_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
else if (sd->battery_charging)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (sd->battery_capacity >= 100)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
--
2.54.0
^ permalink raw reply related
* [PATCH v5 4/9] HID: steelseries: Refactor Arctis driver to use device_info framework
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
Replace the per-product if/else quirk bitmap with a
steelseries_device_info struct. Each model provides its capabilities,
sync_interface, and request_status/parse_status callbacks. Report
sending is folded into steelseries_send_report() and the feature and
output wrappers, and the battery identifiers lose their per-model names.
This is mostly a refactor, but it changes two things:
- Battery status is polled from a periodic delayed work (status_work)
instead of being requested from raw_event(). The interval stays at
3s.
- Arctis 1 no longer clamps the reported capacity to 100% while
disconnected. The connection state already controls how this is
shown to userspace.
ARCTIS_1_X and ARCTIS_9 keep working. No new devices are added.
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 468 +++++++++++++++------------
1 file changed, 267 insertions(+), 201 deletions(-)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 079504e6932a..c54c56db9ddd 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -3,6 +3,7 @@
* HID driver for Steelseries arctis headsets
*
* Copyright (c) 2023 Bastien Nocera
+ * Copyright (c) 2026 Sriman Achanta
*/
#include <linux/device.h>
@@ -15,70 +16,89 @@
#include "hid-ids.h"
-#define STEELSERIES_ARCTIS_1_X BIT(0)
-#define STEELSERIES_ARCTIS_9 BIT(1)
+#define SS_CAP_BATTERY BIT(0)
+
+struct steelseries_device;
+
+struct steelseries_device_info {
+ unsigned long capabilities;
+
+ u8 sync_interface;
+
+ int (*request_status)(struct hid_device *hdev);
+ void (*parse_status)(struct steelseries_device *sd, u8 *data, int size);
+};
struct steelseries_device {
struct hid_device *hdev;
- unsigned long quirks;
+ const struct steelseries_device_info *info;
- struct delayed_work battery_work;
- spinlock_t lock;
- bool removed;
+ struct delayed_work status_work;
struct power_supply_desc battery_desc;
struct power_supply *battery;
- uint8_t battery_capacity;
bool headset_connected;
+ u8 battery_capacity;
bool battery_charging;
-};
-#define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS 3000
+ spinlock_t lock;
+ bool removed;
+};
-#define ARCTIS_1_BATTERY_RESPONSE_LEN 8
-#define ARCTIS_9_BATTERY_RESPONSE_LEN 64
-static const char arctis_1_battery_request[] = { 0x06, 0x12 };
-static const char arctis_9_battery_request[] = { 0x00, 0x20 };
+/*
+ * Headset report helpers
+ */
-static int steelseries_headset_request_battery(struct hid_device *hdev,
- const char *request, size_t len)
+static int steelseries_send_report(struct hid_device *hdev, const u8 *data,
+ int len, enum hid_report_type type)
{
- u8 *write_buf;
+ u8 *buf;
int ret;
- /* Request battery information */
- write_buf = kmemdup(request, len, GFP_KERNEL);
- if (!write_buf)
+ buf = kmemdup(data, len, GFP_KERNEL);
+ if (!buf)
return -ENOMEM;
- hid_dbg(hdev, "Sending battery request report");
- ret = hid_hw_raw_request(hdev, request[0], write_buf, len,
- HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
- if (ret < (int)len) {
- hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
- ret = -ENODATA;
- }
+ ret = hid_hw_raw_request(hdev, data[0], buf, len, type,
+ HID_REQ_SET_REPORT);
+ kfree(buf);
- kfree(write_buf);
- return ret;
+ if (ret < 0)
+ return ret;
+ if (ret < len)
+ return -EIO;
+
+ return 0;
}
-static void steelseries_headset_fetch_battery(struct hid_device *hdev)
+static inline int steelseries_send_output_report(struct hid_device *hdev,
+ const u8 *data, int len)
{
- int ret = 0;
+ return steelseries_send_report(hdev, data, len, HID_OUTPUT_REPORT);
+}
+
+/*
+ * Headset status request functions
+ */
- if (hdev->product == USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X)
- ret = steelseries_headset_request_battery(hdev,
- arctis_1_battery_request, sizeof(arctis_1_battery_request));
- else if (hdev->product == USB_DEVICE_ID_STEELSERIES_ARCTIS_9)
- ret = steelseries_headset_request_battery(hdev,
- arctis_9_battery_request, sizeof(arctis_9_battery_request));
+static int steelseries_arctis_1_request_status(struct hid_device *hdev)
+{
+ const u8 data[] = { 0x06, 0x12 };
- if (ret < 0)
- hid_dbg(hdev,
- "Battery query failed (err: %d)\n", ret);
+ return steelseries_send_output_report(hdev, data, sizeof(data));
}
+static int steelseries_arctis_9_request_status(struct hid_device *hdev)
+{
+ const u8 data[] = { 0x00, 0x20 };
+
+ return steelseries_send_output_report(hdev, data, sizeof(data));
+}
+
+/*
+ * Headset battery helpers
+ */
+
static int battery_capacity_to_level(int capacity)
{
if (capacity >= 50)
@@ -88,30 +108,101 @@ static int battery_capacity_to_level(int capacity)
return POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
}
-static void steelseries_headset_battery_timer_tick(struct work_struct *work)
+static u8 steelseries_map_capacity(u8 capacity, u8 min_in, u8 max_in)
{
- struct steelseries_device *sd = container_of(work,
- struct steelseries_device, battery_work.work);
- struct hid_device *hdev = sd->hdev;
+ if (capacity >= max_in)
+ return 100;
+ if (capacity <= min_in)
+ return 0;
+ return (capacity - min_in) * 100 / (max_in - min_in);
+}
- steelseries_headset_fetch_battery(hdev);
+/*
+ * Headset status parse functions
+ */
+
+static void steelseries_arctis_1_parse_status(struct steelseries_device *sd,
+ u8 *data, int size)
+{
+ /* Only the battery status report echoes the request header. */
+ if (size < 8 || data[0] != 0x06 || data[1] != 0x12)
+ return;
+
+ sd->headset_connected = (data[2] != 0x01);
+ sd->battery_capacity = data[3];
+}
+
+static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
+ u8 *data, int size)
+{
+ if (size < 5)
+ return;
+
+ if (data[0] == 0xaa && data[1] == 0x01) {
+ sd->headset_connected = true;
+ sd->battery_charging = (data[4] == 0x01);
+ sd->battery_capacity = steelseries_map_capacity(data[3], 0x68, 0x9d);
+ } else {
+ /* Device off: 0x55 (no status) or 0x03 (stale status). */
+ sd->headset_connected = false;
+ sd->battery_charging = false;
+ }
+}
+
+/*
+ * Device info definitions
+ */
+
+static const struct steelseries_device_info arctis_1_info = {
+ .sync_interface = 3,
+ .capabilities = SS_CAP_BATTERY,
+ .request_status = steelseries_arctis_1_request_status,
+ .parse_status = steelseries_arctis_1_parse_status,
+};
+
+static const struct steelseries_device_info arctis_9_info = {
+ .sync_interface = 0,
+ .capabilities = SS_CAP_BATTERY,
+ .request_status = steelseries_arctis_9_request_status,
+ .parse_status = steelseries_arctis_9_parse_status,
+};
+
+/*
+ * Headset wireless status and battery infrastructure
+ */
+
+#define STEELSERIES_HEADSET_STATUS_TIMEOUT_MS 3000
+
+static void
+steelseries_headset_set_wireless_status(struct hid_device *hdev,
+ bool connected)
+{
+ struct usb_interface *intf;
+
+ if (!hid_is_usb(hdev))
+ return;
+
+ intf = to_usb_interface(hdev->dev.parent);
+ usb_set_wireless_status(intf, connected ?
+ USB_WIRELESS_STATUS_CONNECTED :
+ USB_WIRELESS_STATUS_DISCONNECTED);
}
#define STEELSERIES_PREFIX "SteelSeries "
-#define STEELSERIES_PREFIX_LEN strlen(STEELSERIES_PREFIX)
-static int steelseries_headset_battery_get_property(struct power_supply *psy,
+static int steelseries_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
struct steelseries_device *sd = power_supply_get_drvdata(psy);
+ size_t prefix_len;
int ret = 0;
switch (psp) {
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = sd->hdev->name;
- while (!strncmp(val->strval, STEELSERIES_PREFIX, STEELSERIES_PREFIX_LEN))
- val->strval += STEELSERIES_PREFIX_LEN;
+ while ((prefix_len = str_has_prefix(val->strval, STEELSERIES_PREFIX)))
+ val->strval += prefix_len;
break;
case POWER_SUPPLY_PROP_MANUFACTURER:
val->strval = "SteelSeries";
@@ -120,12 +211,12 @@ static int steelseries_headset_battery_get_property(struct power_supply *psy,
val->intval = 1;
break;
case POWER_SUPPLY_PROP_STATUS:
- if (sd->headset_connected) {
- val->intval = sd->battery_charging ?
- POWER_SUPPLY_STATUS_CHARGING :
- POWER_SUPPLY_STATUS_DISCHARGING;
- } else
+ if (!sd->headset_connected)
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+ else if (sd->battery_charging)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break;
case POWER_SUPPLY_PROP_SCOPE:
val->intval = POWER_SUPPLY_SCOPE_DEVICE;
@@ -143,22 +234,7 @@ static int steelseries_headset_battery_get_property(struct power_supply *psy,
return ret;
}
-static void
-steelseries_headset_set_wireless_status(struct hid_device *hdev,
- bool connected)
-{
- struct usb_interface *intf;
-
- if (!hid_is_usb(hdev))
- return;
-
- intf = to_usb_interface(hdev->dev.parent);
- usb_set_wireless_status(intf, connected ?
- USB_WIRELESS_STATUS_CONNECTED :
- USB_WIRELESS_STATUS_DISCONNECTED);
-}
-
-static enum power_supply_property steelseries_headset_battery_props[] = {
+static enum power_supply_property steelseries_battery_props[] = {
POWER_SUPPLY_PROP_MODEL_NAME,
POWER_SUPPLY_PROP_MANUFACTURER,
POWER_SUPPLY_PROP_PRESENT,
@@ -168,7 +244,26 @@ static enum power_supply_property steelseries_headset_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
};
-static int steelseries_headset_battery_register(struct steelseries_device *sd)
+/*
+ * Delayed work handlers for status polling
+ */
+
+static void steelseries_status_timer_work_handler(struct work_struct *work)
+{
+ struct steelseries_device *sd = container_of(
+ work, struct steelseries_device, status_work.work);
+ unsigned long flags;
+
+ sd->info->request_status(sd->hdev);
+
+ spin_lock_irqsave(&sd->lock, flags);
+ if (!sd->removed)
+ schedule_delayed_work(&sd->status_work,
+ msecs_to_jiffies(STEELSERIES_HEADSET_STATUS_TIMEOUT_MS));
+ spin_unlock_irqrestore(&sd->lock, flags);
+}
+
+static int steelseries_battery_register(struct steelseries_device *sd)
{
static atomic_t battery_no = ATOMIC_INIT(0);
struct power_supply_config battery_cfg = { .drv_data = sd, };
@@ -176,25 +271,27 @@ static int steelseries_headset_battery_register(struct steelseries_device *sd)
int ret;
sd->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
- sd->battery_desc.properties = steelseries_headset_battery_props;
- sd->battery_desc.num_properties = ARRAY_SIZE(steelseries_headset_battery_props);
- sd->battery_desc.get_property = steelseries_headset_battery_get_property;
+ sd->battery_desc.properties = steelseries_battery_props;
+ sd->battery_desc.num_properties = ARRAY_SIZE(steelseries_battery_props);
+ sd->battery_desc.get_property = steelseries_battery_get_property;
sd->battery_desc.use_for_apm = 0;
n = atomic_inc_return(&battery_no) - 1;
sd->battery_desc.name = devm_kasprintf(&sd->hdev->dev, GFP_KERNEL,
- "steelseries_headset_battery_%ld", n);
+ "steelseries_headset_battery_%ld", n);
if (!sd->battery_desc.name)
return -ENOMEM;
/* avoid the warning of 0% battery while waiting for the first info */
- steelseries_headset_set_wireless_status(sd->hdev, false);
sd->battery_capacity = 100;
sd->battery_charging = false;
+ sd->headset_connected = false;
+ steelseries_headset_set_wireless_status(sd->hdev, false);
sd->battery = devm_power_supply_register(&sd->hdev->dev,
&sd->battery_desc, &battery_cfg);
if (IS_ERR(sd->battery)) {
ret = PTR_ERR(sd->battery);
+ sd->battery = NULL;
hid_err(sd->hdev,
"%s:power_supply_register failed with error %d\n",
__func__, ret);
@@ -202,59 +299,65 @@ static int steelseries_headset_battery_register(struct steelseries_device *sd)
}
power_supply_powers(sd->battery, &sd->hdev->dev);
- INIT_DELAYED_WORK(&sd->battery_work, steelseries_headset_battery_timer_tick);
- steelseries_headset_fetch_battery(sd->hdev);
-
- if (sd->quirks & STEELSERIES_ARCTIS_9) {
- /* The first fetch_battery request can remain unanswered in some cases */
- schedule_delayed_work(&sd->battery_work,
- msecs_to_jiffies(STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS));
- }
-
return 0;
}
-static bool steelseries_is_vendor_usage_page(struct hid_device *hdev, uint8_t usage_page)
-{
- return hdev->rdesc[0] == 0x06 &&
- hdev->rdesc[1] == usage_page &&
- hdev->rdesc[2] == 0xff;
-}
-
-static int steelseries_arctis_probe(struct hid_device *hdev, const struct hid_device_id *id)
+static int steelseries_arctis_probe(struct hid_device *hdev,
+ const struct hid_device_id *id)
{
+ const struct steelseries_device_info *info =
+ (const struct steelseries_device_info *)id->driver_data;
struct steelseries_device *sd;
+ struct usb_interface *intf;
+ u8 interface_num;
int ret;
- sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
- if (!sd)
- return -ENOMEM;
- hid_set_drvdata(hdev, sd);
- sd->hdev = hdev;
- sd->quirks = id->driver_data;
+ if (hid_is_usb(hdev)) {
+ intf = to_usb_interface(hdev->dev.parent);
+ interface_num = intf->cur_altsetting->desc.bInterfaceNumber;
+ } else {
+ return -ENODEV;
+ }
ret = hid_parse(hdev);
if (ret)
return ret;
- if (sd->quirks & STEELSERIES_ARCTIS_9 &&
- !steelseries_is_vendor_usage_page(hdev, 0xc0))
- return -ENODEV;
+ /* Let hid-generic handle non-sync interfaces */
+ if (interface_num != info->sync_interface)
+ return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+
+ sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+ sd->hdev = hdev;
+ sd->info = info;
spin_lock_init(&sd->lock);
+ hid_set_drvdata(hdev, sd);
+
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret)
return ret;
ret = hid_hw_open(hdev);
if (ret)
- return ret;
+ goto err_stop;
- if (steelseries_headset_battery_register(sd) < 0)
- hid_err(sd->hdev,
- "Failed to register battery for headset\n");
+ if (info->capabilities & SS_CAP_BATTERY) {
+ ret = steelseries_battery_register(sd);
+ if (ret < 0)
+ hid_warn(hdev, "Failed to register battery: %d\n", ret);
+ }
+
+ INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
+ schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
+ return 0;
+
+err_stop:
+ hid_hw_stop(hdev);
return ret;
}
@@ -262,130 +365,92 @@ static void steelseries_arctis_remove(struct hid_device *hdev)
{
struct steelseries_device *sd;
unsigned long flags;
+ struct usb_interface *intf;
+ u8 interface_num;
+
+ if (hid_is_usb(hdev)) {
+ intf = to_usb_interface(hdev->dev.parent);
+ interface_num = intf->cur_altsetting->desc.bInterfaceNumber;
+ } else {
+ return;
+ }
sd = hid_get_drvdata(hdev);
- spin_lock_irqsave(&sd->lock, flags);
- sd->removed = true;
- spin_unlock_irqrestore(&sd->lock, flags);
+ if (!sd) {
+ hid_hw_stop(hdev);
+ return;
+ }
- cancel_delayed_work_sync(&sd->battery_work);
+ if (interface_num == sd->info->sync_interface) {
+ spin_lock_irqsave(&sd->lock, flags);
+ sd->removed = true;
+ spin_unlock_irqrestore(&sd->lock, flags);
+
+ cancel_delayed_work_sync(&sd->status_work);
+ }
hid_hw_close(hdev);
hid_hw_stop(hdev);
}
-static uint8_t steelseries_headset_map_capacity(uint8_t capacity, uint8_t min_in, uint8_t max_in)
-{
- if (capacity >= max_in)
- return 100;
- if (capacity <= min_in)
- return 0;
- return (capacity - min_in) * 100 / (max_in - min_in);
-}
-
static int steelseries_arctis_raw_event(struct hid_device *hdev,
- struct hid_report *report, u8 *read_buf,
- int size)
+ struct hid_report *report, u8 *data, int size)
{
struct steelseries_device *sd = hid_get_drvdata(hdev);
- int capacity = sd->battery_capacity;
- bool connected = sd->headset_connected;
- bool charging = sd->battery_charging;
- unsigned long flags;
+ u8 old_capacity;
+ bool old_connected;
+ bool old_charging;
- if (hdev->product == USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X) {
- hid_dbg(sd->hdev,
- "Parsing raw event for Arctis 1 headset (%*ph)\n", size, read_buf);
- if (size < ARCTIS_1_BATTERY_RESPONSE_LEN ||
- memcmp(read_buf, arctis_1_battery_request, sizeof(arctis_1_battery_request))) {
- if (!delayed_work_pending(&sd->battery_work))
- goto request_battery;
- return 0;
- }
- if (read_buf[2] == 0x01) {
- connected = false;
- capacity = 100;
- } else {
- connected = true;
- capacity = read_buf[3];
- }
- }
+ if (!sd)
+ return 0;
- if (hdev->product == USB_DEVICE_ID_STEELSERIES_ARCTIS_9) {
- hid_dbg(sd->hdev,
- "Parsing raw event for Arctis 9 headset (%*ph)\n", size, read_buf);
- if (size < ARCTIS_9_BATTERY_RESPONSE_LEN) {
- if (!delayed_work_pending(&sd->battery_work))
- goto request_battery;
- return 0;
- }
+ old_capacity = sd->battery_capacity;
+ old_connected = sd->headset_connected;
+ old_charging = sd->battery_charging;
- if (read_buf[0] == 0xaa && read_buf[1] == 0x01) {
- connected = true;
- charging = read_buf[4] == 0x01;
-
- /*
- * Found no official documentation about min and max.
- * Values defined by testing.
- */
- capacity = steelseries_headset_map_capacity(read_buf[3], 0x68, 0x9d);
- } else {
- /*
- * Device is off and sends the last known status read_buf[1] == 0x03 or
- * there is no known status of the device read_buf[0] == 0x55
- */
- connected = false;
- charging = false;
- }
- }
+ sd->info->parse_status(sd, data, size);
- if (connected != sd->headset_connected) {
- hid_dbg(sd->hdev,
+ if (sd->headset_connected != old_connected) {
+ hid_dbg(hdev,
"Connected status changed from %sconnected to %sconnected\n",
- sd->headset_connected ? "" : "not ",
- connected ? "" : "not ");
- sd->headset_connected = connected;
- steelseries_headset_set_wireless_status(hdev, connected);
+ old_connected ? "" : "not ",
+ sd->headset_connected ? "" : "not ");
+
+ if (sd->battery) {
+ steelseries_headset_set_wireless_status(sd->hdev,
+ sd->headset_connected);
+ power_supply_changed(sd->battery);
+ }
}
- if (capacity != sd->battery_capacity) {
- hid_dbg(sd->hdev,
- "Battery capacity changed from %d%% to %d%%\n",
- sd->battery_capacity, capacity);
- sd->battery_capacity = capacity;
- power_supply_changed(sd->battery);
+ if (sd->battery_capacity != old_capacity) {
+ hid_dbg(hdev, "Battery capacity changed from %d%% to %d%%\n",
+ old_capacity, sd->battery_capacity);
+ if (sd->battery)
+ power_supply_changed(sd->battery);
}
- if (charging != sd->battery_charging) {
- hid_dbg(sd->hdev,
+ if (sd->battery_charging != old_charging) {
+ hid_dbg(hdev,
"Battery charging status changed from %scharging to %scharging\n",
- sd->battery_charging ? "" : "not ",
- charging ? "" : "not ");
- sd->battery_charging = charging;
- power_supply_changed(sd->battery);
+ old_charging ? "" : "not ",
+ sd->battery_charging ? "" : "not ");
+ if (sd->battery)
+ power_supply_changed(sd->battery);
}
-request_battery:
- spin_lock_irqsave(&sd->lock, flags);
- if (!sd->removed)
- schedule_delayed_work(&sd->battery_work,
- msecs_to_jiffies(STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS));
- spin_unlock_irqrestore(&sd->lock, flags);
-
return 0;
}
static const struct hid_device_id steelseries_arctis_devices[] = {
- { /* SteelSeries Arctis 1 Wireless for XBox */
- HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X),
- .driver_data = STEELSERIES_ARCTIS_1_X },
-
- { /* SteelSeries Arctis 9 Wireless for XBox */
- HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_9),
- .driver_data = STEELSERIES_ARCTIS_9 },
-
- { }
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X),
+ .driver_data = (unsigned long)&arctis_1_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_9),
+ .driver_data = (unsigned long)&arctis_9_info },
+ {}
};
MODULE_DEVICE_TABLE(hid, steelseries_arctis_devices);
@@ -402,3 +467,4 @@ MODULE_DESCRIPTION("HID driver for Steelseries arctis headsets");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Christian Mayer <git@mayer-bgk.de>");
MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
+MODULE_AUTHOR("Sriman Achanta <srimanachanta@gmail.com>");
--
2.54.0
^ permalink raw reply related
* [PATCH v5 7/9] HID: steelseries: Manage battery lifetime with refcounting
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
The next change shares one steelseries_device between two HID
interfaces, so the state can outlive either interface. Stop using devm
for it. Reference count the struct with a kref and free it from
steelseries_device_release(). Register and unregister the power supply
explicitly, and clear sd->battery under sd->lock in remove() so it is
not touched after it is unregistered.
Drop the global atomic battery counter and name the power supply after
the device (hdev->uniq, or dev_name() when empty), as hid-input and the
other HID battery drivers do.
No functional change for the current single-interface devices.
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 47 +++++++++++++++++++++-------
1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index d1552bf6567b..6c745058f70e 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -8,6 +8,8 @@
#include <linux/device.h>
#include <linux/hid.h>
+#include <linux/kref.h>
+#include <linux/slab.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <linux/spinlock.h>
@@ -30,6 +32,8 @@ struct steelseries_device_info {
};
struct steelseries_device {
+ struct kref refcnt;
+
struct hid_device *hdev;
const struct steelseries_device_info *info;
@@ -45,6 +49,14 @@ struct steelseries_device {
bool removed;
};
+static void steelseries_device_release(struct kref *ref)
+{
+ struct steelseries_device *sd =
+ container_of(ref, struct steelseries_device, refcnt);
+
+ kfree(sd);
+}
+
/*
* Headset report helpers
*/
@@ -267,9 +279,8 @@ static void steelseries_status_timer_work_handler(struct work_struct *work)
static int steelseries_battery_register(struct steelseries_device *sd)
{
- static atomic_t battery_no = ATOMIC_INIT(0);
struct power_supply_config battery_cfg = { .drv_data = sd, };
- unsigned long n;
+ struct power_supply *battery;
int ret;
sd->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
@@ -277,9 +288,10 @@ static int steelseries_battery_register(struct steelseries_device *sd)
sd->battery_desc.num_properties = ARRAY_SIZE(steelseries_battery_props);
sd->battery_desc.get_property = steelseries_battery_get_property;
sd->battery_desc.use_for_apm = 0;
- n = atomic_inc_return(&battery_no) - 1;
sd->battery_desc.name = devm_kasprintf(&sd->hdev->dev, GFP_KERNEL,
- "steelseries_headset_battery_%ld", n);
+ "steelseries_headset_battery_%s",
+ sd->hdev->uniq[0] ? sd->hdev->uniq :
+ dev_name(&sd->hdev->dev));
if (!sd->battery_desc.name)
return -ENOMEM;
@@ -289,17 +301,19 @@ static int steelseries_battery_register(struct steelseries_device *sd)
sd->headset_connected = false;
steelseries_headset_set_wireless_status(sd->hdev, false);
- sd->battery = devm_power_supply_register(&sd->hdev->dev,
+ battery = power_supply_register(&sd->hdev->dev,
&sd->battery_desc, &battery_cfg);
- if (IS_ERR(sd->battery)) {
- ret = PTR_ERR(sd->battery);
- sd->battery = NULL;
+ if (IS_ERR(battery)) {
+ ret = PTR_ERR(battery);
hid_err(sd->hdev,
"%s:power_supply_register failed with error %d\n",
__func__, ret);
return ret;
}
- power_supply_powers(sd->battery, &sd->hdev->dev);
+ power_supply_powers(battery, &sd->hdev->dev);
+
+ /* Assign on success only, so a concurrent raw_event never sees an ERR_PTR. */
+ sd->battery = battery;
return 0;
}
@@ -329,10 +343,11 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
if (interface_num != info->sync_interface)
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- sd = devm_kzalloc(&hdev->dev, sizeof(*sd), GFP_KERNEL);
+ sd = kzalloc_obj(*sd, GFP_KERNEL);
if (!sd)
return -ENOMEM;
+ kref_init(&sd->refcnt);
sd->hdev = hdev;
sd->info = info;
spin_lock_init(&sd->lock);
@@ -341,7 +356,7 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret)
- return ret;
+ goto err_put;
ret = hid_hw_open(hdev);
if (ret)
@@ -360,12 +375,15 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
err_stop:
hid_hw_stop(hdev);
+err_put:
+ kref_put(&sd->refcnt, steelseries_device_release);
return ret;
}
static void steelseries_arctis_remove(struct hid_device *hdev)
{
struct steelseries_device *sd;
+ struct power_supply *battery;
unsigned long flags;
struct usb_interface *intf;
u8 interface_num;
@@ -387,13 +405,20 @@ static void steelseries_arctis_remove(struct hid_device *hdev)
if (interface_num == sd->info->sync_interface) {
spin_lock_irqsave(&sd->lock, flags);
sd->removed = true;
+ battery = sd->battery;
+ sd->battery = NULL;
spin_unlock_irqrestore(&sd->lock, flags);
cancel_delayed_work_sync(&sd->status_work);
+
+ if (battery)
+ power_supply_unregister(battery);
}
hid_hw_close(hdev);
hid_hw_stop(hdev);
+
+ kref_put(&sd->refcnt, steelseries_device_release);
}
static int steelseries_arctis_raw_event(struct hid_device *hdev,
--
2.54.0
^ permalink raw reply related
* [PATCH v5 8/9] HID: steelseries: Add async status interface support
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
Some headsets expose a second HID interface that sends battery and
connection updates on its own. Watching that interface lets the driver
stop polling the sync interface. Add a
steelseries_device_info::async_interface field and the code to handle
it:
- The driver binds both the sync and async interfaces. The async
interface shares the steelseries_device created by the sync
interface. It finds the sibling with usb_ifnum_to_if(), takes a
reference, and returns -EPROBE_DEFER until the sync interface has
probed. If the sync interface never binds, the async interface
defers forever, which is fine here.
- raw_event() now holds sd->lock and re-checks sd->removed so events
on either interface are serialised against removal.
- status_work runs once for async devices instead of rearming. A
single status request is sent when the headset connects to get the
initial battery level.
No device sets async_interface yet. This is the infrastructure for the
next commit.
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 137 +++++++++++++++++++++------
1 file changed, 110 insertions(+), 27 deletions(-)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 6c745058f70e..689435c60ecb 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -26,6 +26,7 @@ struct steelseries_device_info {
unsigned long capabilities;
u8 sync_interface;
+ u8 async_interface;
int (*request_status)(struct hid_device *hdev);
void (*parse_status)(struct steelseries_device *sd, u8 *data, int size);
@@ -271,7 +272,8 @@ static void steelseries_status_timer_work_handler(struct work_struct *work)
sd->info->request_status(sd->hdev);
spin_lock_irqsave(&sd->lock, flags);
- if (!sd->removed)
+ /* Async devices push status events themselves; only poll once. */
+ if (!sd->removed && !sd->info->async_interface)
schedule_delayed_work(&sd->status_work,
msecs_to_jiffies(STEELSERIES_HEADSET_STATUS_TIMEOUT_MS));
spin_unlock_irqrestore(&sd->lock, flags);
@@ -318,6 +320,32 @@ static int steelseries_battery_register(struct steelseries_device *sd)
return 0;
}
+static struct hid_driver steelseries_arctis_driver;
+
+static struct steelseries_device *
+steelseries_get_sibling_sd(struct hid_device *hdev, int interface_num)
+{
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+ struct usb_device *usb_dev = interface_to_usbdev(intf);
+ struct usb_interface *sibling_intf;
+ struct hid_device *sibling_hdev;
+ struct steelseries_device *sd;
+
+ sibling_intf = usb_ifnum_to_if(usb_dev, interface_num);
+ if (!sibling_intf)
+ return NULL;
+
+ sibling_hdev = usb_get_intfdata(sibling_intf);
+ if (!sibling_hdev || sibling_hdev->driver != &steelseries_arctis_driver)
+ return NULL;
+
+ sd = hid_get_drvdata(sibling_hdev);
+ if (sd)
+ kref_get(&sd->refcnt);
+
+ return sd;
+}
+
static int steelseries_arctis_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -339,43 +367,81 @@ static int steelseries_arctis_probe(struct hid_device *hdev,
if (ret)
return ret;
- /* Let hid-generic handle non-sync interfaces */
- if (interface_num != info->sync_interface)
+ /* Let hid-generic handle non-vendor or unknown interfaces */
+ if (interface_num != info->sync_interface &&
+ (!info->async_interface || interface_num != info->async_interface))
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- sd = kzalloc_obj(*sd, GFP_KERNEL);
- if (!sd)
- return -ENOMEM;
-
- kref_init(&sd->refcnt);
- sd->hdev = hdev;
- sd->info = info;
- spin_lock_init(&sd->lock);
+ if (interface_num == info->sync_interface) {
+ sd = kzalloc_obj(*sd, GFP_KERNEL);
+ if (!sd)
+ return -ENOMEM;
+
+ kref_init(&sd->refcnt);
+ sd->hdev = hdev;
+ sd->info = info;
+ spin_lock_init(&sd->lock);
+ INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret)
+ goto err_free;
+
+ ret = hid_hw_open(hdev);
+ if (ret)
+ goto err_stop;
+
+ if (info->capabilities & SS_CAP_BATTERY) {
+ ret = steelseries_battery_register(sd);
+ if (ret < 0)
+ hid_warn(hdev, "Failed to register battery: %d\n", ret);
+ }
- hid_set_drvdata(hdev, sd);
+ /*
+ * Publish drvdata only once fully initialised: the async sibling
+ * attaches by reading it, so it must never observe a half-built or
+ * failed instance. A failed probe never gets here, so the error
+ * path below has nothing to unpublish.
+ */
+ hid_set_drvdata(hdev, sd);
+ schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
- ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
- if (ret)
- goto err_put;
+ return 0;
+ }
- ret = hid_hw_open(hdev);
- if (ret)
- goto err_stop;
+ /*
+ * The async interface shares the steelseries_device created by the
+ * sync interface. Defer until the sync interface has probed and
+ * published its drvdata.
+ */
+ if (info->async_interface && interface_num == info->async_interface) {
+ sd = steelseries_get_sibling_sd(hdev, info->sync_interface);
+ if (!sd)
+ return -EPROBE_DEFER;
+
+ hid_set_drvdata(hdev, sd);
+
+ ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ kref_put(&sd->refcnt, steelseries_device_release);
+ return ret;
+ }
- if (info->capabilities & SS_CAP_BATTERY) {
- ret = steelseries_battery_register(sd);
- if (ret < 0)
- hid_warn(hdev, "Failed to register battery: %d\n", ret);
+ ret = hid_hw_open(hdev);
+ if (ret) {
+ hid_hw_stop(hdev);
+ kref_put(&sd->refcnt, steelseries_device_release);
+ return ret;
+ }
+ return 0;
}
- INIT_DELAYED_WORK(&sd->status_work, steelseries_status_timer_work_handler);
- schedule_delayed_work(&sd->status_work, msecs_to_jiffies(100));
-
- return 0;
+ return -ENODEV;
err_stop:
hid_hw_stop(hdev);
-err_put:
+err_free:
+ /* drvdata is unpublished until full success, so no sibling can hold sd. */
kref_put(&sd->refcnt, steelseries_device_release);
return ret;
}
@@ -428,10 +494,21 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
u8 old_capacity;
bool old_connected;
bool old_charging;
+ bool is_async_interface;
+ unsigned long flags;
if (!sd)
return 0;
+ is_async_interface = (hdev != sd->hdev);
+
+ spin_lock_irqsave(&sd->lock, flags);
+
+ if (sd->removed) {
+ spin_unlock_irqrestore(&sd->lock, flags);
+ return 0;
+ }
+
old_capacity = sd->battery_capacity;
old_connected = sd->headset_connected;
old_charging = sd->battery_charging;
@@ -444,6 +521,10 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
old_connected ? "" : "not ",
sd->headset_connected ? "" : "not ");
+ if (sd->headset_connected && !old_connected &&
+ sd->info->async_interface && is_async_interface)
+ schedule_delayed_work(&sd->status_work, 0);
+
if (sd->battery) {
steelseries_headset_set_wireless_status(sd->hdev,
sd->headset_connected);
@@ -467,6 +548,8 @@ static int steelseries_arctis_raw_event(struct hid_device *hdev,
power_supply_changed(sd->battery);
}
+ spin_unlock_irqrestore(&sd->lock, flags);
+
return 0;
}
--
2.54.0
^ permalink raw reply related
* [PATCH v5 9/9] HID: steelseries: Add support for Arctis Nova 7 Gen2 family
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
The Arctis Nova 7 Gen2 headsets answer status polls, but they also send
unsolicited battery and connection updates on a second HID interface
(interface 5). Use that interface through async_interface so the driver
does not have to poll. Add request and parse helpers for the Gen2 status
format (0xb0/0xb7/0xb9/0xbb opcodes).
Add the eight USB product IDs that share this protocol:
0x22a1 Arctis Nova 7 2026
0x22a7 Arctis Nova 7P 2026
0x22a5 Arctis Nova 7X 2026
0x22a9 Arctis Nova 7 Diablo 2026
0x227e Arctis Nova 7 Gen 2
0x2258 Arctis Nova 7X Gen 2
0x229e Arctis Nova 7X Gen 2 (alternate PID)
0x22ad Arctis Nova 7X Gen 2 (alternate PID)
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-ids.h | 8 ++++
drivers/hid/hid-quirks.c | 8 ++++
drivers/hid/hid-steelseries-arctis.c | 63 ++++++++++++++++++++++++++++
3 files changed, 79 insertions(+)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 915e936cbf8b..6b5be86b1bdf 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -1379,6 +1379,14 @@
#define USB_DEVICE_ID_STEELSERIES_SRWS1 0x1410
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X 0x12b6
#define USB_DEVICE_ID_STEELSERIES_ARCTIS_9 0x12c2
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026 0x22a1
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026 0x22a7
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026 0x22a5
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026 0x22a9
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2 0x227e
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2 0x2258
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2 0x229e
+#define USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3 0x22ad
#define USB_VENDOR_ID_SUN 0x0430
#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
index f546179858c2..40a761b5df91 100644
--- a/drivers/hid/hid-quirks.c
+++ b/drivers/hid/hid-quirks.c
@@ -749,6 +749,14 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_SRWS1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X) },
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_9) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3) },
#endif
#if IS_ENABLED(CONFIG_HID_SUNPLUS)
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index 689435c60ecb..31d31f3f4b0e 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -108,6 +108,13 @@ static int steelseries_arctis_9_request_status(struct hid_device *hdev)
return steelseries_send_output_report(hdev, data, sizeof(data));
}
+static int steelseries_arctis_nova_request_status(struct hid_device *hdev)
+{
+ const u8 data[] = { 0x00, 0xb0 };
+
+ return steelseries_send_output_report(hdev, data, sizeof(data));
+}
+
/*
* Headset battery helpers
*/
@@ -162,6 +169,30 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
}
}
+static void steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_device *sd,
+ u8 *data, int size)
+{
+ if (size < 4)
+ return;
+
+ switch (data[0]) {
+ case 0xb0:
+ sd->headset_connected = (data[1] == 0x03);
+ sd->battery_capacity = data[2];
+ sd->battery_charging = (data[3] == 0x01);
+ break;
+ case 0xb7:
+ sd->battery_capacity = data[1];
+ break;
+ case 0xb9:
+ sd->headset_connected = (data[1] == 0x03);
+ break;
+ case 0xbb:
+ sd->battery_charging = (data[1] == 0x01);
+ break;
+ }
+}
+
/*
* Device info definitions
*/
@@ -180,6 +211,14 @@ static const struct steelseries_device_info arctis_9_info = {
.parse_status = steelseries_arctis_9_parse_status,
};
+static const struct steelseries_device_info arctis_nova_7_gen2_info = {
+ .sync_interface = 3,
+ .async_interface = 5,
+ .capabilities = SS_CAP_BATTERY,
+ .request_status = steelseries_arctis_nova_request_status,
+ .parse_status = steelseries_arctis_nova_7_gen2_parse_status,
+};
+
/*
* Headset wireless status and battery infrastructure
*/
@@ -560,6 +599,30 @@ static const struct hid_device_id steelseries_arctis_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
USB_DEVICE_ID_STEELSERIES_ARCTIS_9),
.driver_data = (unsigned long)&arctis_9_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_2026),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_P_2026),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_2026),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_DIABLO_2026),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_GEN2),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_2),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
+ { HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES,
+ USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_7_X_GEN2_3),
+ .driver_data = (unsigned long)&arctis_nova_7_gen2_info },
{}
};
MODULE_DEVICE_TABLE(hid, steelseries_arctis_devices);
--
2.54.0
^ permalink raw reply related
* [PATCH v5 6/9] HID: steelseries: Correct Arctis 9 battery calibration range
From: Sriman Achanta @ 2026-06-30 17:29 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-input, linux-kernel, Bastien Nocera, Simon Wood,
Christian Mayer, Sriman Achanta
In-Reply-To: <cover.1782840133.git.srimanachanta@gmail.com>
Map the Arctis 9 raw battery value over 0x64 (empty) to 0x9a (full)
instead of 0x68 to 0x9d. These values match the HeadsetControl project
[1] and fit the calibration points from an independent reverse
engineering of the battery tray (about 25% at raw 112, 50% at raw 125)
[2].
I do not have this headset. The values come from those references and
were not measured directly.
[1] https://github.com/Sapd/HeadsetControl/blob/master/lib/devices/steelseries_arctis_9.hpp
[2] https://magnier.io/reverse-engineering-arctis-9-battery-tray/
Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
---
drivers/hid/hid-steelseries-arctis.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
index ce5875c03e73..d1552bf6567b 100644
--- a/drivers/hid/hid-steelseries-arctis.c
+++ b/drivers/hid/hid-steelseries-arctis.c
@@ -141,7 +141,7 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
if (data[0] == 0xaa && data[1] == 0x01) {
sd->headset_connected = true;
sd->battery_charging = (data[4] == 0x01);
- sd->battery_capacity = steelseries_map_capacity(data[3], 0x68, 0x9d);
+ sd->battery_capacity = steelseries_map_capacity(data[3], 0x64, 0x9a);
} else {
/* Device off: 0x55 (no status) or 0x03 (stale status). */
sd->headset_connected = false;
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v5 8/9] HID: steelseries: Add async status interface support
From: sashiko-bot @ 2026-06-30 17:39 UTC (permalink / raw)
To: Sriman Achanta; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <c993054229da167e96332fc142d372091e8c7406.1782840133.git.srimanachanta@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unsynchronized access to the sibling interface's HID device and driver data in `steelseries_get_sibling_sd()` leads to Use-After-Free vulnerabilities during concurrent unbinding.
- [High] Unsafe retrieval of `intfdata` from a sibling USB interface without verifying the bound USB driver leads to type confusion.
--
commit 184e416637c40dbd71e035542907c5105f99d55d
Author: Sriman Achanta <srimanachanta@gmail.com>
HID: steelseries: Add async status interface support
This patch adds support for an async status interface on some Steelseries
headsets. The driver binds both sync and async interfaces, using the async
interface to push status events and delay its probe until the sync interface
is fully initialized.
> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> +static struct steelseries_device *
> +steelseries_get_sibling_sd(struct hid_device *hdev, int interface_num)
> +{
> + struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
> + struct usb_device *usb_dev = interface_to_usbdev(intf);
> + struct usb_interface *sibling_intf;
> + struct hid_device *sibling_hdev;
> + struct steelseries_device *sd;
> +
> + sibling_intf = usb_ifnum_to_if(usb_dev, interface_num);
> + if (!sibling_intf)
> + return NULL;
> +
> + sibling_hdev = usb_get_intfdata(sibling_intf);
> + if (!sibling_hdev || sibling_hdev->driver != &steelseries_arctis_driver)
[Severity: High]
Can a malicious USB device trigger an out-of-bounds read here?
If the device advertises the sync interface as a non-HID class (like Mass
Storage) but the async interface as HID, the USB core might bind a different
driver to the sync interface. In that case, usb_get_intfdata() would return
a driver-specific structure (like struct us_data) rather than a
struct hid_device.
Would it be safer to verify the bound USB driver on the sibling interface
before casting the intfdata and dereferencing sibling_hdev->driver?
> + return NULL;
> +
> + sd = hid_get_drvdata(sibling_hdev);
> + if (sd)
> + kref_get(&sd->refcnt);
[Severity: High]
Is there a race condition with concurrent unbinding here?
If the sync interface is concurrently unbound (e.g., via sysfs or physical
disconnection) while the async interface is probing, usb_get_intfdata()
and hid_get_drvdata() are called without holding device_lock() for the
sibling interface's device.
Could this allow the hid_device to be freed before checking
sibling_hdev->driver, or allow the steelseries_device (sd) to be freed
before kref_get() is called?
> +
> + return sd;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1782840133.git.srimanachanta@gmail.com?part=8
^ permalink raw reply
* Re: [PATCH v5 5/9] HID: steelseries: Report POWER_SUPPLY_STATUS_FULL when full
From: sashiko-bot @ 2026-06-30 17:39 UTC (permalink / raw)
To: Sriman Achanta; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <3d06ba7fcb4873c9d9d69c1fcbcd3d6bc21fadd0.1782840133.git.srimanachanta@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The patch incorrectly reports POWER_SUPPLY_STATUS_FULL for an unplugged, actively discharging wireless headset solely because its capacity is 100%.
--
commit 7a846a17b1f3241f94405b831860eba9d3123648
Author: Sriman Achanta <srimanachanta@gmail.com>
HID: steelseries: Report POWER_SUPPLY_STATUS_FULL when full
This commit updates the battery status reporting for SteelSeries headsets.
It now returns POWER_SUPPLY_STATUS_FULL when the headset is connected, not
charging, and at 100% capacity instead of returning DISCHARGING.
> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
> @@ -215,6 +215,8 @@ static int steelseries_battery_get_property(struct power_supply *psy,
> val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
> else if (sd->battery_charging)
> val->intval = POWER_SUPPLY_STATUS_CHARGING;
> + else if (sd->battery_capacity >= 100)
> + val->intval = POWER_SUPPLY_STATUS_FULL;
[Severity: Medium]
Will this incorrectly report POWER_SUPPLY_STATUS_FULL for an unplugged,
actively discharging wireless headset just because its capacity is at 100%?
When the headset is unplugged from external power but still fully charged,
sd->battery_charging is false and sd->battery_capacity is 100. It appears
this logic will now return POWER_SUPPLY_STATUS_FULL instead of
POWER_SUPPLY_STATUS_DISCHARGING, because there is no explicit check to verify
if the device is currently receiving external power.
Is there a way to ensure the headset is actually plugged in before returning
FULL, so that userspace tools don't incorrectly hide the discharge state
until the capacity drops below 100%?
> else
> val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
> break;
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1782840133.git.srimanachanta@gmail.com?part=5
^ permalink raw reply
* Re: [PATCH v5 9/9] HID: steelseries: Add support for Arctis Nova 7 Gen2 family
From: sashiko-bot @ 2026-06-30 17:44 UTC (permalink / raw)
To: Sriman Achanta; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <8d6f139f082f2b985bad0cb3f60f260e60a7f2e9.1782840133.git.srimanachanta@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [Medium] The global bounds check `if (size < 4)` incorrectly drops valid, shorter unsolicited status reports.
Pre-existing issues:
- [High] Concurrent sysfs unbind leads to Use-After-Free of sibling `hid_device` and `steelseries_device`.
- [High] Type confusion when retrieving the sibling HID device can lead to an out-of-bounds memory read.
--
commit 70087cd16ba3bb84894fac86ae371e8ee1265c7a
Author: Sriman Achanta <srimanachanta@gmail.com>
HID: steelseries: Add support for Arctis Nova 7 Gen2 family
This patch adds support for the Arctis Nova 7 Gen2 headsets. It introduces a
new parser for unsolicited battery and connection updates on a second HID
interface, and adds eight new USB product IDs to the supported devices list.
> diff --git a/drivers/hid/hid-steelseries-arctis.c b/drivers/hid/hid-steelseries-arctis.c
> index 689435c60ecbd..31d31f3f4b0e9 100644
> --- a/drivers/hid/hid-steelseries-arctis.c
> +++ b/drivers/hid/hid-steelseries-arctis.c
[ ... ]
> @@ -162,6 +169,30 @@ static void steelseries_arctis_9_parse_status(struct steelseries_device *sd,
> }
> }
>
> +static void steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_device *sd,
> + u8 *data, int size)
> +{
> + if (size < 4)
> + return;
[Severity: Medium]
Could this global bounds check prematurely discard valid unsolicited battery
and connection updates?
The new opcodes 0xb7, 0xb9, and 0xbb only require up to data[1] to be valid.
If the headset firmware sends these unsolicited updates as 2-byte short USB
HID packets reflecting their actual content size, this check will drop them.
[ ... ]
> @@ -180,6 +211,14 @@ static const struct steelseries_device_info arctis_9_info = {
> .parse_status = steelseries_arctis_9_parse_status,
> };
>
> +static const struct steelseries_device_info arctis_nova_7_gen2_info = {
> + .sync_interface = 3,
> + .async_interface = 5,
[Severity: High]
This is a pre-existing issue, but the addition of these new devices using the
async/sync interface mechanism heavily exercises it. Is it possible for a
concurrent sysfs unbind to cause a use-after-free?
During the async interface probe, steelseries_get_sibling_sd() calls
usb_get_intfdata(sibling_intf) without holding the device lock for the sibling
interface. If a user concurrently unbinds the sibling interface (e.g., via
sysfs), usbhid destroys the hid_device. This causes the probe path to
locklessly dereference the freed sibling_hdev->driver:
sibling_hdev = usb_get_intfdata(sibling_intf);
if (!sibling_hdev || sibling_hdev->driver != &steelseries_arctis_driver)
return NULL;
sd = hid_get_drvdata(sibling_hdev);
if (sd)
kref_get(&sd->refcnt);
It then calls kref_get(&sd->refcnt) on the associated private data, modifying
freed memory.
[Severity: High]
This isn't a bug introduced by this patch, but adding these devices expands
the exposure to a pre-existing type confusion issue. Could this lead to an
out-of-bounds memory read?
In steelseries_get_sibling_sd(), the driver extracts the private data via
usb_get_intfdata() and assumes it is a struct hid_device *:
sibling_intf = usb_ifnum_to_if(usb_dev, interface_num);
if (!sibling_intf)
return NULL;
sibling_hdev = usb_get_intfdata(sibling_intf);
if (!sibling_hdev || sibling_hdev->driver != &steelseries_arctis_driver)
return NULL;
If a crafted USB device is plugged in where the sibling interface (e.g.,
interface 0 or 3) is a non-HID class like USB Audio, a different driver will
bind and store its own private structure in intfdata.
The driver field sits hundreds of bytes deep into struct hid_device. Reading
it from a smaller structure belonging to another driver will read out-of-bounds
of the allocated SLUB object.
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1782840133.git.srimanachanta@gmail.com?part=9
^ permalink raw reply
* Re: [PATCH] HID: asus: add new Asus EC hid device for keyboard backlight and FN HotKeys
From: Alexandru Serdeliuc @ 2026-06-30 16:43 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: linux-kernel, linux-input
In-Reply-To: <20251221-add-support-for-the-asus-hid-ec-v1-1-35d7d70fbbfc@yahoo.com>
Hi Jiri, Benjamin,
Enquiring if anyone has had a chance to look over this patch series from
December?
To provide a bit of architectural context, this is a 100% pure HID
client driver.
This laptop (Asus Zenbook A14 UX3407QA) runs on the Qualcomm ARM64
Snapdragon platform.
Because it is an ARM device, it does not use traditional legacy x86
ACPI/WMI code.
Instead, the Fn hotkeys and keyboard backlight controls are routed
completely through standard vendor-specific HID reports (using Report ID
0x5A) over the existing I2C-HID transport layer.
It requires absolutely zero Device Tree modifications or external
platform subsystem hooks to bind or function.
The driver matches strictly on Vendor/Product ID (0x0B05 / 0x0220)
passed directly through the core HID subsystem.
I would highly appreciate any architectural feedback or a quick review!
Best regards,
Alexandru Marc Serdeliuc
On 12/21/25 12:12, Alexandru Marc Serdeliuc via B4 Relay wrote:
> From: Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
>
> Add support for Asus Embedded Controlled accessed via HID
>
> Currently working features:
> - Keyboard Backlight
> - FN HotKeys
>
> Signed-off-by: Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
> ---
> Add support for Asus Embedded Controlled accessed via HID
>
> Currently working features:
> - Keyboard Backlight
> - FN HotKeys
> ---
> drivers/hid/Kconfig | 10 ++
> drivers/hid/Makefile | 1 +
> drivers/hid/hid-asus-ec.c | 386 ++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 397 insertions(+)
>
> diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
> index 920a64b66b25b39e8259105c7c9b975fb77b2725..f0fbc951735eeea39198137294a9429f5b9d34b8 100644
> --- a/drivers/hid/Kconfig
> +++ b/drivers/hid/Kconfig
> @@ -202,6 +202,16 @@ config HID_ASUS
> - GL553V series
> - GL753V series
>
> +config HID_ASUS_EC
> + tristate "ASUS EC HID support (Zenbook A14 UX3407QA)"
> + depends on HID && I2C_HID
> + help
> + Say Y here if you have an ASUS Zenbook A14 (UX3407QA) and want
> + support for its EC-controlled keyboard backlight and Fn hotkeys
> +
> + This driver is currently only tested on the ASUS Zenbook A14
> + UX3407QA; behaviour on other models is unknown.
> +
> config HID_AUREAL
> tristate "Aureal"
> help
> diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
> index 361a7daedeb85454114def8afb5f58caeab58a00..bacccf00482c1b787ce59660e4366f8224aeefee 100644
> --- a/drivers/hid/Makefile
> +++ b/drivers/hid/Makefile
> @@ -34,6 +34,7 @@ obj-$(CONFIG_HID_APPLETB_BL) += hid-appletb-bl.o
> obj-$(CONFIG_HID_APPLETB_KBD) += hid-appletb-kbd.o
> obj-$(CONFIG_HID_CREATIVE_SB0540) += hid-creative-sb0540.o
> obj-$(CONFIG_HID_ASUS) += hid-asus.o
> +obj-$(CONFIG_HID_ASUS_EC) += hid-asus-ec.o
> obj-$(CONFIG_HID_AUREAL) += hid-aureal.o
> obj-$(CONFIG_HID_BELKIN) += hid-belkin.o
> obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o
> diff --git a/drivers/hid/hid-asus-ec.c b/drivers/hid/hid-asus-ec.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..1cf61fb2468d079827bfdb1db49daca905e53874
> --- /dev/null
> +++ b/drivers/hid/hid-asus-ec.c
> @@ -0,0 +1,386 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * ASUS EC HID driver for Zenbook A14 (UX3407QA)
> + *
> + * EC I2C HID driver for keyboard backlight and Fn hotkeys.
> + *
> + * Copyright (c) 2025 Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>
> + */
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/hid.h>
> +#include <linux/input.h>
> +#include <linux/leds.h>
> +#include <linux/slab.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/string.h>
> +#include <linux/delay.h>
> +#include <linux/pm.h>
> +
> +#define ASUS_VENDOR_ID 0x0B05
> +#define ASUS_PRODUCT_ID 0x0220
> +
> +#define A14_EC_REPORT_ID 0x5A
> +#define A14_EC_REPORT_SIZE 64
> +#define A14_EC_MAX_BACKLIGHT 3
> +
> +#define A14_EC_EVT_KEY_FN_ESC 0x4E
> +#define A14_EC_EVT_KEY_FN_F4 0xC7
> +#define A14_EC_EVT_KEY_FN_F5 0x10
> +#define A14_EC_EVT_KEY_FN_F6 0x20
> +#define A14_EC_EVT_KEY_FN_F8 0x7E
> +#define A14_EC_EVT_KEY_FN_F9 0x7C
> +#define A14_EC_EVT_KEY_FN_F10 0x85
> +#define A14_EC_EVT_KEY_FN_F11 0x6B
> +#define A14_EC_EVT_KEY_FN_F12 0x86
> +#define A14_EC_EVT_KEY_FN_F 0x9d
> +
> +
> +struct asus_hid_data {
> + struct hid_device *hdev;
> + struct led_classdev kbd_led_cdev;
> + struct input_dev *hotkey_input_dev;
> + enum led_brightness saved_brightness;
> +};
> +
> +static struct asus_hid_data *asus_data;
> +
> +static int asus_send_ec_command(struct hid_device *hdev, u8 *cmd_buf)
> +{
> + int ret;
> + u8 report_id = cmd_buf[0];
> +
> + ret = hid_hw_raw_request(hdev, report_id, cmd_buf, A14_EC_REPORT_SIZE,
> + HID_FEATURE_REPORT,
> + HID_REQ_SET_REPORT);
> +
> + if (ret < 0)
> + dev_err(&hdev->dev, "hid_hw_raw_request failed with status: %d\n", ret);
> +
> + return ret;
> +}
> +
> +static int asus_kbd_led_init(struct hid_device *hdev)
> +{
> + u8 ec_init_cmd[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xD0, 0x8F, 0x01 };
> + int ret;
> +
> + ret = asus_send_ec_command(hdev, ec_init_cmd);
> +
> + if (ret < 0)
> + return ret;
> +
> + u8 brightness_cmd[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xBA, 0xC5,
> + 0xC4, A14_EC_MAX_BACKLIGHT };
> +
> + ret = asus_send_ec_command(hdev, brightness_cmd);
> + if (ret < 0)
> + dev_warn(&hdev->dev, "Brightness init failed: %d\n", ret);
> +
> + return ret;
> +}
> +
> +static void asus_kbd_set_brightness(struct led_classdev *led_cdev,
> + enum led_brightness brightness)
> +{
> + struct asus_hid_data *data = container_of(led_cdev, struct asus_hid_data, kbd_led_cdev);
> +
> + u8 level = (u8)brightness;
> +
> + if (level > A14_EC_MAX_BACKLIGHT)
> + level = A14_EC_MAX_BACKLIGHT;
> +
> + u8 buf[A14_EC_REPORT_SIZE] = { A14_EC_REPORT_ID, 0xBA, 0xC5, 0xC4, level };
> +
> + asus_send_ec_command(data->hdev, buf);
> + msleep(20);
> + data->saved_brightness = (enum led_brightness)level;
> +}
> +
> +static int asus_raw_event(struct hid_device *hdev, struct hid_report *report,
> + u8 *raw_data, int size)
> +{
> + struct asus_hid_data *data = hid_get_drvdata(hdev);
> + struct input_dev *input_dev = data->hotkey_input_dev;
> +
> + if (report->id == A14_EC_REPORT_ID && size >= 2) {
> + u8 usage_code = raw_data[1];
> +
> + switch (usage_code) {
> + case A14_EC_EVT_KEY_FN_ESC:
> + input_event(input_dev, EV_KEY, KEY_FN_ESC, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_FN_ESC, 0);
> + input_sync(input_dev);
> + return 1;
> +
> + /* FN + F1, F2 and F3 are not managed by EC*/
> +
> + case A14_EC_EVT_KEY_FN_F4:
> + if (size >= 3) {
> + u8 current_level = data->saved_brightness;
> + u8 max_level = A14_EC_MAX_BACKLIGHT;
> + u8 next_level = (current_level + 1) % (max_level + 1);
> +
> + asus_kbd_set_brightness(&data->kbd_led_cdev,
> + (enum led_brightness)next_level);
> + if (next_level > current_level ||
> + (current_level == max_level && next_level == 0)) {
> + if (next_level == 0) {
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + } else {
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMUP, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMUP, 0);
> + input_sync(input_dev);
> + }
> + } else if (next_level < current_level) {
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY,
> + KEY_KBDILLUMDOWN, 0);
> + input_sync(input_dev);
> + }
> + }
> + return 1;
> + case A14_EC_EVT_KEY_FN_F5:
> + input_event(input_dev, EV_KEY, KEY_BRIGHTNESSDOWN, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_BRIGHTNESSDOWN, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F6:
> + input_event(input_dev, EV_KEY, KEY_BRIGHTNESSUP, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_BRIGHTNESSUP, 0);
> + input_sync(input_dev);
> + return 1;
> +
> + /* FN + F7 is not managed by the EC*/
> +
> + case A14_EC_EVT_KEY_FN_F8:
> + input_event(input_dev, EV_KEY, KEY_EMOJI_PICKER, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_EMOJI_PICKER, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F9:
> + input_event(input_dev, EV_KEY, KEY_MICMUTE, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_MICMUTE, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F10:
> + input_event(input_dev, EV_KEY, KEY_CAMERA_ACCESS_TOGGLE, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_CAMERA_ACCESS_TOGGLE, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F11:
> + input_event(input_dev, EV_KEY, KEY_TOUCHPAD_TOGGLE, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_TOUCHPAD_TOGGLE, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F12:
> + input_event(input_dev, EV_KEY, KEY_PROG1, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_PROG1, 0);
> + input_sync(input_dev);
> + return 1;
> + case A14_EC_EVT_KEY_FN_F:
> + input_event(input_dev, EV_KEY, KEY_PERFORMANCE, 1);
> + input_sync(input_dev);
> + input_event(input_dev, EV_KEY, KEY_PERFORMANCE, 0);
> + input_sync(input_dev);
> + return 1;
> + default:
> + return 0;
> + }
> + }
> + return 0;
> +}
> +
> +static int asus_hid_suspend(struct hid_device *hdev, pm_message_t message)
> +{
> + struct asus_hid_data *data = hid_get_drvdata(hdev);
> +
> + if (message.event == PM_EVENT_SUSPEND || message.event == PM_EVENT_HIBERNATE) {
> + asus_kbd_set_brightness(&data->kbd_led_cdev, LED_OFF);
> + return 0;
> + }
> +
> + dev_dbg(&hdev->dev, "Runtime suspend: turning off keyboard backlight\n");
> + asus_kbd_set_brightness(&data->kbd_led_cdev, LED_OFF);
> + return 0;
> +}
> +
> +
> +static int asus_hid_resume(struct hid_device *hdev)
> +{
> + struct asus_hid_data *data = hid_get_drvdata(hdev);
> + int ret;
> + int retry_count;
> +
> + msleep(40);
> +
> + dev_dbg(&hdev->dev, "Re-initialising EC backlight communication\n");
> + retry_count = 0;
> + do {
> + ret = asus_kbd_led_init(hdev);
> + if (ret >= 0) {
> + dev_dbg(&hdev->dev,
> + "EC init successful on attempt %d\n",
> + retry_count + 1);
> + break;
> + }
> + retry_count++;
> + dev_warn(&hdev->dev,
> + "EC init attempt %d failed: %d, retrying...\n",
> + retry_count, ret);
> + msleep(300 * retry_count);
> + } while (retry_count < 5);
> +
> + if (ret < 0) {
> + dev_err(&hdev->dev,
> + "EC init on resume failed after %d attempts: %d\n",
> + retry_count, ret);
> + dev_err(&hdev->dev,
> + "Keyboard backlight may not work; try reloading the driver\n");
> + } else {
> + dev_dbg(&hdev->dev, "EC backlight communication restored\n");
> + }
> +
> + asus_kbd_set_brightness(&data->kbd_led_cdev, data->saved_brightness);
> +
> + dev_info(&hdev->dev, "Resume complete\n");
> + return 0;
> +}
> +
> +static const struct hid_device_id asus_hid_devices[] = {
> + /* Tested on ASUS Zenbook A14 (UX3407QA) only. */
> + { HID_DEVICE(0x18, 0x00, ASUS_VENDOR_ID, ASUS_PRODUCT_ID) },
> + { } /* Terminating entry */
> +};
> +MODULE_DEVICE_TABLE(hid, asus_hid_devices);
> +
> +static int asus_hid_probe(struct hid_device *hdev, const struct hid_device_id *id)
> +{
> + int ret;
> + struct asus_hid_data *data;
> +
> + data = devm_kzalloc(&hdev->dev, sizeof(*data), GFP_KERNEL);
> + if (!data)
> + return -ENOMEM;
> + data->hdev = hdev;
> + hid_set_drvdata(hdev, data);
> + asus_data = data;
> + data->saved_brightness = A14_EC_MAX_BACKLIGHT;
> + ret = hid_parse(hdev);
> + if (ret)
> + return ret;
> + ret = hid_hw_start(hdev, HID_INPUT_REPORT | HID_OUTPUT_REPORT | HID_FEATURE_REPORT);
> + if (ret)
> + return ret;
> + data->hotkey_input_dev = input_allocate_device();
> + if (!data->hotkey_input_dev) {
> + dev_err(&hdev->dev, "Failed to allocate hotkey input device\n");
> + hid_hw_stop(hdev); return -ENOMEM;
> + }
> + data->hotkey_input_dev->name = "ASUS EC I2C HID hotkeys";
> + data->hotkey_input_dev->phys = "i2c-hid/input1/hotkeys";
> + data->hotkey_input_dev->id.bustype = hdev->bus;
> + data->hotkey_input_dev->id.vendor = hdev->vendor;
> + data->hotkey_input_dev->id.product = hdev->product;
> + data->hotkey_input_dev->dev.parent = &hdev->dev;
> + set_bit(EV_KEY, data->hotkey_input_dev->evbit);
> + set_bit(KEY_FN_ESC, data->hotkey_input_dev->keybit);
> + set_bit(KEY_KBDILLUMUP, data->hotkey_input_dev->keybit);
> + set_bit(KEY_KBDILLUMDOWN, data->hotkey_input_dev->keybit);
> + set_bit(KEY_BRIGHTNESSDOWN, data->hotkey_input_dev->keybit);
> + set_bit(KEY_BRIGHTNESSUP, data->hotkey_input_dev->keybit);
> + set_bit(KEY_SWITCHVIDEOMODE, data->hotkey_input_dev->keybit);
> + set_bit(KEY_EMOJI_PICKER, data->hotkey_input_dev->keybit);
> + set_bit(KEY_MICMUTE, data->hotkey_input_dev->keybit);
> + set_bit(KEY_CAMERA_ACCESS_TOGGLE, data->hotkey_input_dev->keybit);
> + set_bit(KEY_TOUCHPAD_TOGGLE, data->hotkey_input_dev->keybit);
> + set_bit(KEY_PROG1, data->hotkey_input_dev->keybit);
> + set_bit(KEY_PERFORMANCE, data->hotkey_input_dev->keybit);
> +
> + ret = input_register_device(data->hotkey_input_dev);
> + if (ret) {
> + dev_err(&hdev->dev, "Failed to register hotkey input device\n");
> + input_free_device(data->hotkey_input_dev); hid_hw_stop(hdev);
> + return ret;
> + }
> + asus_kbd_led_init(hdev);
> + data->kbd_led_cdev.name = "asus::kbd_backlight";
> + data->kbd_led_cdev.brightness_set = asus_kbd_set_brightness;
> + data->kbd_led_cdev.max_brightness = A14_EC_MAX_BACKLIGHT;
> + ret = led_classdev_register(&hdev->dev, &data->kbd_led_cdev);
> + if (ret) {
> + input_unregister_device(data->hotkey_input_dev);
> + hid_hw_stop(hdev);
> + return ret;
> + }
> + dev_info(&hdev->dev,
> + "ASUS EC HID driver for Zenbook A14 loaded for 0x%04x:0x%04x\n",
> + ASUS_VENDOR_ID, ASUS_PRODUCT_ID);
> + return 0;
> +}
> +static void asus_hid_remove(struct hid_device *hdev)
> +{
> + struct asus_hid_data *data = hid_get_drvdata(hdev);
> +
> + led_classdev_unregister(&data->kbd_led_cdev);
> + input_unregister_device(data->hotkey_input_dev);
> + hid_hw_stop(hdev);
> + asus_data = NULL;
> +}
> +static struct hid_driver hid_asus_ec_driver = {
> + .name = "hid-asus-ec",
> + .id_table = asus_hid_devices,
> + .probe = asus_hid_probe,
> + .remove = asus_hid_remove,
> + .raw_event = asus_raw_event,
> + .suspend = asus_hid_suspend,
> + .resume = asus_hid_resume,
> +};
> +module_hid_driver(hid_asus_ec_driver);
> +MODULE_AUTHOR("Alexandru Marc Serdeliuc <serdeliuk@yahoo.com>");
> +MODULE_DESCRIPTION("ASUS EC HID driver for Zenbook A14 (UX3407QA)");
> +MODULE_LICENSE("GPL");
>
> ---
> base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> change-id: 20251221-add-support-for-the-asus-hid-ec-a60b9a2d74b3
>
> Best regards,
^ permalink raw reply
* [dtor-input:for-linus] BUILD SUCCESS ee89db004238bd0b034f2a6176e175561658750b
From: kernel test robot @ 2026-06-30 18:42 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
branch HEAD: ee89db004238bd0b034f2a6176e175561658750b Input: maplemouse - fix NULL pointer dereference in open()
elapsed time: 746m
configs tested: 284
configs skipped: 3
The following configs have been built successfully.
More configs may be tested in the coming days.
tested configs:
alpha allnoconfig gcc-16.1.0
alpha allyesconfig gcc-16.1.0
alpha defconfig gcc-16.1.0
arc allmodconfig clang-23
arc allmodconfig gcc-16.1.0
arc allnoconfig gcc-16.1.0
arc allyesconfig clang-23
arc allyesconfig gcc-16.1.0
arc defconfig gcc-16.1.0
arc randconfig-001-20260630 clang-23
arc randconfig-001-20260701 gcc-12.5.0
arc randconfig-002-20260630 clang-23
arc randconfig-002-20260701 gcc-12.5.0
arm allnoconfig clang-23
arm allnoconfig gcc-16.1.0
arm allyesconfig clang-23
arm allyesconfig gcc-16.1.0
arm defconfig gcc-16.1.0
arm randconfig-001-20260630 clang-23
arm randconfig-001-20260701 gcc-12.5.0
arm randconfig-002-20260630 clang-23
arm randconfig-002-20260701 gcc-12.5.0
arm randconfig-003-20260630 clang-23
arm randconfig-003-20260701 gcc-12.5.0
arm randconfig-004-20260630 clang-23
arm randconfig-004-20260701 gcc-12.5.0
arm64 allmodconfig clang-23
arm64 allnoconfig gcc-16.1.0
arm64 defconfig gcc-16.1.0
arm64 randconfig-001-20260630 clang-23
arm64 randconfig-002-20260630 clang-23
arm64 randconfig-003-20260630 clang-23
arm64 randconfig-004-20260630 clang-23
csky allmodconfig gcc-16.1.0
csky allnoconfig gcc-16.1.0
csky defconfig gcc-16.1.0
csky randconfig-001-20260630 clang-23
csky randconfig-002-20260630 clang-23
hexagon allmodconfig clang-23
hexagon allmodconfig gcc-16.1.0
hexagon allnoconfig clang-23
hexagon allnoconfig gcc-16.1.0
hexagon defconfig gcc-16.1.0
hexagon randconfig-001-20260630 clang-18
hexagon randconfig-002-20260630 clang-18
i386 allmodconfig clang-22
i386 allmodconfig gcc-14
i386 allnoconfig gcc-14
i386 allnoconfig gcc-16.1.0
i386 allyesconfig clang-22
i386 allyesconfig gcc-14
i386 buildonly-randconfig-001 clang-22
i386 buildonly-randconfig-001-20260630 clang-22
i386 buildonly-randconfig-001-20260701 clang-22
i386 buildonly-randconfig-002 clang-22
i386 buildonly-randconfig-002-20260630 clang-22
i386 buildonly-randconfig-002-20260701 clang-22
i386 buildonly-randconfig-003 clang-22
i386 buildonly-randconfig-003-20260630 clang-22
i386 buildonly-randconfig-003-20260701 clang-22
i386 buildonly-randconfig-004 clang-22
i386 buildonly-randconfig-004-20260630 clang-22
i386 buildonly-randconfig-004-20260701 clang-22
i386 buildonly-randconfig-005 clang-22
i386 buildonly-randconfig-005-20260630 clang-22
i386 buildonly-randconfig-005-20260701 clang-22
i386 buildonly-randconfig-006 clang-22
i386 buildonly-randconfig-006-20260630 clang-22
i386 buildonly-randconfig-006-20260701 clang-22
i386 defconfig gcc-16.1.0
i386 randconfig-001 clang-22
i386 randconfig-001-20260630 clang-22
i386 randconfig-002 clang-22
i386 randconfig-002-20260630 clang-22
i386 randconfig-003 clang-22
i386 randconfig-003-20260630 clang-22
i386 randconfig-004 clang-22
i386 randconfig-004-20260630 clang-22
i386 randconfig-005 clang-22
i386 randconfig-005-20260630 clang-22
i386 randconfig-006 clang-22
i386 randconfig-006-20260630 clang-22
i386 randconfig-007 clang-22
i386 randconfig-007-20260630 clang-22
i386 randconfig-011 gcc-12
i386 randconfig-011-20260630 gcc-12
i386 randconfig-012 gcc-12
i386 randconfig-012-20260630 gcc-12
i386 randconfig-013 gcc-12
i386 randconfig-013-20260630 gcc-12
i386 randconfig-014 gcc-12
i386 randconfig-014-20260630 gcc-12
i386 randconfig-015 gcc-12
i386 randconfig-015-20260630 gcc-12
i386 randconfig-016 gcc-12
i386 randconfig-016-20260630 gcc-12
i386 randconfig-017 gcc-12
i386 randconfig-017-20260630 gcc-12
loongarch allmodconfig clang-19
loongarch allmodconfig clang-23
loongarch allnoconfig clang-20
loongarch allnoconfig gcc-16.1.0
loongarch defconfig clang-23
loongarch randconfig-001-20260630 clang-18
loongarch randconfig-002-20260630 clang-18
m68k alldefconfig gcc-16.1.0
m68k allmodconfig gcc-16.1.0
m68k allnoconfig gcc-16.1.0
m68k allyesconfig clang-23
m68k allyesconfig gcc-16.1.0
m68k defconfig clang-23
microblaze allnoconfig gcc-16.1.0
microblaze allyesconfig gcc-16.1.0
microblaze defconfig clang-23
mips allmodconfig gcc-16.1.0
mips allnoconfig gcc-16.1.0
mips allyesconfig gcc-16.1.0
mips bmips_stb_defconfig clang-17
mips malta_kvm_defconfig gcc-16.1.0
nios2 allmodconfig clang-20
nios2 allmodconfig gcc-11.5.0
nios2 allnoconfig clang-23
nios2 allnoconfig gcc-11.5.0
nios2 defconfig clang-23
nios2 randconfig-001-20260630 clang-18
nios2 randconfig-002-20260630 clang-18
openrisc allmodconfig clang-20
openrisc allmodconfig gcc-16.1.0
openrisc allnoconfig clang-23
openrisc allnoconfig gcc-16.1.0
openrisc defconfig gcc-16.1.0
parisc allmodconfig gcc-16.1.0
parisc allnoconfig clang-23
parisc allnoconfig gcc-16.1.0
parisc allyesconfig clang-17
parisc allyesconfig gcc-16.1.0
parisc defconfig gcc-16.1.0
parisc randconfig-001-20260630 clang-22
parisc randconfig-001-20260701 clang-17
parisc randconfig-002-20260630 clang-22
parisc randconfig-002-20260701 clang-17
parisc64 defconfig clang-23
powerpc allmodconfig gcc-16.1.0
powerpc allnoconfig clang-23
powerpc allnoconfig gcc-16.1.0
powerpc randconfig-001-20260630 clang-22
powerpc randconfig-001-20260701 clang-17
powerpc randconfig-002-20260630 clang-22
powerpc randconfig-002-20260701 clang-17
powerpc64 randconfig-001-20260630 clang-22
powerpc64 randconfig-001-20260701 clang-17
powerpc64 randconfig-002-20260630 clang-22
powerpc64 randconfig-002-20260701 clang-17
riscv allmodconfig clang-23
riscv allnoconfig clang-23
riscv allnoconfig gcc-16.1.0
riscv allyesconfig clang-23
riscv defconfig gcc-16.1.0
riscv randconfig-001 gcc-9.5.0
riscv randconfig-001-20260630 gcc-9.5.0
riscv randconfig-002 gcc-9.5.0
riscv randconfig-002-20260630 gcc-9.5.0
s390 allmodconfig clang-17
s390 allmodconfig clang-23
s390 allnoconfig clang-23
s390 allyesconfig gcc-16.1.0
s390 defconfig gcc-16.1.0
s390 randconfig-001 gcc-9.5.0
s390 randconfig-001-20260630 gcc-9.5.0
s390 randconfig-002 gcc-9.5.0
s390 randconfig-002-20260630 gcc-9.5.0
sh allmodconfig gcc-16.1.0
sh allnoconfig clang-23
sh allnoconfig gcc-16.1.0
sh allyesconfig clang-17
sh allyesconfig gcc-16.1.0
sh defconfig gcc-14
sh randconfig-001 gcc-9.5.0
sh randconfig-001-20260630 gcc-9.5.0
sh randconfig-002 gcc-9.5.0
sh randconfig-002-20260630 gcc-9.5.0
sh se7750_defconfig gcc-16.1.0
sparc allnoconfig clang-23
sparc allnoconfig gcc-16.1.0
sparc defconfig gcc-16.1.0
sparc randconfig-001 clang-17
sparc randconfig-001-20260630 clang-17
sparc randconfig-002 clang-17
sparc randconfig-002-20260630 clang-17
sparc64 allmodconfig clang-20
sparc64 defconfig gcc-14
sparc64 randconfig-001 clang-17
sparc64 randconfig-001-20260630 clang-17
sparc64 randconfig-002 clang-17
sparc64 randconfig-002-20260630 clang-17
um allmodconfig clang-17
um allmodconfig clang-23
um allnoconfig clang-16
um allnoconfig clang-23
um allyesconfig gcc-14
um allyesconfig gcc-16.1.0
um defconfig gcc-14
um i386_defconfig gcc-14
um randconfig-001 clang-17
um randconfig-001-20260630 clang-17
um randconfig-002 clang-17
um randconfig-002-20260630 clang-17
um x86_64_defconfig gcc-14
x86_64 allmodconfig clang-22
x86_64 allnoconfig clang-22
x86_64 allnoconfig clang-23
x86_64 allyesconfig clang-22
x86_64 buildonly-randconfig-001 clang-22
x86_64 buildonly-randconfig-001-20260630 clang-22
x86_64 buildonly-randconfig-002 clang-22
x86_64 buildonly-randconfig-002-20260630 clang-22
x86_64 buildonly-randconfig-002-20260630 gcc-14
x86_64 buildonly-randconfig-003 clang-22
x86_64 buildonly-randconfig-003-20260630 clang-22
x86_64 buildonly-randconfig-004 clang-22
x86_64 buildonly-randconfig-004-20260630 clang-22
x86_64 buildonly-randconfig-005 clang-22
x86_64 buildonly-randconfig-005-20260630 clang-22
x86_64 buildonly-randconfig-006 clang-22
x86_64 buildonly-randconfig-006-20260630 clang-22
x86_64 defconfig gcc-14
x86_64 kexec clang-22
x86_64 randconfig-001 gcc-14
x86_64 randconfig-001-20260630 gcc-14
x86_64 randconfig-002 gcc-14
x86_64 randconfig-002-20260630 gcc-14
x86_64 randconfig-003 gcc-14
x86_64 randconfig-003-20260630 gcc-14
x86_64 randconfig-004 gcc-14
x86_64 randconfig-004-20260630 gcc-14
x86_64 randconfig-005 gcc-14
x86_64 randconfig-005-20260630 gcc-14
x86_64 randconfig-006 gcc-14
x86_64 randconfig-006-20260630 gcc-14
x86_64 randconfig-011-20260630 gcc-14
x86_64 randconfig-012-20260630 gcc-14
x86_64 randconfig-013-20260630 gcc-14
x86_64 randconfig-014-20260630 gcc-14
x86_64 randconfig-015-20260630 gcc-14
x86_64 randconfig-016-20260630 gcc-14
x86_64 randconfig-071 gcc-13
x86_64 randconfig-071-20260630 clang-22
x86_64 randconfig-071-20260630 gcc-13
x86_64 randconfig-071-20260701 gcc-14
x86_64 randconfig-072 gcc-13
x86_64 randconfig-072-20260630 clang-22
x86_64 randconfig-072-20260630 gcc-13
x86_64 randconfig-072-20260701 gcc-14
x86_64 randconfig-073 gcc-13
x86_64 randconfig-073-20260630 clang-22
x86_64 randconfig-073-20260630 gcc-13
x86_64 randconfig-073-20260701 gcc-14
x86_64 randconfig-074 gcc-13
x86_64 randconfig-074-20260630 clang-22
x86_64 randconfig-074-20260630 gcc-13
x86_64 randconfig-074-20260701 gcc-14
x86_64 randconfig-075 gcc-13
x86_64 randconfig-075-20260630 clang-22
x86_64 randconfig-075-20260630 gcc-13
x86_64 randconfig-075-20260701 gcc-14
x86_64 randconfig-076 gcc-13
x86_64 randconfig-076-20260630 clang-22
x86_64 randconfig-076-20260630 gcc-13
x86_64 randconfig-076-20260701 gcc-14
x86_64 rhel-9.4 clang-22
x86_64 rhel-9.4-bpf gcc-14
x86_64 rhel-9.4-func clang-22
x86_64 rhel-9.4-kselftests clang-22
x86_64 rhel-9.4-kunit gcc-14
x86_64 rhel-9.4-ltp gcc-14
x86_64 rhel-9.4-rust clang-22
xtensa allnoconfig clang-23
xtensa allnoconfig gcc-16.1.0
xtensa allyesconfig clang-20
xtensa randconfig-001 clang-17
xtensa randconfig-001-20260630 clang-17
xtensa randconfig-002 clang-17
xtensa randconfig-002-20260630 clang-17
xtensa smp_lx200_defconfig gcc-16.1.0
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH] Input: maplemouse - set driver data before registering input device
From: Florian Fuchs @ 2026-06-30 19:15 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, Adrian McMenamin, linux-kernel
In-Reply-To: <akNXw45L_8bxD6QV@google.com>
On 29 Jun 22:47, Dmitry Torokhov wrote:
> Set maple driver data before calling input_register_device() to
> ensure that it is available if the device is opened immediately and
> the callback is triggered.
>
> Cc: stable@vger.kernel.org
> Assisted-by: Antigravity:gemini-3.5-flash
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/mouse/maplemouse.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c
> index c41182766538..0c8f7d1b02aa 100644
> --- a/drivers/input/mouse/maplemouse.c
> +++ b/drivers/input/mouse/maplemouse.c
> @@ -88,6 +88,8 @@ static int probe_maple_mouse(struct device *dev)
> mse->dev = input_dev;
> mse->mdev = mdev;
>
> + maple_set_drvdata(mdev, mse);
> +
> input_set_drvdata(input_dev, mse);
> input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
> input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
> @@ -103,12 +105,12 @@ static int probe_maple_mouse(struct device *dev)
> goto fail_register;
>
> mdev->driver = mdrv;
> - maple_set_drvdata(mdev, mse);
>
> return error;
>
> fail_register:
> input_free_device(input_dev);
> + maple_set_drvdata(mdev, NULL);
> fail_nomem:
> kfree(mse);
> fail:
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
>
> --
> Dmitry
Tested-by: Florian Fuchs <fuchsfl@gmail.com>
Regards
Florian
^ permalink raw reply
* Re: [PATCH] Input: maplecontrol - set driver data before registering input device
From: Florian Fuchs @ 2026-06-30 19:15 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Adrian McMenamin, linux-input, linux-kernel
In-Reply-To: <akNYib9hQFNN1fA9@google.com>
On 29 Jun 22:49, Dmitry Torokhov wrote:
> Set maple driver data before calling input_register_device() to
> ensure that it is available if the device is opened immediately and
> the callback is triggered.
>
> Cc: stable@vger.kernel.org
> Assisted-by: Antigravity:gemini-3.5-flash
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> ---
> drivers/input/joystick/maplecontrol.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c
> index 7f36f73844a9..6293b6e8148b 100644
> --- a/drivers/input/joystick/maplecontrol.c
> +++ b/drivers/input/joystick/maplecontrol.c
> @@ -112,6 +112,8 @@ static int probe_maple_controller(struct device *dev)
> pad->dev = idev;
> pad->mdev = mdev;
>
> + maple_set_drvdata(mdev, pad);
> +
> idev->open = dc_pad_open;
> idev->close = dc_pad_close;
>
> @@ -146,7 +148,6 @@ static int probe_maple_controller(struct device *dev)
> goto fail;
>
> mdev->driver = mdrv;
> - maple_set_drvdata(mdev, pad);
>
> return 0;
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
>
> --
> Dmitry
Tested-by: Florian Fuchs <fuchsfl@gmail.com>
Regards
Florian
^ permalink raw reply
* [PATCH] HID: hiddev: set report-init policy before device registration
From: Yousef Alhouseen @ 2026-06-30 21:18 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires
Cc: linux-usb, linux-input, linux-kernel, Yousef Alhouseen
usb_register_dev() publishes the hiddev character device before
hiddev_connect() initializes the report policy. A process that opens the
new node immediately can issue a usage ioctl while initialized is still
false and trigger usbhid_init_reports(), bypassing
HID_QUIRK_NO_INIT_REPORTS.
Set initialized before registering the character device so every opener
observes the quirk-selected policy.
Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
drivers/hid/usbhid/hiddev.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 6378801b22c6..c822e7dee8b7 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -900,6 +900,8 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
hid->hiddev = hiddev;
hiddev->hid = hid;
hiddev->exist = 1;
+ /* Honor NO_INIT_REPORTS before the character device becomes visible. */
+ hiddev->initialized = hid->quirks & HID_QUIRK_NO_INIT_REPORTS;
retval = usb_register_dev(usbhid->intf, &hiddev_class);
if (retval) {
hid_err(hid, "Not able to get a minor for this device\n");
@@ -908,12 +910,6 @@ int hiddev_connect(struct hid_device *hid, unsigned int force)
return retval;
}
- /*
- * If HID_QUIRK_NO_INIT_REPORTS is set, make sure we don't initialize
- * the reports.
- */
- hiddev->initialized = hid->quirks & HID_QUIRK_NO_INIT_REPORTS;
-
hiddev->minor = usbhid->intf->minor;
return 0;
--
2.55.0
^ permalink raw reply related
* Re: [PATCH 00/13] treewide: replace linux/gpio.h
From: Linus Walleij @ 2026-06-30 21:39 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-gpio, Arnd Bergmann, Bartosz Golaszewski, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Frank Li, Robert Jarzmik,
Krzysztof Kozlowski, Greg Ungerer, Thomas Bogendoerfer,
Hauke Mehrtens, Rafał Miłecki, Yoshinori Sato,
John Paul Adrian Glaubitz, Dmitry Torokhov, Jakub Kicinski,
Paolo Abeni, Dominik Brodowski, linux-kernel, linux-arm-kernel,
linux-samsung-soc, patches, linux-m68k, linux-mips, linux-sh,
linux-input, linux-media, netdev, linux-sunxi, linux-phy,
linux-rockchip, linux-sound
In-Reply-To: <20260629132633.1300009-1-arnd@kernel.org>
On Mon, Jun 29, 2026 at 3:26 PM Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> The linux/gpio.h header used to be the global definition for the gpio
> interfaces, with 1100 users back in linux-3.17. In linux-7.2, only about
> 130 of those remain, so this series cleans out the rest.
>
> In each subsystem, we can replace the header either with
> linux/gpio/consumer.h for users of the modern gpio descriptor interface,
> or linux/gpio/legacy.h for the few remaining users of the old number
> based interface.
>
> All patches in this series can get applied independently, so my
> preference would be for each subsystem maintainer to apply these
> directly, with the rest going into the gpio tree at some point.
>
> The final patch here obviously needs to wait for all the others
> to get merged first.
This is helpful.
The series:
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply
* Re: [PATCH 03/13] mips: replace linux/gpio.h inclusions
From: Philippe Mathieu-Daudé @ 2026-06-30 22:08 UTC (permalink / raw)
To: Arnd Bergmann, linux-gpio
Cc: Arnd Bergmann, Bartosz Golaszewski, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Frank Li, Robert Jarzmik,
Krzysztof Kozlowski, Greg Ungerer, Thomas Bogendoerfer,
Hauke Mehrtens, Rafał Miłecki, Yoshinori Sato,
John Paul Adrian Glaubitz, Linus Walleij, Dmitry Torokhov,
Jakub Kicinski, Paolo Abeni, Dominik Brodowski, linux-kernel,
linux-arm-kernel, linux-samsung-soc, patches, linux-m68k,
linux-mips, linux-sh, linux-input, linux-media, netdev,
linux-sunxi, linux-phy, linux-rockchip, linux-sound
In-Reply-To: <20260629132633.1300009-4-arnd@kernel.org>
On 29/6/26 15:26, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> linux/gpio.h should no longer be used, convert these instead to
> either linux/gpio/consumer.h or linux/gpio/legacy.h as needed.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/mips/alchemy/board-xxs1500.c | 2 +-
> arch/mips/alchemy/devboards/db1000.c | 2 +-
> arch/mips/alchemy/devboards/db1200.c | 2 +-
> arch/mips/alchemy/devboards/db1550.c | 2 +-
> arch/mips/bcm47xx/workarounds.c | 2 +-
> arch/mips/bcm63xx/boards/board_bcm963xx.c | 1 +
> arch/mips/include/asm/mach-bcm63xx/board_bcm963xx.h | 2 +-
> arch/mips/txx9/rbtx4927/setup.c | 2 +-
> 8 files changed, 8 insertions(+), 7 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 04/13] sh: replace linux/gpio.h inclusions
From: Philippe Mathieu-Daudé @ 2026-06-30 22:08 UTC (permalink / raw)
To: Arnd Bergmann, linux-gpio
Cc: Arnd Bergmann, Bartosz Golaszewski, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Frank Li, Robert Jarzmik,
Krzysztof Kozlowski, Greg Ungerer, Thomas Bogendoerfer,
Hauke Mehrtens, Rafał Miłecki, Yoshinori Sato,
John Paul Adrian Glaubitz, Linus Walleij, Dmitry Torokhov,
Jakub Kicinski, Paolo Abeni, Dominik Brodowski, linux-kernel,
linux-arm-kernel, linux-samsung-soc, patches, linux-m68k,
linux-mips, linux-sh, linux-input, linux-media, netdev,
linux-sunxi, linux-phy, linux-rockchip, linux-sound
In-Reply-To: <20260629132633.1300009-5-arnd@kernel.org>
On 29/6/26 15:26, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> linux/gpio.h should no longer be used, convert these instead to
> linux/gpio/legacy.h for the sh boards using the legacy interfaces,
> or remove it where it is not needed at all.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/sh/boards/board-magicpanelr2.c | 2 +-
> arch/sh/boards/board-sh7757lcr.c | 2 +-
> arch/sh/boards/board-urquell.c | 2 +-
> arch/sh/boards/mach-ap325rxa/setup.c | 2 +-
> arch/sh/boards/mach-ecovec24/setup.c | 2 +-
> arch/sh/boards/mach-highlander/pinmux-r7785rp.c | 2 +-
> arch/sh/boards/mach-kfr2r09/lcd_wqvga.c | 2 +-
> arch/sh/boards/mach-kfr2r09/setup.c | 2 +-
> arch/sh/boards/mach-migor/lcd_qvga.c | 2 +-
> arch/sh/boards/mach-migor/setup.c | 2 +-
> arch/sh/boards/mach-rsk/devices-rsk7203.c | 2 +-
> arch/sh/boards/mach-rsk/devices-rsk7269.c | 1 -
> arch/sh/boards/mach-se/7724/setup.c | 2 +-
> arch/sh/include/mach-common/mach/magicpanelr2.h | 2 --
> arch/sh/kernel/cpu/sh4a/setup-shx3.c | 2 +-
> 15 files changed, 13 insertions(+), 16 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 13/13] gpiolib: remove linux/gpio.h
From: Philippe Mathieu-Daudé @ 2026-06-30 22:09 UTC (permalink / raw)
To: Arnd Bergmann, linux-gpio
Cc: Arnd Bergmann, Bartosz Golaszewski, Andrew Lunn,
Sebastian Hesselbarth, Gregory Clement, Frank Li, Robert Jarzmik,
Krzysztof Kozlowski, Greg Ungerer, Thomas Bogendoerfer,
Hauke Mehrtens, Rafał Miłecki, Yoshinori Sato,
John Paul Adrian Glaubitz, Linus Walleij, Dmitry Torokhov,
Jakub Kicinski, Paolo Abeni, Dominik Brodowski, linux-kernel,
linux-arm-kernel, linux-samsung-soc, patches, linux-m68k,
linux-mips, linux-sh, linux-input, linux-media, netdev,
linux-sunxi, linux-phy, linux-rockchip, linux-sound
In-Reply-To: <20260629132633.1300009-14-arnd@kernel.org>
On 29/6/26 15:26, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> After all other drivers have converted to linux/gpio/consumer.h
> or linux/gpio/legacy.h, remove the final leftover bits here.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> MAINTAINERS | 1 -
> drivers/gpio/TODO | 4 +---
> drivers/gpio/gpiolib-cdev.c | 2 +-
> drivers/gpio/gpiolib-legacy.c | 3 +--
> drivers/gpio/gpiolib.c | 2 +-
> include/linux/gpio.h | 22 ----------------------
> 6 files changed, 4 insertions(+), 30 deletions(-)
> delete mode 100644 include/linux/gpio.h
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v4 1/3] HID: wacom: Fix Use-After-Free in wacom_intuos_pad
From: Jason Gerecke @ 2026-06-30 23:27 UTC (permalink / raw)
To: Lee Jones
Cc: Ping Cheng, Jason Gerecke, Jiri Kosina, Benjamin Tissoires,
Peter Hutterer, Dmitry Torokhov, linux-input, linux-kernel
In-Reply-To: <20260616092658.1714548-1-lee@kernel.org>
I'm still working on testing and reviewing this set as a whole, but I
can provide some immediate feedback on this first patch at least:
On Tue, Jun 16, 2026 at 2:29 AM Lee Jones <lee@kernel.org> wrote:
>
> wacom_intuos_pad() accesses wacom->shared->touch_input locklessly
> inside the interrupt handler context. If the Touch sibling device
> is disconnected, wacom_remove_shared_data() clears 'touch_input'
> outside any lock, creating a Time-of-Check to Time-of-Use (TOCTOU)
> race condition where a preempted reader in interrupt context
> dereferences the freed pointer, leading to a Use-After-Free.
>
> Resolve this by introducing RCU protection for the touch_input
> pointer:
>
> - Annotate 'touch_input' in wacom_shared struct with __rcu
> - Wrap all lockless readers in wacom_wac.c with rcu_read_lock() and
> rcu_dereference() using a unified wacom_report_touch_mute()
> helper
> - Update writers in wacom_sys.c using rcu_assign_pointer()
> - Call synchronize_rcu() in wacom_remove_shared_data() to ensure
> all active RCU readers have finished before the input device is
> freed
>
> Also wrap wacom_set_shared_values() and touch/pen assignments in
> wacom_add_shared_data() inside the wacom_udev_list_lock to serialize
> concurrent probe assignments, and verify that 'shared->touch == hdev'
> before setting touch_input to prevent concurrent sibling probe state
> desynchronization.
>
> Finally, advertise the SW_MUTE_DEVICE capability on Touch input
> devices prior to registration in wacom_setup_touch_input_capabilities()
> to prevent invalid post-registration capability modifications.
>
It seems like this patch can be split into at least two different
patches, maybe even three. The changes to
wacom_setup_touch_input_capabilities() especially feel like they could
be seperate from the introduction of RCU for shared->touch_input.
> Fixes: 961794a00eab ("Input: wacom - add reporting of SW_MUTE_DEVICE events")
> Signed-off-by: Lee Jones <lee@kernel.org>
> ---
>
> v1 -> v2: Split and use RCU as per Dmitry's review
> v2 -> v3: Sashiko fixes
> v3 -> v4: Dmitry's review [redundant check and guard()]
>
> drivers/hid/wacom_sys.c | 41 ++++++++++++++-----------
> drivers/hid/wacom_wac.c | 66 +++++++++++++++++++++--------------------
> drivers/hid/wacom_wac.h | 2 +-
> 3 files changed, 58 insertions(+), 51 deletions(-)
>
> diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
> index 2220168bf116..86895f13dbae 100644
> --- a/drivers/hid/wacom_sys.c
> +++ b/drivers/hid/wacom_sys.c
> @@ -877,10 +877,16 @@ static void wacom_remove_shared_data(void *res)
> data = container_of(wacom_wac->shared, struct wacom_hdev_data,
> shared);
>
> - if (wacom_wac->shared->touch == wacom->hdev)
> - wacom_wac->shared->touch = NULL;
> - else if (wacom_wac->shared->pen == wacom->hdev)
> - wacom_wac->shared->pen = NULL;
> + scoped_guard(mutex, &wacom_udev_list_lock) {
> + if (wacom_wac->shared->touch == wacom->hdev) {
> + wacom_wac->shared->touch = NULL;
> + rcu_assign_pointer(wacom_wac->shared->touch_input, NULL);
> + } else if (wacom_wac->shared->pen == wacom->hdev) {
> + wacom_wac->shared->pen = NULL;
> + }
> + }
> +
> + synchronize_rcu();
>
> kref_put(&data->kref, wacom_release_shared_data);
> wacom_wac->shared = NULL;
> @@ -909,6 +915,11 @@ static int wacom_add_shared_data(struct hid_device *hdev)
> list_add_tail(&data->list, &wacom_udev_list);
> }
>
> + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
> + data->shared.touch = hdev;
> + else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
> + data->shared.pen = hdev;
> +
> mutex_unlock(&wacom_udev_list_lock);
>
> wacom_wac->shared = &data->shared;
> @@ -917,11 +928,6 @@ static int wacom_add_shared_data(struct hid_device *hdev)
> if (retval)
> return retval;
>
> - if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)
> - wacom_wac->shared->touch = hdev;
> - else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN)
> - wacom_wac->shared->pen = hdev;
> -
> return retval;
> }
>
> @@ -2345,9 +2351,15 @@ static void wacom_release_resources(struct wacom *wacom)
>
> static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
> {
> + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
> +
> + guard(mutex)(&wacom_udev_list_lock);
> +
> if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) {
> - wacom_wac->shared->type = wacom_wac->features.type;
> - wacom_wac->shared->touch_input = wacom_wac->touch_input;
> + if (wacom_wac->shared->touch == wacom->hdev) {
> + wacom_wac->shared->type = wacom_wac->features.type;
> + rcu_assign_pointer(wacom_wac->shared->touch_input, wacom_wac->touch_input);
> + }
> }
>
> if (wacom_wac->has_mute_touch_switch) {
> @@ -2360,13 +2372,6 @@ static void wacom_set_shared_values(struct wacom_wac *wacom_wac)
> if (wacom_wac->is_soft_touch_switch)
> wacom_wac->shared->is_touch_on = true;
> }
> -
> - if (wacom_wac->shared->has_mute_touch_switch &&
> - wacom_wac->shared->touch_input) {
> - set_bit(EV_SW, wacom_wac->shared->touch_input->evbit);
> - input_set_capability(wacom_wac->shared->touch_input, EV_SW,
> - SW_MUTE_DEVICE);
> - }
> }
>
> static int wacom_parse_and_register(struct wacom *wacom, bool wireless)
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index da1f0ea85625..23eaa81cd827 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -510,6 +510,18 @@ static void wacom_intuos_schedule_prox_event(struct wacom_wac *wacom_wac)
> }
> }
>
> +static void wacom_report_touch_mute(struct wacom_wac *wacom_wac, bool mute)
> +{
> + struct input_dev *touch_input;
> +
> + guard(rcu)();
> + touch_input = rcu_dereference(wacom_wac->shared->touch_input);
> + if (touch_input) {
> + input_report_switch(touch_input, SW_MUTE_DEVICE, mute);
> + input_sync(touch_input);
> + }
> +}
> +
> static int wacom_intuos_pad(struct wacom_wac *wacom)
> {
> struct wacom_features *features = &wacom->features;
> @@ -650,12 +662,8 @@ static int wacom_intuos_pad(struct wacom_wac *wacom)
> input_report_key(input, KEY_CONTROLPANEL, menu);
> input_report_key(input, KEY_INFO, info);
>
> - if (wacom->shared && wacom->shared->touch_input) {
> - input_report_switch(wacom->shared->touch_input,
> - SW_MUTE_DEVICE,
> - !wacom->shared->is_touch_on);
> - input_sync(wacom->shared->touch_input);
> - }
> + if (wacom->shared)
> + wacom_report_touch_mute(wacom, !wacom->shared->is_touch_on);
>
> input_report_abs(input, ABS_RX, strip1);
> input_report_abs(input, ABS_RY, strip2);
> @@ -2153,7 +2161,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
> */
> if ((equivalent_usage == WACOM_HID_WD_MUTE_DEVICE) ||
> (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)) {
> - if (wacom_wac->shared->touch_input) {
> + if (wacom_wac->shared) {
> bool *is_touch_on = &wacom_wac->shared->is_touch_on;
>
> if (equivalent_usage == WACOM_HID_WD_MUTE_DEVICE && value)
> @@ -2161,9 +2169,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
> else if (equivalent_usage == WACOM_HID_WD_TOUCHONOFF)
> *is_touch_on = value;
>
> - input_report_switch(wacom_wac->shared->touch_input,
> - SW_MUTE_DEVICE, !(*is_touch_on));
> - input_sync(wacom_wac->shared->touch_input);
> + wacom_report_touch_mute(wacom_wac, !(*is_touch_on));
> }
> return;
> }
> @@ -3381,11 +3387,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
>
> if ((wacom->shared->type == INTUOSHT ||
> wacom->shared->type == INTUOSHT2) &&
> - wacom->shared->touch_input &&
> wacom->shared->touch_max) {
> - input_report_switch(wacom->shared->touch_input,
> - SW_MUTE_DEVICE, data[5] & 0x40);
> - input_sync(wacom->shared->touch_input);
> + wacom_report_touch_mute(wacom, data[5] & 0x40);
> }
>
> pid = get_unaligned_be16(&data[6]);
> @@ -3420,11 +3423,8 @@ static int wacom_status_irq(struct wacom_wac *wacom_wac, size_t len)
>
> if ((features->type == INTUOSHT ||
> features->type == INTUOSHT2) &&
> - wacom_wac->shared->touch_input &&
> features->touch_max) {
> - input_report_switch(wacom_wac->shared->touch_input,
> - SW_MUTE_DEVICE, data[8] & 0x40);
> - input_sync(wacom_wac->shared->touch_input);
> + wacom_report_touch_mute(wacom_wac, data[8] & 0x40);
> }
>
> if (data[9] & 0x02) { /* wireless module is attached */
> @@ -3951,11 +3951,22 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev,
> int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
> struct wacom_wac *wacom_wac)
> {
> + struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
> + struct hid_device *hdev = wacom->hdev;
> struct wacom_features *features = &wacom_wac->features;
>
> if (!(features->device_type & WACOM_DEVICETYPE_TOUCH))
> return -ENODEV;
>
> + if (features->type != TABLETPC &&
> + features->type != TABLETPC2FG &&
> + features->type != MTSCREEN &&
> + features->type != MTTPC &&
> + features->type != MTTPC_B) {
> + input_dev->evbit[0] |= BIT_MASK(EV_SW);
> + __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
> + }
> +
1. This if statement is missing a number of cases. INTUOS5, for
example (and among others) is missing and would incorrectly gain
SW_MUTE_DEVICE. The list of cases from the big switch below needs to
be consulted again.
2. It seems like this would result in SW_MUTE_DEVICE being given to
all HID_GENERIC touch devices. It should only be added in the case
that `wacom_wac->has_mute_touch_switch` is true, however.
3. I'm not sure why we're even bothering with moving all of the
initialization for SW_MUTE_DEVICE from the individual cases out to a
single awkward if statement. The only thing I can think of is that
HID_GENERIC devices need to have it set (when appropriate) now that
the responsibility has been removed from wacom_set_shared_values(). It
should be much cleaner, however, to simply add the SW_MUTE_DEVICE
setup for HID_GENERIC devices right before the function returns early
for them.
> if (features->device_type & WACOM_DEVICETYPE_DIRECT)
> __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
> else
> @@ -3992,22 +4003,17 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
> switch (features->type) {
> case INTUOSP2_BT:
> case INTUOSP2S_BT:
> - input_dev->evbit[0] |= BIT_MASK(EV_SW);
> - __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
> -
> - if (wacom_wac->shared->touch->product == 0x361) {
> + if (hdev->product == 0x361) {
> input_set_abs_params(input_dev, ABS_MT_POSITION_X,
> 0, 12440, 4, 0);
> input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
> 0, 8640, 4, 0);
> - }
> - else if (wacom_wac->shared->touch->product == 0x360) {
> + } else if (hdev->product == 0x360) {
> input_set_abs_params(input_dev, ABS_MT_POSITION_X,
> 0, 8960, 4, 0);
> input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
> 0, 5920, 4, 0);
> - }
> - else if (wacom_wac->shared->touch->product == 0x393) {
> + } else if (hdev->product == 0x393) {
> input_set_abs_params(input_dev, ABS_MT_POSITION_X,
> 0, 6400, 4, 0);
> input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
> @@ -4037,10 +4043,8 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
> fallthrough;
>
> case WACOM_27QHDT:
> - if (wacom_wac->shared->touch->product == 0x32C ||
> - wacom_wac->shared->touch->product == 0xF6) {
> - input_dev->evbit[0] |= BIT_MASK(EV_SW);
> - __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
> + if (hdev->product == 0x32C ||
> + hdev->product == 0xF6) {
> wacom_wac->has_mute_touch_switch = true;
> wacom_wac->is_soft_touch_switch = true;
> }
> @@ -4059,8 +4063,6 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev,
>
> case INTUOSHT:
> case INTUOSHT2:
> - input_dev->evbit[0] |= BIT_MASK(EV_SW);
> - __set_bit(SW_MUTE_DEVICE, input_dev->swbit);
> fallthrough;
>
> case BAMBOO_PT:
> diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
> index 126bec6e5c0c..a8bbba4a6f37 100644
> --- a/drivers/hid/wacom_wac.h
> +++ b/drivers/hid/wacom_wac.h
> @@ -285,7 +285,7 @@ struct wacom_shared {
> /* for wireless device to access USB interfaces */
> unsigned touch_max;
> int type;
> - struct input_dev *touch_input;
> + struct input_dev __rcu *touch_input;
> struct hid_device *pen;
> struct hid_device *touch;
> bool has_mute_touch_switch;
> --
> 2.54.0.1136.gdb2ca164c4-goog
>
>
^ permalink raw reply
* [PATCH v3] HID: cleanup help indentation in kconfig
From: Julian Braha @ 2026-06-30 23:34 UTC (permalink / raw)
To: jikos, bentiss; +Cc: linux-input, linux-kernel, Julian Braha
The indentation in this kconfig was all over the place:
Half of the 'help' texts were not indented, while the other
half indented by the more standard 2 spaces shown in the
kconfig documentation.
Let's standardize to 2 spaces.
Signed-off-by: Julian Braha <julianbraha@gmail.com>
---
v3: fix even more lines' indentation (sashiko, again)
Link to v2:
https://lore.kernel.org/all/20260630150134.514348-1-julianbraha@gmail.com/
v2: fix 2 more lines' indentation, thanks sashiko
Link to v1:
https://lore.kernel.org/all/20260630142043.496559-1-julianbraha@gmail.com/
drivers/hid/Kconfig | 662 ++++++++++++++++++++++----------------------
1 file changed, 331 insertions(+), 331 deletions(-)
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index f9bcaeb66385..9f72b8b5966b 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -38,77 +38,77 @@ config HID_BATTERY_STRENGTH
select POWER_SUPPLY
default n
help
- This option adds support of reporting battery strength (for HID devices
- that support this feature) through power_supply class so that userspace
- tools, such as upower, can display it.
+ This option adds support of reporting battery strength (for HID devices
+ that support this feature) through power_supply class so that userspace
+ tools, such as upower, can display it.
config HIDRAW
bool "/dev/hidraw raw HID device support"
help
- Say Y here if you want to support HID devices (from the USB
- specification standpoint) that aren't strictly user interface
- devices, like monitor controls and Uninterruptible Power Supplies.
+ Say Y here if you want to support HID devices (from the USB
+ specification standpoint) that aren't strictly user interface
+ devices, like monitor controls and Uninterruptible Power Supplies.
- This module supports these devices separately using a separate
- event interface on /dev/hidraw.
+ This module supports these devices separately using a separate
+ event interface on /dev/hidraw.
- There is also a /dev/hiddev configuration option in the USB HID
- configuration menu. In comparison to hiddev, this device does not process
- the hid events at all (no parsing, no lookups). This lets applications
- to work on raw hid events when they want to, and avoid using transport-specific
- userspace libhid/libusb libraries.
+ There is also a /dev/hiddev configuration option in the USB HID
+ configuration menu. In comparison to hiddev, this device does not process
+ the hid events at all (no parsing, no lookups). This lets applications
+ to work on raw hid events when they want to, and avoid using transport-specific
+ userspace libhid/libusb libraries.
- If unsure, say Y.
+ If unsure, say Y.
config UHID
tristate "User-space I/O driver support for HID subsystem"
default n
help
- Say Y here if you want to provide HID I/O Drivers from user-space.
- This allows to write I/O drivers in user-space and feed the data from
- the device into the kernel. The kernel parses the HID reports, loads the
- corresponding HID Device Driver or provides input devices on top of your
- user-space device.
+ Say Y here if you want to provide HID I/O Drivers from user-space.
+ This allows to write I/O drivers in user-space and feed the data from
+ the device into the kernel. The kernel parses the HID reports, loads the
+ corresponding HID Device Driver or provides input devices on top of your
+ user-space device.
- This driver cannot be used to parse HID-reports in user-space and write
- special HID-drivers. You should use hidraw for that.
- Instead, this driver allows to write the transport-layer driver in
- user-space like USB-HID and Bluetooth-HID do in kernel-space.
+ This driver cannot be used to parse HID-reports in user-space and write
+ special HID-drivers. You should use hidraw for that.
+ Instead, this driver allows to write the transport-layer driver in
+ user-space like USB-HID and Bluetooth-HID do in kernel-space.
- If unsure, say N.
+ If unsure, say N.
- To compile this driver as a module, choose M here: the
- module will be called uhid.
+ To compile this driver as a module, choose M here: the
+ module will be called uhid.
config HID_GENERIC
tristate "Generic HID driver"
default HID
help
- Support for generic devices on the HID bus. This includes most
- keyboards and mice, joysticks, tablets and digitizers.
+ Support for generic devices on the HID bus. This includes most
+ keyboards and mice, joysticks, tablets and digitizers.
- To compile this driver as a module, choose M here: the module
- will be called hid-generic.
+ To compile this driver as a module, choose M here: the module
+ will be called hid-generic.
- If unsure, say Y.
+ If unsure, say Y.
config HID_HAPTIC
bool "Haptic touchpad support"
default n
help
- Support for touchpads with force sensors and haptic actuators instead of a
- traditional button.
- Adds extra parsing and FF device for the hid multitouch driver.
- It can be used for Elan 2703 haptic touchpad.
+ Support for touchpads with force sensors and haptic actuators instead of a
+ traditional button.
+ Adds extra parsing and FF device for the hid multitouch driver.
+ It can be used for Elan 2703 haptic touchpad.
- If unsure, say N.
+ If unsure, say N.
menu "Special HID drivers"
config HID_A4TECH
tristate "A4TECH mice"
help
- Support for some A4TECH mice with two scroll wheels.
+ Support for some A4TECH mice with two scroll wheels.
config HID_ACCUTOUCH
tristate "Accutouch touch device"
@@ -118,44 +118,44 @@ config HID_ACCUTOUCH
The driver works around a problem in the reported device capabilities
which causes userspace to detect the device as a mouse rather than
- a touchscreen.
+ a touchscreen.
Say Y here if you have a Accutouch 2216 touch controller.
config HID_ACRUX
tristate "ACRUX game controller support"
help
- Say Y here if you want to enable support for ACRUX game controllers.
+ Say Y here if you want to enable support for ACRUX game controllers.
config HID_ACRUX_FF
bool "ACRUX force feedback support"
depends on HID_ACRUX
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for ACRUX
- game controllers.
+ Say Y here if you want to enable force feedback support for ACRUX
+ game controllers.
config HID_APPLE
tristate "Apple {i,Power,Mac}Books"
depends on LEDS_CLASS
depends on NEW_LEDS
help
- Support for some Apple devices which less or more break
- HID specification.
+ Support for some Apple devices which less or more break
+ HID specification.
- Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
- MacBooks, MacBook Pros and Apple Aluminum.
+ Say Y here if you want support for keyboards of Apple iBooks, PowerBooks,
+ MacBooks, MacBook Pros and Apple Aluminum.
config HID_APPLEIR
tristate "Apple infrared receiver"
depends on (USB_HID)
help
- Support for Apple infrared remote control. All the Apple computers from
+ Support for Apple infrared remote control. All the Apple computers from
2005 onwards include such a port, except the unibody Macbook (2009),
and Mac Pros. This receiver is also used in the Apple TV set-top box
prior to the 2010 model.
- Say Y here if you want support for Apple infrared remote control.
+ Say Y here if you want support for Apple infrared remote control.
config HID_APPLETB_BL
tristate "Apple Touch Bar Backlight"
@@ -191,34 +191,34 @@ config HID_ASUS
depends on ASUS_WMI || ASUS_WMI=n
select POWER_SUPPLY
help
- Support for Asus notebook built-in keyboard and touchpad via i2c, and
- the Asus Republic of Gamers laptop keyboard special keys.
+ Support for Asus notebook built-in keyboard and touchpad via i2c, and
+ the Asus Republic of Gamers laptop keyboard special keys.
- Supported devices:
- - EeeBook X205TA
- - VivoBook E200HA
- - GL553V series
- - GL753V series
+ Supported devices:
+ - EeeBook X205TA
+ - VivoBook E200HA
+ - GL553V series
+ - GL753V series
config HID_AUREAL
tristate "Aureal"
help
- Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
+ Support for Aureal Cy se W-01RN Remote Controller and other Aureal derived remotes.
config HID_BELKIN
tristate "Belkin Flip KVM and Wireless keyboard"
help
- Support for Belkin Flip KVM and Wireless keyboard.
+ Support for Belkin Flip KVM and Wireless keyboard.
config HID_BETOP_FF
tristate "Betop Production Inc. force feedback support"
depends on USB_HID
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for devices by
- BETOP Production Ltd.
- Currently the following devices are known to be supported:
- - BETOP 2185 PC & BFM MODE
+ Say Y here if you want to enable force feedback support for devices by
+ BETOP Production Ltd.
+ Currently the following devices are known to be supported:
+ - BETOP 2185 PC & BFM MODE
config HID_BIGBEN_FF
tristate "BigBen Interactive Kids' gamepad support"
@@ -235,54 +235,54 @@ config HID_BIGBEN_FF
config HID_CHERRY
tristate "Cherry Cymotion keyboard"
help
- Support for Cherry Cymotion keyboard.
+ Support for Cherry Cymotion keyboard.
config HID_CHICONY
tristate "Chicony devices"
depends on USB_HID
help
- Support for Chicony Tactical pad and special keys on Chicony keyboards.
+ Support for Chicony Tactical pad and special keys on Chicony keyboards.
config HID_CORSAIR
tristate "Corsair devices"
depends on USB_HID && LEDS_CLASS
select POWER_SUPPLY
help
- Support for Corsair devices that are not fully compliant with the
- HID standard.
- Support for Corsair Void headsets.
+ Support for Corsair devices that are not fully compliant with the
+ HID standard.
+ Support for Corsair Void headsets.
- Supported devices:
- - Vengeance K90
- - Scimitar PRO RGB
- - Corsair Void headsets
+ Supported devices:
+ - Vengeance K90
+ - Scimitar PRO RGB
+ - Corsair Void headsets
config HID_COUGAR
tristate "Cougar devices"
help
- Support for Cougar devices that are not fully compliant with the
- HID standard.
+ Support for Cougar devices that are not fully compliant with the
+ HID standard.
- Supported devices:
- - Cougar 500k Gaming Keyboard
+ Supported devices:
+ - Cougar 500k Gaming Keyboard
config HID_MACALLY
tristate "Macally devices"
help
- Support for Macally devices that are not fully compliant with the
- HID standard.
+ Support for Macally devices that are not fully compliant with the
+ HID standard.
- supported devices:
- - Macally ikey keyboard
+ supported devices:
+ - Macally ikey keyboard
config HID_PRODIKEYS
tristate "Prodikeys PC-MIDI Keyboard support"
depends on USB_HID && SND
select SND_RAWMIDI
help
- Support for Prodikeys PC-MIDI Keyboard device support.
- Say Y here to enable support for this device.
- - Prodikeys PC-MIDI keyboard.
+ Support for Prodikeys PC-MIDI Keyboard device support.
+ Say Y here to enable support for this device.
+ - Prodikeys PC-MIDI keyboard.
The Prodikeys PC-MIDI acts as a USB Audio device, with one MIDI
input and one MIDI output. These MIDI jacks appear as
a sound "card" in the ALSA sound system.
@@ -293,97 +293,97 @@ config HID_PRODIKEYS
config HID_CMEDIA
tristate "CMedia audio chips"
help
- Support for CMedia CM6533 HID audio jack controls
- and HS100B mute buttons.
+ Support for CMedia CM6533 HID audio jack controls
+ and HS100B mute buttons.
config HID_CP2112
tristate "Silicon Labs CP2112 HID USB-to-SMBus Bridge support"
depends on USB_HID && HIDRAW && I2C && GPIOLIB
select GPIOLIB_IRQCHIP
help
- Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
- This is a HID device driver which registers as an i2c adapter
- and gpiochip to expose these functions of the CP2112. The
- customizable USB descriptor fields are exposed as sysfs attributes.
+ Support for Silicon Labs CP2112 HID USB to SMBus Master Bridge.
+ This is a HID device driver which registers as an i2c adapter
+ and gpiochip to expose these functions of the CP2112. The
+ customizable USB descriptor fields are exposed as sysfs attributes.
config HID_CREATIVE_SB0540
tristate "Creative SB0540 infrared receiver"
depends on USB_HID
help
- Support for Creative infrared SB0540-compatible remote controls, such
- as the RM-1500 and RM-1800 remotes.
+ Support for Creative infrared SB0540-compatible remote controls, such
+ as the RM-1500 and RM-1800 remotes.
- Say Y here if you want support for Creative SB0540 infrared receiver.
+ Say Y here if you want support for Creative SB0540 infrared receiver.
config HID_CYPRESS
tristate "Cypress mouse and barcode readers"
help
- Support for cypress mouse and barcode readers.
+ Support for cypress mouse and barcode readers.
config HID_DRAGONRISE
tristate "DragonRise Inc. game controller"
help
- Say Y here if you have DragonRise Inc. game controllers.
- These might be branded as:
- - Tesun USB-703
- - Media-tech MT1504 "Rogue"
- - DVTech JS19 "Gear"
- - Defender Game Master
+ Say Y here if you have DragonRise Inc. game controllers.
+ These might be branded as:
+ - Tesun USB-703
+ - Media-tech MT1504 "Rogue"
+ - DVTech JS19 "Gear"
+ - Defender Game Master
config DRAGONRISE_FF
bool "DragonRise Inc. force feedback"
depends on HID_DRAGONRISE
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for DragonRise Inc.
- game controllers.
+ Say Y here if you want to enable force feedback support for DragonRise Inc.
+ game controllers.
config HID_EMS_FF
tristate "EMS Production Inc. force feedback support"
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for devices by
- EMS Production Ltd.
- Currently the following devices are known to be supported:
- - Trio Linker Plus II
+ Say Y here if you want to enable force feedback support for devices by
+ EMS Production Ltd.
+ Currently the following devices are known to be supported:
+ - Trio Linker Plus II
config HID_ELAN
tristate "ELAN USB Touchpad Support"
depends on LEDS_CLASS && USB_HID
help
- Say Y to enable support for the USB ELAN touchpad
- Currently the following devices are known to be supported:
- - HP Pavilion X2 10-p0XX.
+ Say Y to enable support for the USB ELAN touchpad
+ Currently the following devices are known to be supported:
+ - HP Pavilion X2 10-p0XX.
config HID_ELECOM
tristate "ELECOM HID devices"
help
- Support for ELECOM devices:
- - BM084 Bluetooth Mouse
- - EX-G Trackballs (M-XT3DRBK, M-XT3URBK)
- - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
- - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
- - HUGE Plus Trackball (M-HT1MRBK)
+ Support for ELECOM devices:
+ - BM084 Bluetooth Mouse
+ - EX-G Trackballs (M-XT3DRBK, M-XT3URBK)
+ - DEFT Trackballs (M-DT1DRBK, M-DT1URBK, M-DT2DRBK, M-DT2URBK)
+ - HUGE Trackballs (M-HT1DRBK, M-HT1URBK)
+ - HUGE Plus Trackball (M-HT1MRBK)
config HID_ELO
tristate "ELO USB 4000/4500 touchscreen"
depends on USB_HID
help
- Support for the ELO USB 4000/4500 touchscreens. Note that this is for
- different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO.
+ Support for the ELO USB 4000/4500 touchscreens. Note that this is for
+ different devices than those handled by CONFIG_TOUCHSCREEN_USB_ELO.
config HID_EVISION
tristate "EVision Keyboards Support"
depends on HID
help
- Support for some EVision keyboards. Note that this is needed only when
- applying customization using userspace programs.
- Support for some EVision devices requiring report descriptor fixups.
+ Support for some EVision keyboards. Note that this is needed only when
+ applying customization using userspace programs.
+ Support for some EVision devices requiring report descriptor fixups.
config HID_EZKEY
tristate "Ezkey BTC 8193 keyboard"
help
- Support for Ezkey BTC 8193 keyboard.
+ Support for Ezkey BTC 8193 keyboard.
config HID_FT260
tristate "FTDI FT260 USB HID to I2C host support"
@@ -399,12 +399,12 @@ config HID_FT260
config HID_GEMBIRD
tristate "Gembird Joypad"
help
- Support for Gembird JPD-DualForce 2.
+ Support for Gembird JPD-DualForce 2.
config HID_GFRM
tristate "Google Fiber TV Box remote control support"
help
- Support for Google Fiber TV Box remote controls
+ Support for Google Fiber TV Box remote controls
config HID_GLORIOUS
tristate "Glorious PC Gaming Race mice"
@@ -416,14 +416,14 @@ config HID_HOLTEK
tristate "Holtek HID devices"
depends on USB_HID
help
- Support for Holtek based devices:
- - Holtek On Line Grip based game controller
- - Trust GXT 18 Gaming Keyboard
- - Sharkoon Drakonia / Perixx MX-2000 gaming mice
- - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
- Zalman ZM-GM1
- - SHARKOON DarkGlider Gaming mouse
- - LEETGION Hellion Gaming Mouse
+ Support for Holtek based devices:
+ - Holtek On Line Grip based game controller
+ - Trust GXT 18 Gaming Keyboard
+ - Sharkoon Drakonia / Perixx MX-2000 gaming mice
+ - Tracer Sniper TRM-503 / NOVA Gaming Slider X200 /
+ Zalman ZM-GM1
+ - SHARKOON DarkGlider Gaming mouse
+ - LEETGION Hellion Gaming Mouse
config HOLTEK_FF
bool "Holtek On Line Grip force feedback support"
@@ -452,14 +452,14 @@ config HID_GOOGLE_HAMMER
select INPUT_VIVALDIFMAP
depends on USB_HID && LEDS_CLASS && CROS_EC
help
- Say Y here if you have a Google Hammer device.
+ Say Y here if you have a Google Hammer device.
config HID_GOOGLE_STADIA_FF
tristate "Google Stadia force feedback"
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for the Google
- Stadia controller.
+ Say Y here if you want to enable force feedback support for the Google
+ Stadia controller.
config HID_VIVALDI
tristate "Vivaldi Keyboard"
@@ -475,51 +475,51 @@ config HID_GT683R
tristate "MSI GT68xR LED support"
depends on LEDS_CLASS && USB_HID
help
- Say Y here if you want to enable support for the three MSI GT68xR LEDs
+ Say Y here if you want to enable support for the three MSI GT68xR LEDs
- This driver support following modes:
- - Normal: LEDs are fully on when enabled
- - Audio: LEDs brightness depends on sound level
- - Breathing: LEDs brightness varies at human breathing rate
+ This driver support following modes:
+ - Normal: LEDs are fully on when enabled
+ - Audio: LEDs brightness depends on sound level
+ - Breathing: LEDs brightness varies at human breathing rate
- Currently the following devices are know to be supported:
- - MSI GT683R
+ Currently the following devices are know to be supported:
+ - MSI GT683R
config HID_KEYTOUCH
tristate "Keytouch HID devices"
help
- Support for Keytouch HID devices not fully compliant with
- the specification. Currently supported:
+ Support for Keytouch HID devices not fully compliant with
+ the specification. Currently supported:
- Keytouch IEC 60945
config HID_KYE
tristate "KYE/Genius devices"
help
- Support for KYE/Genius devices not fully compliant with HID standard:
- - Ergo Mouse
- - EasyPen i405X tablet
- - MousePen i608X tablet
- - EasyPen M610X tablet
+ Support for KYE/Genius devices not fully compliant with HID standard:
+ - Ergo Mouse
+ - EasyPen i405X tablet
+ - MousePen i608X tablet
+ - EasyPen M610X tablet
config HID_KYSONA
tristate "Kysona devices"
depends on USB_HID
help
- Support for Kysona mice.
+ Support for Kysona mice.
- Say Y here if you have a Kysona M600 mouse
- and want to be able to read its battery capacity.
+ Say Y here if you have a Kysona M600 mouse
+ and want to be able to read its battery capacity.
config HID_UCLOGIC
tristate "UC-Logic"
depends on USB_HID
help
- Support for UC-Logic and Huion tablets.
+ Support for UC-Logic and Huion tablets.
config HID_WALTOP
tristate "Waltop"
help
- Support for Waltop tablets.
+ Support for Waltop tablets.
config HID_VIEWSONIC
tristate "ViewSonic/Signotec"
@@ -530,11 +530,11 @@ config HID_VRC2
tristate "VRC-2 Car Controller"
depends on HID
help
- Support for VRC-2 which is a 2-axis controller often used in
- car simulators.
+ Support for VRC-2 which is a 2-axis controller often used in
+ car simulators.
- To compile this driver as a module, choose M here: the
- module will be called hid-vrc2.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-vrc2.
config HID_XIAOMI
tristate "Xiaomi"
@@ -545,95 +545,95 @@ config HID_XIAOMI
config HID_GYRATION
tristate "Gyration remote control"
help
- Support for Gyration remote control.
+ Support for Gyration remote control.
config HID_ICADE
tristate "ION iCade arcade controller"
help
- Support for the ION iCade arcade controller to work as a joystick.
+ Support for the ION iCade arcade controller to work as a joystick.
- To compile this driver as a module, choose M here: the
- module will be called hid-icade.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-icade.
config HID_ITE
tristate "ITE devices"
help
- Support for ITE devices not fully compliant with HID standard.
+ Support for ITE devices not fully compliant with HID standard.
config HID_JABRA
tristate "Jabra USB HID Driver"
help
- Support for Jabra USB HID devices.
+ Support for Jabra USB HID devices.
- Prevents mapping of vendor defined HID usages to input events. Without
- this driver HID reports from Jabra devices may incorrectly be seen as
- mouse button events.
- Say M here if you may ever plug in a Jabra USB device.
+ Prevents mapping of vendor defined HID usages to input events. Without
+ this driver HID reports from Jabra devices may incorrectly be seen as
+ mouse button events.
+ Say M here if you may ever plug in a Jabra USB device.
config HID_TWINHAN
tristate "Twinhan IR remote control"
help
- Support for Twinhan IR remote control.
+ Support for Twinhan IR remote control.
config HID_KENSINGTON
tristate "Kensington Slimblade Trackball"
help
- Support for Kensington Slimblade Trackball.
+ Support for Kensington Slimblade Trackball.
config HID_LCPOWER
tristate "LC-Power"
help
- Support for LC-Power RC1000MCE RF remote control.
+ Support for LC-Power RC1000MCE RF remote control.
config HID_LED
tristate "Simple RGB LED support"
depends on LEDS_CLASS
help
- Support for simple RGB LED devices. Currently supported are:
- - Riso Kagaku Webmail Notifier
- - Dream Cheeky Webmail Notifier and Friends Alert
- - ThingM blink(1)
- - Delcom Visual Signal Indicator Generation 2
- - Greynut Luxafor
+ Support for simple RGB LED devices. Currently supported are:
+ - Riso Kagaku Webmail Notifier
+ - Dream Cheeky Webmail Notifier and Friends Alert
+ - ThingM blink(1)
+ - Delcom Visual Signal Indicator Generation 2
+ - Greynut Luxafor
- To compile this driver as a module, choose M here: the
- module will be called hid-led.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-led.
config HID_LENOVO
tristate "Lenovo / Thinkpad devices"
depends on LEDS_CLASS
help
- Support for IBM/Lenovo devices that are not fully compliant with HID standard.
+ Support for IBM/Lenovo devices that are not fully compliant with HID standard.
- Say Y if you want support for horizontal scrolling of the IBM/Lenovo
- Scrollpoint mice or the non-compliant features of the Lenovo Thinkpad
- standalone keyboards, e.g:
- - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
- configuration)
- - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
- - ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
+ Say Y if you want support for horizontal scrolling of the IBM/Lenovo
+ Scrollpoint mice or the non-compliant features of the Lenovo Thinkpad
+ standalone keyboards, e.g:
+ - ThinkPad USB Keyboard with TrackPoint (supports extra LEDs and trackpoint
+ configuration)
+ - ThinkPad Compact Bluetooth Keyboard with TrackPoint (supports Fn keys)
+ - ThinkPad Compact USB Keyboard with TrackPoint (supports Fn keys)
config HID_LENOVO_GO
tristate "HID Driver for Lenovo Legion Go Series Controllers"
depends on USB_HID
depends on LEDS_CLASS_MULTICOLOR
help
- Support for Lenovo Legion Go devices with detachable controllers.
+ Support for Lenovo Legion Go devices with detachable controllers.
- Say Y here to include configuration interface support for the Lenovo Legion Go
- and Legion Go 2 Handheld Console Controllers. Say M here to compile this
- driver as a module. The module will be called hid-lenovo-go.
+ Say Y here to include configuration interface support for the Lenovo Legion Go
+ and Legion Go 2 Handheld Console Controllers. Say M here to compile this
+ driver as a module. The module will be called hid-lenovo-go.
config HID_LENOVO_GO_S
tristate "HID Driver for Lenovo Legion Go S Controller"
depends on USB_HID
depends on LEDS_CLASS_MULTICOLOR
help
- Support for Lenovo Legion Go S Handheld Console Controller.
+ Support for Lenovo Legion Go S Handheld Console Controller.
- Say Y here to include configuration interface support for the Lenovo Legion Go
- S. Say M here to compile this driver as a module. The module will be called
- hid-lenovo-go-s.
+ Say Y here to include configuration interface support for the Lenovo Legion Go
+ S. Say M here to compile this driver as a module. The module will be called
+ hid-lenovo-go-s.
config HID_LETSKETCH
tristate "Letsketch WP9620N tablets"
@@ -655,7 +655,7 @@ config HID_LOGITECH
depends on LEDS_CLASS
depends on LEDS_CLASS_MULTICOLOR
help
- Support for Logitech devices that are not fully compliant with HID standard.
+ Support for Logitech devices that are not fully compliant with HID standard.
config HID_LOGITECH_DJ
tristate "Logitech receivers full support"
@@ -664,23 +664,23 @@ config HID_LOGITECH_DJ
depends on HID_LOGITECH
select HID_LOGITECH_HIDPP
help
- Say Y if you want support for Logitech receivers and devices.
- Logitech receivers are capable of pairing multiple Logitech compliant
- devices to the same receiver. Without this driver it will be handled by
- generic USB_HID driver and all incoming events will be multiplexed
- into a single mouse and a single keyboard device.
+ Say Y if you want support for Logitech receivers and devices.
+ Logitech receivers are capable of pairing multiple Logitech compliant
+ devices to the same receiver. Without this driver it will be handled by
+ generic USB_HID driver and all incoming events will be multiplexed
+ into a single mouse and a single keyboard device.
config HID_LOGITECH_HIDPP
tristate "Logitech HID++ devices support"
depends on HID_LOGITECH
select POWER_SUPPLY
help
- Support for Logitech devices relying on the HID++ Logitech specification
+ Support for Logitech devices relying on the HID++ Logitech specification
- Say Y if you want support for Logitech devices relying on the HID++
- specification. Such devices are the various Logitech Touchpads (T650,
- T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar
- Keyboard).
+ Say Y if you want support for Logitech devices relying on the HID++
+ specification. Such devices are the various Logitech Touchpads (T650,
+ T651, TK820), some mice (Zone Touch mouse), or even keyboards (Solar
+ Keyboard).
config LOGITECH_FF
bool "Logitech force feedback support"
@@ -740,31 +740,31 @@ config LOGIWHEELS_FF
config HID_MAGICMOUSE
tristate "Apple Magic Mouse/Trackpad multi-touch support"
help
- Support for the Apple Magic Mouse/Trackpad multi-touch.
+ Support for the Apple Magic Mouse/Trackpad multi-touch.
- Say Y here if you want support for the multi-touch features of the
- Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
+ Say Y here if you want support for the multi-touch features of the
+ Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
config HID_MALTRON
tristate "Maltron L90 keyboard"
help
- Adds support for the volume up, volume down, mute, and play/pause buttons
- of the Maltron L90 keyboard.
+ Adds support for the volume up, volume down, mute, and play/pause buttons
+ of the Maltron L90 keyboard.
config HID_MAYFLASH
tristate "Mayflash game controller adapter force feedback"
select INPUT_FF_MEMLESS
help
- Say Y here if you have HJZ Mayflash PS3 game controller adapters
- and want to enable force feedback support.
+ Say Y here if you have HJZ Mayflash PS3 game controller adapters
+ and want to enable force feedback support.
config HID_MEGAWORLD_FF
tristate "Mega World based game controller force feedback support"
depends on USB_HID
select INPUT_FF_MEMLESS
help
- Say Y here if you have a Mega World based game controller and want
- to have force feedback support for it.
+ Say Y here if you have a Mega World based game controller and want
+ to have force feedback support for it.
config HID_RAKK
tristate "Rakk support"
@@ -778,18 +778,18 @@ config HID_RAKK
config HID_REDRAGON
tristate "Redragon keyboards"
help
- Support for Redragon keyboards that need fix-ups to work properly.
+ Support for Redragon keyboards that need fix-ups to work properly.
config HID_MICROSOFT
tristate "Microsoft non-fully HID-compliant devices"
select INPUT_FF_MEMLESS
help
- Support for Microsoft devices that are not fully compliant with HID standard.
+ Support for Microsoft devices that are not fully compliant with HID standard.
config HID_MONTEREY
tristate "Monterey Genius KB29E keyboard"
help
- Support for Monterey Genius KB29E.
+ Support for Monterey Genius KB29E.
config HID_MULTITOUCH
tristate "HID Multitouch panels"
@@ -843,35 +843,35 @@ config HID_NINTENDO
depends on LEDS_CLASS
select POWER_SUPPLY
help
- Adds support for the Nintendo Switch Joy-Cons, NSO, Pro Controller.
- All controllers support bluetooth, and the Pro Controller also supports
- its USB mode. This also includes support for the Nintendo Switch Online
- Controllers which include the NES, Genesis, SNES, and N64 controllers.
+ Adds support for the Nintendo Switch Joy-Cons, NSO, Pro Controller.
+ All controllers support bluetooth, and the Pro Controller also supports
+ its USB mode. This also includes support for the Nintendo Switch Online
+ Controllers which include the NES, Genesis, SNES, and N64 controllers.
- To compile this driver as a module, choose M here: the
- module will be called hid-nintendo.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-nintendo.
config NINTENDO_FF
bool "Nintendo Switch controller force feedback support"
depends on HID_NINTENDO
select INPUT_FF_MEMLESS
help
- Say Y here if you have a Nintendo Switch controller and want to enable
- force feedback support for it. This works for both joy-cons, the pro
- controller, and the NSO N64 controller. For the pro controller, both
- rumble motors can be controlled individually.
+ Say Y here if you have a Nintendo Switch controller and want to enable
+ force feedback support for it. This works for both joy-cons, the pro
+ controller, and the NSO N64 controller. For the pro controller, both
+ rumble motors can be controlled individually.
config HID_NTI
tristate "NTI keyboard adapters"
help
- Support for the "extra" Sun keyboard keys on keyboards attached
- through Network Technologies USB-SUN keyboard adapters.
+ Support for the "extra" Sun keyboard keys on keyboards attached
+ through Network Technologies USB-SUN keyboard adapters.
config HID_NTRIG
tristate "N-Trig touch screen"
depends on USB_HID
help
- Support for N-Trig touch screen.
+ Support for N-Trig touch screen.
config HID_NVIDIA_SHIELD
tristate "NVIDIA SHIELD devices"
@@ -896,14 +896,14 @@ config NVIDIA_SHIELD_FF
config HID_ORTEK
tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
help
- There are certain devices which have LogicalMaximum wrong in the keyboard
- usage page of their report descriptor. The most prevailing ones so far
- are manufactured by Ortek, thus the name of the driver. Currently
- supported devices by this driver are
+ There are certain devices which have LogicalMaximum wrong in the keyboard
+ usage page of their report descriptor. The most prevailing ones so far
+ are manufactured by Ortek, thus the name of the driver. Currently
+ supported devices by this driver are
- - Ortek PKB-1700
- - Ortek WKB-2000
- - Skycable wireless presenter
+ - Ortek PKB-1700
+ - Ortek WKB-2000
+ - Skycable wireless presenter
config HID_OXP
tristate "OneXPlayer handheld controller configuration support"
@@ -946,7 +946,7 @@ config HID_PENMOUNT
config HID_PETALYNX
tristate "Petalynx Maxter remote control"
help
- Support for Petalynx Maxter remote control.
+ Support for Petalynx Maxter remote control.
config HID_PICOLCD
tristate "PicoLCD (graphic version)"
@@ -1038,77 +1038,77 @@ config PLAYSTATION_FF
PlayStation game controllers.
config HID_PXRC
- tristate "PhoenixRC HID Flight Controller"
- depends on HID
- help
- Support for PhoenixRC HID Flight Controller, a 8-axis flight controller.
+ tristate "PhoenixRC HID Flight Controller"
+ depends on HID
+ help
+ Support for PhoenixRC HID Flight Controller, a 8-axis flight controller.
- To compile this driver as a module, choose M here: the
- module will be called hid-pxrc.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-pxrc.
config HID_RAPOO
tristate "Rapoo non-fully HID-compliant devices"
help
- Support for Rapoo devices that are not fully compliant with the
- HID standard.
+ Support for Rapoo devices that are not fully compliant with the
+ HID standard.
config HID_RAZER
tristate "Razer non-fully HID-compliant devices"
help
- Support for Razer devices that are not fully compliant with the
- HID standard.
+ Support for Razer devices that are not fully compliant with the
+ HID standard.
config HID_PRIMAX
tristate "Primax non-fully HID-compliant devices"
help
- Support for Primax devices that are not fully compliant with the
- HID standard.
+ Support for Primax devices that are not fully compliant with the
+ HID standard.
config HID_RETRODE
tristate "Retrode 2 USB adapter for vintage video games"
depends on USB_HID
help
- Support for
- * Retrode 2 cartridge and controller adapter
+ Support for
+ * Retrode 2 cartridge and controller adapter
config HID_ROCCAT
tristate "Roccat device support"
depends on USB_HID
help
- Support for Roccat devices.
- Say Y here if you have a Roccat mouse or keyboard and want
- support for its special functionalities.
+ Support for Roccat devices.
+ Say Y here if you have a Roccat mouse or keyboard and want
+ support for its special functionalities.
config HID_SAITEK
tristate "Saitek (Mad Catz) non-fully HID-compliant devices"
help
- Support for Saitek devices that are not fully compliant with the
- HID standard.
+ Support for Saitek devices that are not fully compliant with the
+ HID standard.
- Supported devices:
- - PS1000 Dual Analog Pad
- - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice
- - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice
+ Supported devices:
+ - PS1000 Dual Analog Pad
+ - Saitek R.A.T.7, R.A.T.9, M.M.O.7 Gaming Mice
+ - Mad Catz R.A.T.5, R.A.T.9 Gaming Mice
config HID_SAMSUNG
tristate "Samsung InfraRed remote control or keyboards"
depends on USB_HID
help
- Support for Samsung InfraRed remote control or keyboards.
+ Support for Samsung InfraRed remote control or keyboards.
config HID_SEMITEK
tristate "Semitek USB keyboards"
help
- Support for Semitek USB keyboards that are not fully compliant
- with the HID standard.
+ Support for Semitek USB keyboards that are not fully compliant
+ with the HID standard.
- There are many variants, including:
- - GK61, GK64, GK68, GK84, GK96, etc.
- - SK61, SK64, SK68, SK84, SK96, etc.
- - Dierya DK61/DK66
- - Tronsmart TK09R
- - Woo-dy
- - X-Bows Nature/Knight
+ There are many variants, including:
+ - GK61, GK64, GK68, GK84, GK96, etc.
+ - SK61, SK64, SK68, SK84, SK96, etc.
+ - Dierya DK61/DK66
+ - Tronsmart TK09R
+ - Woo-dy
+ - X-Bows Nature/Knight
config HID_SIGMAMICRO
tristate "SiGma Micro-based keyboards"
@@ -1128,58 +1128,58 @@ config HID_SONY
select POWER_SUPPLY
select CRC32
help
- Support for
+ Support for
- * Sixaxis controllers for PS3
- * Buzz controllers
- * Blu-ray Disc Remote Control for PS3
- * Logitech Harmony adapter for PS3
- * Guitar Hero Live PS3, Wii U and PS4 guitars
- * Guitar Hero PS3 and PC guitars
- * Rock Band 1, 2 and 3 PS3 and Wii instruments
- * Rock Band 4 PS4 and PS5 guitars
- * DJ Hero Turntable for PS3
+ * Sixaxis controllers for PS3
+ * Buzz controllers
+ * Blu-ray Disc Remote Control for PS3
+ * Logitech Harmony adapter for PS3
+ * Guitar Hero Live PS3, Wii U and PS4 guitars
+ * Guitar Hero PS3 and PC guitars
+ * Rock Band 1, 2 and 3 PS3 and Wii instruments
+ * Rock Band 4 PS4 and PS5 guitars
+ * DJ Hero Turntable for PS3
config SONY_FF
bool "Sony PS2/3/4 accessories force feedback support"
depends on HID_SONY
select INPUT_FF_MEMLESS
help
- Say Y here if you have a Sony PS2/3/4 accessory and want to enable
- force feedback support for it.
+ Say Y here if you have a Sony PS2/3/4 accessory and want to enable
+ force feedback support for it.
config HID_SPEEDLINK
tristate "Speedlink VAD Cezanne mouse support"
help
- Support for Speedlink Vicious and Divine Cezanne mouse.
+ Support for Speedlink Vicious and Divine Cezanne mouse.
config HID_STEAM
tristate "Steam Controller/Deck support"
select POWER_SUPPLY
help
- Say Y here if you have a Steam Controller or Deck if you want to use it
- without running the Steam Client. It supports both the wired and
- the wireless adaptor.
+ Say Y here if you have a Steam Controller or Deck if you want to use it
+ without running the Steam Client. It supports both the wired and
+ the wireless adaptor.
config STEAM_FF
bool "Steam Deck force feedback support"
depends on HID_STEAM
select INPUT_FF_MEMLESS
help
- Say Y here if you want to enable force feedback support for the Steam
- Deck.
+ Say Y here if you want to enable force feedback support for the Steam
+ Deck.
config HID_STEELSERIES
tristate "Steelseries devices support"
depends on USB_HID
help
- Support for Steelseries SRW-S1 steering wheel, and the Steelseries
- Arctis 1 Wireless for XBox headset.
+ Support for Steelseries SRW-S1 steering wheel, and the Steelseries
+ Arctis 1 Wireless for XBox headset.
config HID_SUNPLUS
tristate "Sunplus wireless desktop"
help
- Support for Sunplus wireless desktop.
+ Support for Sunplus wireless desktop.
config HID_RMI
tristate "Synaptics RMI4 device support"
@@ -1190,9 +1190,9 @@ config HID_RMI
select RMI4_F30
select RMI4_F3A
help
- Support for Synaptics RMI4 touchpads.
- Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
- and want support for its special functionalities.
+ Support for Synaptics RMI4 touchpads.
+ Say Y here if you have a Synaptics RMI4 touchpads over i2c-hid or usbhid
+ and want support for its special functionalities.
config HID_GREENASIA
tristate "GreenAsia (Product ID 0x12) game controller support"
@@ -1205,59 +1205,59 @@ config GREENASIA_FF
depends on HID_GREENASIA
select INPUT_FF_MEMLESS
help
- Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
- (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
- and want to enable force feedback support for it.
+ Say Y here if you have a GreenAsia (Product ID 0x12) based game controller
+ (like MANTA Warrior MM816 and SpeedLink Strike2 SL-6635) or adapter
+ and want to enable force feedback support for it.
config HID_HYPERV_MOUSE
tristate "Microsoft Hyper-V mouse driver"
depends on HYPERV_VMBUS
help
- Select this option to enable the Hyper-V mouse driver.
+ Select this option to enable the Hyper-V mouse driver.
config HID_SMARTJOYPLUS
tristate "SmartJoy PLUS PS2/USB adapter support"
help
- Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
- Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
+ Support for SmartJoy PLUS PS2/USB adapter, Super Dual Box,
+ Super Joy Box 3 Pro, Super Dual Box Pro, and Super Joy Box 5 Pro.
- Note that DDR (Dance Dance Revolution) mode is not supported, nor
- is pressure sensitive buttons on the pro models.
+ Note that DDR (Dance Dance Revolution) mode is not supported, nor
+ is pressure sensitive buttons on the pro models.
config SMARTJOYPLUS_FF
bool "SmartJoy PLUS PS2/USB adapter force feedback support"
depends on HID_SMARTJOYPLUS
select INPUT_FF_MEMLESS
help
- Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
- enable force feedback support for it.
+ Say Y here if you have a SmartJoy PLUS PS2/USB adapter and want to
+ enable force feedback support for it.
config HID_TIVO
tristate "TiVo Slide Bluetooth remote control support"
help
- Say Y if you have a TiVo Slide Bluetooth remote control.
+ Say Y if you have a TiVo Slide Bluetooth remote control.
config HID_TOPSEED
tristate "TopSeed Cyberlink, BTC Emprex, Conceptronic remote control support"
help
- Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
- CLLRCMCE remote control.
+ Say Y if you have a TopSeed Cyberlink or BTC Emprex or Conceptronic
+ CLLRCMCE remote control.
config HID_TOPRE
tristate "Topre REALFORCE keyboards"
depends on HID
help
Say Y for N-key rollover support on Topre REALFORCE R2 108/87 key and
- Topre REALFORCE R3S 87 key keyboards.
+ Topre REALFORCE R3S 87 key keyboards.
config HID_THINGM
tristate "ThingM blink(1) USB RGB LED"
depends on LEDS_CLASS
select HID_LED
help
- Support for the ThingM blink(1) USB RGB LED. This driver has been
- merged into the generic hid led driver. Config symbol HID_THINGM
- just selects HID_LED and will be removed soon.
+ Support for the ThingM blink(1) USB RGB LED. This driver has been
+ merged into the generic hid led driver. Config symbol HID_THINGM
+ just selects HID_LED and will be removed soon.
config HID_THRUSTMASTER
tristate "ThrustMaster devices support"
@@ -1332,23 +1332,23 @@ config HID_WIIMOTE
select POWER_SUPPLY
select INPUT_FF_MEMLESS
help
- Support for Nintendo Wii and Wii U Bluetooth peripherals. Supported
- devices are the Wii Remote and its extension devices, but also devices
- based on the Wii Remote like the Wii U Pro Controller or the
- Wii Balance Board.
+ Support for Nintendo Wii and Wii U Bluetooth peripherals. Supported
+ devices are the Wii Remote and its extension devices, but also devices
+ based on the Wii Remote like the Wii U Pro Controller or the
+ Wii Balance Board.
- Support for all official Nintendo extensions is available, however, 3rd
- party extensions might not be supported. Please report these devices to:
+ Support for all official Nintendo extensions is available, however, 3rd
+ party extensions might not be supported. Please report these devices to:
http://github.com/dvdhrm/xwiimote/issues
- Other Nintendo Wii U peripherals that are IEEE 802.11 based (including
- the Wii U Gamepad) might be supported in the future. But currently
- support is limited to Bluetooth based devices.
+ Other Nintendo Wii U peripherals that are IEEE 802.11 based (including
+ the Wii U Gamepad) might be supported in the future. But currently
+ support is limited to Bluetooth based devices.
- If unsure, say N.
+ If unsure, say N.
- To compile this driver as a module, choose M here: the
- module will be called hid-wiimote.
+ To compile this driver as a module, choose M here: the
+ module will be called hid-wiimote.
config HID_WINWING
tristate "WinWing Orion2 throttle support"
@@ -1371,9 +1371,9 @@ config HID_WINWING
config HID_XINMO
tristate "Xin-Mo non-fully compliant devices"
help
- Support for Xin-Mo devices that are not fully compliant with the HID
- standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
- if you have a Xin-Mo Dual Arcade controller.
+ Support for Xin-Mo devices that are not fully compliant with the HID
+ standard. Currently only supports the Xin-Mo Dual Arcade. Say Y here
+ if you have a Xin-Mo Dual Arcade controller.
config HID_ZEROPLUS
tristate "Zeroplus based game controller support"
@@ -1391,7 +1391,7 @@ config ZEROPLUS_FF
config HID_ZYDACRON
tristate "Zydacron remote control support"
help
- Support for Zydacron remote control.
+ Support for Zydacron remote control.
config HID_SENSOR_HUB
tristate "HID Sensors framework support"
@@ -1425,9 +1425,9 @@ config HID_SENSOR_CUSTOM_SENSOR
config HID_ALPS
tristate "Alps HID device support"
help
- Support for Alps I2C HID touchpads and StickPointer.
- Say Y here if you have a Alps touchpads over i2c-hid or usbhid
- and want support for its special functionalities.
+ Support for Alps I2C HID touchpads and StickPointer.
+ Say Y here if you have a Alps touchpads over i2c-hid or usbhid
+ and want support for its special functionalities.
config HID_MCP2200
tristate "Microchip MCP2200 HID USB-to-GPIO bridge"
@@ -1444,11 +1444,11 @@ config HID_MCP2221
imply GPIOLIB
imply IIO
help
- Provides I2C and SMBUS host adapter functionality over USB-HID
- through MCP2221 device.
+ Provides I2C and SMBUS host adapter functionality over USB-HID
+ through MCP2221 device.
- To compile this driver as a module, choose M here: the module
- will be called hid-mcp2221.ko.
+ To compile this driver as a module, choose M here: the module
+ will be called hid-mcp2221.ko.
config HID_KUNIT_TEST
tristate "KUnit tests for HID" if !KUNIT_ALL_TESTS
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 00/13] treewide: replace linux/gpio.h
From: patchwork-bot+netdevbpf @ 2026-07-01 0:00 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-gpio, arnd, brgl, andrew, sebastian.hesselbarth,
gregory.clement, Frank.Li, robert.jarzmik, krzk, gerg, tsbogend,
hauke, zajec5, ysato, glaubitz, linusw, dmitry.torokhov, kuba,
pabeni, linux, linux-kernel, linux-arm-kernel, linux-samsung-soc,
patches, linux-m68k, linux-mips, linux-sh, linux-input,
linux-media, netdev, linux-sunxi, linux-phy, linux-rockchip,
linux-sound
In-Reply-To: <20260629132633.1300009-1-arnd@kernel.org>
Hello:
This series was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Mon, 29 Jun 2026 15:26:20 +0200 you wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> The linux/gpio.h header used to be the global definition for the gpio
> interfaces, with 1100 users back in linux-3.17. In linux-7.2, only about
> 130 of those remain, so this series cleans out the rest.
>
> In each subsystem, we can replace the header either with
> linux/gpio/consumer.h for users of the modern gpio descriptor interface,
> or linux/gpio/legacy.h for the few remaining users of the old number
> based interface.
>
> [...]
Here is the summary with links:
- [01/13] ARM: replace linux/gpio.h inclusions
(no matching commit)
- [02/13] m68k/coldfire: replace linux/gpio.h inclusions
(no matching commit)
- [03/13] mips: replace linux/gpio.h inclusions
(no matching commit)
- [04/13] sh: replace linux/gpio.h inclusions
(no matching commit)
- [05/13] mfd: replace linux/gpio.h inclusions
(no matching commit)
- [06/13,net-next] net: replace linux/gpio.h inclusions
https://git.kernel.org/netdev/net-next/c/a53d1872f2be
- [07/13] ASoC: replace linux/gpio.h inclusions
(no matching commit)
- [08/13] pcmcia: replace linux/gpio.h inclusions
(no matching commit)
- [09/13] phy: replace linux/gpio.h inclusions
(no matching commit)
- [10/13] media: replace linux/gpio.h inclusions
(no matching commit)
- [11/13] Input: matrix_keyboard - replace linux/gpio.h inclusion
(no matching commit)
- [12/13] gpib: gpio: replace linux/gpio.h inclusion
(no matching commit)
- [13/13] gpiolib: remove linux/gpio.h
(no matching commit)
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* [PATCH 0/3] HID: Intel-thc-hid: Refine error recovery flow
From: Even Xu @ 2026-07-01 2:04 UTC (permalink / raw)
To: bentiss, jikos; +Cc: srinivas.pandruvada, linux-input, linux-kernel, Even Xu
This series refines the fatal error recovery flow for the Intel THC
(Touch Host Controller) subsystem, covering both the QuickI2C and
QuickSPI drivers.
Currently, when a fatal DMA error is detected in the IRQ thread handler,
the recovery is performed inline: the interrupt handler calls
try_recover() directly, which unconfigures and reconfigures the DMA
engine.
This approach has several problems:
1. Recovery runs in the IRQ thread context, which is not ideal for
potentially slow reset operations.
2. The interrupt is re-enabled before recovery completes, risking an
interrupt storm if DMA errors persist.
3. The DMA reset logic is open-coded in each protocol driver, leading
to duplication and divergence over time.
This patch series addresses all of the above:
By adding a new thc_rxdma_reset() API to the THC core layer, QuickI2C
and QuickSPI drivers can call it respectively to refine the recovery
callback.
The synchronous try_recover() call in the IRQ thread is replaced with
schedule_work(), deferring recovery to a workqueue. Within the work
function:
- The interrupt line is disabled before any DMA manipulation.
- thc_rxdma_reset() is used instead of the open-coded sequence.
- On failure the device is marked DISABLED and the interrupt remains
off, preventing an interrupt storm.
Even Xu (3):
HID: Intel-thc-hid: Intel-thc: Add API to reset read DMA
HID: Intel-thc-hid: Intel-quicki2c: Refine recover callback
HID: Intel-thc-hid: Intel-quickspi: Refine recover callback
.../intel-quicki2c/pci-quicki2c.c | 31 +++++++---------
.../intel-quicki2c/quicki2c-dev.h | 2 +
.../intel-quickspi/pci-quickspi.c | 37 +++++++------------
.../intel-quickspi/quickspi-dev.h | 2 +
.../intel-thc-hid/intel-thc/intel-thc-dma.c | 37 +++++++++++++++++++
.../intel-thc-hid/intel-thc/intel-thc-dma.h | 1 +
6 files changed, 68 insertions(+), 42 deletions(-)
--
2.43.0
^ permalink raw reply
* [PATCH 1/3] HID: Intel-thc-hid: Intel-thc: Add API to reset read DMA
From: Even Xu @ 2026-07-01 2:04 UTC (permalink / raw)
To: bentiss, jikos; +Cc: srinivas.pandruvada, linux-input, linux-kernel, Even Xu
In-Reply-To: <20260701020432.3774514-1-even.xu@intel.com>
Add a helper function thc_rxdam_reset() to do read DMA reset, it can be
called when fatal DMA error happens.
Signed-off-by: Even Xu <even.xu@intel.com>
---
.../intel-thc-hid/intel-thc/intel-thc-dma.c | 37 +++++++++++++++++++
.../intel-thc-hid/intel-thc/intel-thc-dma.h | 1 +
2 files changed, 38 insertions(+)
diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c
index 6ee675e0a738..d771c85dff28 100644
--- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c
+++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.c
@@ -532,6 +532,43 @@ void thc_dma_unconfigure(struct thc_device *dev)
}
EXPORT_SYMBOL_NS_GPL(thc_dma_unconfigure, "INTEL_THC");
+/**
+ * thc_rxdma_reset - Reset all read DMA engines
+ *
+ * @dev: The pointer of THC private device context
+ *
+ * This is a helper function to reset RxDMA configure. It's typically used
+ * for RxDMA recovery when fatal error happens.
+ */
+int thc_rxdma_reset(struct thc_device *dev)
+{
+ int ret;
+
+ if (mutex_lock_interruptible(&dev->thc_bus_lock))
+ return -EINTR;
+
+ ret = thc_interrupt_quiesce(dev, true);
+ if (ret) {
+ dev_err_once(dev->dev, "Quiesce interrupt failed during RxDMA reset\n");
+ goto end;
+ }
+
+ thc_dma_unconfigure(dev);
+
+ ret = thc_dma_configure(dev);
+ if (ret) {
+ dev_err_once(dev->dev, "Re-config DMA failed during RxDMA reset\n");
+ goto end;
+ }
+
+ thc_interrupt_quiesce(dev, false);
+
+end:
+ mutex_unlock(&dev->thc_bus_lock);
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(thc_rxdma_reset, "INTEL_THC");
+
static int thc_wait_for_dma_pause(struct thc_device *dev, enum thc_dma_channel channel)
{
u32 ctrl_reg, sts_reg, sts;
diff --git a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h
index 541d33995baf..715423453a9d 100644
--- a/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h
+++ b/drivers/hid/intel-thc-hid/intel-thc/intel-thc-dma.h
@@ -145,6 +145,7 @@ int thc_dma_allocate(struct thc_device *dev);
int thc_dma_configure(struct thc_device *dev);
void thc_dma_unconfigure(struct thc_device *dev);
void thc_dma_release(struct thc_device *dev);
+int thc_rxdma_reset(struct thc_device *dev);
int thc_rxdma_read(struct thc_device *dev, enum thc_dma_channel dma_channel,
void *read_buff, size_t *read_len, int *read_finished);
int thc_swdma_read(struct thc_device *dev, void *write_buff, size_t write_len,
--
2.43.0
^ permalink raw reply related
* [PATCH 2/3] HID: Intel-thc-hid: Intel-quicki2c: Refine recover callback
From: Even Xu @ 2026-07-01 2:04 UTC (permalink / raw)
To: bentiss, jikos; +Cc: srinivas.pandruvada, linux-input, linux-kernel, Even Xu
In-Reply-To: <20260701020432.3774514-1-even.xu@intel.com>
Refine recover flow:
1. Use workqueue to handle recover flow instead of processing in irq
handler.
2. Call thc_rxdma_reset() API to simplify the recover operation.
3. Disable interrupt during whole recover flow.
4. If recover fails, disable interrupt to avoid interrupt storm.
Signed-off-by: Even Xu <even.xu@intel.com>
---
.../intel-quicki2c/pci-quicki2c.c | 31 ++++++++-----------
.../intel-quicki2c/quicki2c-dev.h | 2 ++
2 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
index 46d3e9a01999..411d7a0ab90e 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
@@ -245,28 +245,23 @@ static irqreturn_t quicki2c_irq_quick_handler(int irq, void *dev_id)
}
/**
- * try_recover - Try to recovery THC and Device
- * @qcdev: Pointer to quicki2c_device structure
+ * try_recover - Recover callback to recover THC
+ * @work: pointer to work_struct
*
* This function is an error handler, called when fatal error happens.
- * It try to reset touch device and re-configure THC to recovery
- * communication between touch device and THC.
- *
- * Return: 0 if successful or error code on failure
+ * It try to reset Touch Device and re-configure THC to recover
+ * transferring between Device and THC.
*/
-static int try_recover(struct quicki2c_device *qcdev)
+static void try_recover(struct work_struct *work)
{
- int ret;
+ struct quicki2c_device *qcdev = container_of(work, struct quicki2c_device, recover_work);
- thc_dma_unconfigure(qcdev->thc_hw);
-
- ret = thc_dma_configure(qcdev->thc_hw);
- if (ret) {
- dev_err(qcdev->dev, "Reconfig DMA failed\n");
- return ret;
- }
+ thc_interrupt_enable(qcdev->thc_hw, false);
- return 0;
+ if (thc_rxdma_reset(qcdev->thc_hw))
+ qcdev->state = QUICKI2C_DISABLED;
+ else
+ thc_interrupt_enable(qcdev->thc_hw, true);
}
static int handle_input_report(struct quicki2c_device *qcdev)
@@ -346,8 +341,7 @@ static irqreturn_t quicki2c_irq_thread_handler(int irq, void *dev_id)
thc_interrupt_enable(qcdev->thc_hw, true);
if (err_recover)
- if (try_recover(qcdev))
- qcdev->state = QUICKI2C_DISABLED;
+ schedule_work(&qcdev->recover_work);
pm_runtime_put_autosuspend(qcdev->dev);
@@ -386,6 +380,7 @@ static struct quicki2c_device *quicki2c_dev_init(struct pci_dev *pdev, void __io
qcdev->ddata = ddata;
init_waitqueue_head(&qcdev->reset_ack_wq);
+ INIT_WORK(&qcdev->recover_work, try_recover);
/* THC hardware init */
qcdev->thc_hw = thc_dev_init(qcdev->dev, qcdev->mem_addr);
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
index 61dbdece59a1..aedf85291e60 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
@@ -222,6 +222,8 @@ struct quicki2c_device {
wait_queue_head_t reset_ack_wq;
bool reset_ack;
+ struct work_struct recover_work;
+
u32 i2c_max_frame_size_enable;
u32 i2c_max_frame_size;
u32 i2c_int_delay_enable;
--
2.43.0
^ permalink raw reply related
* [PATCH 3/3] HID: Intel-thc-hid: Intel-quickspi: Refine recover callback
From: Even Xu @ 2026-07-01 2:04 UTC (permalink / raw)
To: bentiss, jikos; +Cc: srinivas.pandruvada, linux-input, linux-kernel, Even Xu
In-Reply-To: <20260701020432.3774514-1-even.xu@intel.com>
Refine recover flow:
1. Use workqueue to handle recover flow instead of processing in irq
handler.
2. Call thc_rxdma_reset() API to simplify the recover operation.
3. Disable interrupt during whole recover flow.
4. If recover fails, disable interrupt to avoid interrupt storm.
Signed-off-by: Even Xu <even.xu@intel.com>
---
.../intel-quickspi/pci-quickspi.c | 37 +++++++------------
.../intel-quickspi/quickspi-dev.h | 2 +
2 files changed, 15 insertions(+), 24 deletions(-)
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
index f669235f1883..1e63b183b3b1 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/pci-quickspi.c
@@ -252,34 +252,23 @@ static irqreturn_t quickspi_irq_quick_handler(int irq, void *dev_id)
}
/**
- * try_recover - Try to recovery THC and Device
- * @qsdev: pointer to quickspi device
+ * try_recover - Recover callback to recover THC
+ * @work: pointer to work_struct
*
- * This function is a error handler, called when fatal error happens.
- * It try to reset Touch Device and re-configure THC to recovery
+ * This function is an error handler, called when fatal error happens.
+ * It try to reset Touch Device and re-configure THC to recover
* transferring between Device and THC.
- *
- * Return: 0 if successful or error code on failed.
*/
-static int try_recover(struct quickspi_device *qsdev)
+static void try_recover(struct work_struct *work)
{
- int ret;
+ struct quickspi_device *qsdev = container_of(work, struct quickspi_device, recover_work);
- ret = reset_tic(qsdev);
- if (ret) {
- dev_err(qsdev->dev, "Reset touch device failed, ret = %d\n", ret);
- return ret;
- }
-
- thc_dma_unconfigure(qsdev->thc_hw);
-
- ret = thc_dma_configure(qsdev->thc_hw);
- if (ret) {
- dev_err(qsdev->dev, "Re-configure THC DMA failed, ret = %d\n", ret);
- return ret;
- }
+ thc_interrupt_enable(qsdev->thc_hw, false);
- return 0;
+ if (thc_rxdma_reset(qsdev->thc_hw))
+ qsdev->state = QUICKSPI_DISABLED;
+ else
+ thc_interrupt_enable(qsdev->thc_hw, true);
}
/**
@@ -340,8 +329,7 @@ static irqreturn_t quickspi_irq_thread_handler(int irq, void *dev_id)
thc_interrupt_enable(qsdev->thc_hw, true);
if (err_recover)
- if (try_recover(qsdev))
- qsdev->state = QUICKSPI_DISABLED;
+ schedule_work(&qsdev->recover_work);
pm_runtime_put_autosuspend(qsdev->dev);
@@ -385,6 +373,7 @@ static struct quickspi_device *quickspi_dev_init(struct pci_dev *pdev, void __io
init_waitqueue_head(&qsdev->report_desc_got_wq);
init_waitqueue_head(&qsdev->get_report_cmpl_wq);
init_waitqueue_head(&qsdev->set_report_cmpl_wq);
+ INIT_WORK(&qsdev->recover_work, try_recover);
/* thc hw init */
qsdev->thc_hw = thc_dev_init(qsdev->dev, qsdev->mem_addr);
diff --git a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
index bf5e18f5a5f4..b0c1219866a4 100644
--- a/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
+++ b/drivers/hid/intel-thc-hid/intel-quickspi/quickspi-dev.h
@@ -173,6 +173,8 @@ struct quickspi_device {
wait_queue_head_t set_report_cmpl_wq;
bool set_report_cmpl;
+
+ struct work_struct recover_work;
};
#endif /* _QUICKSPI_DEV_H_ */
--
2.43.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