.../ABI/testing/sysfs-driver-hid-srws1 | 21 - .../ABI/testing/sysfs-driver-hid-steelseries | 131 ++ drivers/hid/hid-ids.h | 33 +- drivers/hid/hid-quirks.c | 25 + drivers/hid/hid-steelseries.c | 2061 ++++++++++++++--- 5 files changed, 1925 insertions(+), 346 deletions(-) delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-srws1 create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-steelseries
This patch series adds comprehensive support for the SteelSeries Arctis
wireless gaming headset lineup to the hid-steelseries driver.
The current driver provides only basic battery monitoring for Arctis 1
and Arctis 9. This series extends support to 25+ Arctis models with
full feature control including sidetone, auto-sleep, microphone
controls, volume limiting, and Bluetooth settings.
The driver restructure uses a capability-based device info system to
cleanly handle the varying feature sets across different Arctis
generations while maintaining support for the legacy SRW-S1 racing
wheel.
Patch 1: Add 27 new device IDs to hid-ids.h
Patch 2: Add HID quirks for proper device initialization
Patch 3: Update ABI documentation for new sysfs attributes
Patch 4: Complete driver implementation with all features
Tested on Arctis Nova 7 (0x2202). All other implementation details are
based on the reverse engineering done in the HeadsetControl library
(abe3ac8).
V2:
- Fix Documentation formatting issues
Sriman Achanta (4):
HID: hid-ids: Add SteelSeries Arctis headset device IDs
HID: quirks: Add INPUT_CONFIGURED quirk for SteelSeries Arctis
headsets
Documentation: ABI: Document SteelSeries headset sysfs attributes
HID: steelseries: Add support for Arctis headset lineup
.../ABI/testing/sysfs-driver-hid-srws1 | 21 -
.../ABI/testing/sysfs-driver-hid-steelseries | 131 ++
drivers/hid/hid-ids.h | 33 +-
drivers/hid/hid-quirks.c | 25 +
drivers/hid/hid-steelseries.c | 2061 ++++++++++++++---
5 files changed, 1925 insertions(+), 346 deletions(-)
delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-srws1
create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-steelseries
--
2.52.0
Hi Sriman,
As requested, here are my patches for your v2 of the new driver.
They fix an issue where the Arctis 7 incorrectly shows 100% battery due
to submitting an invalid report. They also include some cleanups of a
couple functions.
I've tested these by loading the module in a VM, and seeing that the
Arctis 7 reads the correct battery % through the Ubuntu desktop.
If these don't fit nicely into your v3, feel free to take what you need
out of them, or, once you submit v3, I can re-do my patches and
re-submit.
Thanks!
Benjamin Wheeler (3):
HID: steelseries: Clean up hid send_report functions
HID: steelseries: Add battery request info (byte flags) to device
info.
HID: steelseries: Use device data for battery requests
drivers/hid/hid-steelseries.c | 217 +++++++++++++++++-----------------
1 file changed, 111 insertions(+), 106 deletions(-)
--
2.52.0
These functions do the same thing, so combine them into one with a
parameter.
Use helper functions to keep callsites the same.
Signed-off-by: Benjamin Wheeler <benjaminwheeler0510@gmail.com>
---
drivers/hid/hid-steelseries.c | 45 ++++++++++++++++-------------------
1 file changed, 21 insertions(+), 24 deletions(-)
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index a0046fbc830b..63b086fa6df0 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -829,9 +829,13 @@ static int steelseries_battery_register(struct steelseries_device *sd)
return 0;
}
-/* Helper function to send feature reports */
-static int steelseries_send_feature_report(struct hid_device *hdev,
- const u8 *data, size_t len)
+/**
+ * Send an hid report to the device.
+ * Supported types are output reports and feature reports.
+ */
+static int __steelseries_send_report(struct hid_device *const hdev,
+ const u8 *const data, const size_t len,
+ const enum hid_report_type type)
{
u8 *buf;
int ret;
@@ -840,8 +844,9 @@ static int steelseries_send_feature_report(struct hid_device *hdev,
if (!buf)
return -ENOMEM;
- ret = hid_hw_raw_request(hdev, data[0], buf, len, HID_FEATURE_REPORT,
+ ret = hid_hw_raw_request(hdev, data[0], buf, len, type,
HID_REQ_SET_REPORT);
+
kfree(buf);
if (ret < 0)
@@ -852,28 +857,19 @@ static int steelseries_send_feature_report(struct hid_device *hdev,
return 0;
}
-/* Helper function to send output reports */
-static int steelseries_send_output_report(struct hid_device *hdev,
- const u8 *data, size_t len)
+static inline int steelseries_send_feature_report(struct hid_device *const hdev,
+ const u8 *const data,
+ const size_t len)
{
- u8 *buf;
- int ret;
-
- buf = kmemdup(data, len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* Use raw_request with OUTPUT_REPORT type for devices without Interrupt OUT */
- ret = hid_hw_raw_request(hdev, data[0], buf, len, HID_OUTPUT_REPORT,
- HID_REQ_SET_REPORT);
- kfree(buf);
-
- if (ret < 0)
- return ret;
- if (ret < len)
- return -EIO;
+ return __steelseries_send_report(hdev, data, len, HID_FEATURE_REPORT);
+}
- return 0;
+static inline int steelseries_send_output_report(struct hid_device *const hdev,
+ const u8 *const data,
+ const size_t len)
+{
+ // NOTE: Output report (HID_OUTPUT_REPORT) is for devices without Interrupt OUT
+ return __steelseries_send_report(hdev, data, len, HID_OUTPUT_REPORT);
}
/* Sidetone level attribute */
@@ -2170,3 +2166,4 @@ MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
MODULE_AUTHOR("Simon Wood <simon@mungewell.org>");
MODULE_AUTHOR("Christian Mayer <git@mayer-bgk.de>");
MODULE_AUTHOR("Sriman Achanta <srimanachanta@gmail.com>");
+MODULE_AUTHOR("Benjamin Wheeler <benjaminwheeler0510@gmail.com>");
--
2.52.0
This way, the device info is decoupled from the functions that call it.
This will allow for simplification of calling these functions.
Signed-off-by: Benjamin Wheeler <benjaminwheeler0510@gmail.com>
---
drivers/hid/hid-steelseries.c | 79 +++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 63b086fa6df0..dabc4763f072 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -31,12 +31,22 @@
/* Legacy quirk flag for SRW-S1 */
#define STEELSERIES_SRWS1 BIT(0)
+/**
+ * Stores info about how to send a report to this device.
+ */
+struct steelseries_report_data {
+ const u8 data[2];
+ const u8 len; // Only ever 1 or 2, no need for size_t.
+ const enum hid_report_type type;
+};
+
struct steelseries_device_info {
u16 product_id;
const char *name;
u8 interface_binding_mode; /* 0 = first enumerated, 1 = specific interface(s) */
u16 valid_interfaces; /* Bitmask when mode = 1, ignored when mode = 0 */
unsigned long capabilities;
+ const struct steelseries_report_data *const report_data;
};
struct steelseries_device {
@@ -382,12 +392,55 @@ static const __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev,
return rdesc;
}
+// Report data for: arctis 1, 1x, 7p, 7x
+static const struct steelseries_report_data report_data__1_1x_7p_7x = {
+ .data = { 0x06, 0x12 },
+ .len = 2,
+ .type = HID_FEATURE_REPORT
+};
+
+// Report data for: arctis 7, 7 v2 (2019 ed.)
+static const struct steelseries_report_data report_data__7_7v2 = {
+ .data = { 0x06, 0x18 },
+ .len = 2,
+ .type = HID_OUTPUT_REPORT
+};
+
+// Report data for: 7 plus, 7 plus P, 7 plus X, 7 plus Destiny, all novas besides nova 3p, nova 3x
+static const struct steelseries_report_data report_data__7plus_nova = {
+ .data = { 0x00, 0xb0 },
+ .len = 2,
+ .type = HID_OUTPUT_REPORT
+};
+
+// Report data for: arctis 9
+static const struct steelseries_report_data report_data__9 = {
+ .data = { 0x00, 0x20 },
+ .len = 2,
+ .type = HID_FEATURE_REPORT
+};
+
+// Report data for: Pro
+static const struct steelseries_report_data report_data__pro = {
+ .data = { 0x40, 0xAA },
+ .len = 2,
+ .type = HID_OUTPUT_REPORT
+};
+
+// Report data for: Nova 3p, 3x
+static const struct steelseries_report_data report_data__nova_3p_3x = {
+ .data = { 0xb0 },
+ .len = 1,
+ .type = HID_OUTPUT_REPORT
+};
+
static const struct steelseries_device_info arctis_1_info = {
.product_id = USB_DEVICE_ID_STEELSERIES_ARCTIS_1,
.name = "Arctis 1 Wireless",
.interface_binding_mode = 1,
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__1_1x_7p_7x,
};
static const struct steelseries_device_info arctis_1_x_info = {
@@ -396,6 +449,7 @@ static const struct steelseries_device_info arctis_1_x_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__1_1x_7p_7x,
};
static const struct steelseries_device_info arctis_7_info = {
@@ -404,6 +458,7 @@ static const struct steelseries_device_info arctis_7_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(5),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__7_7v2,
};
static const struct steelseries_device_info arctis_7_p_info = {
@@ -412,6 +467,7 @@ static const struct steelseries_device_info arctis_7_p_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__1_1x_7p_7x,
};
static const struct steelseries_device_info arctis_7_x_info = {
@@ -420,6 +476,7 @@ static const struct steelseries_device_info arctis_7_x_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__1_1x_7p_7x,
};
static const struct steelseries_device_info arctis_7_gen2_info = {
@@ -428,6 +485,7 @@ static const struct steelseries_device_info arctis_7_gen2_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(5),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__7_7v2,
};
static const struct steelseries_device_info arctis_7_plus_info = {
@@ -437,6 +495,7 @@ static const struct steelseries_device_info arctis_7_plus_info = {
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_CHATMIX,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_7_plus_p_info = {
@@ -446,6 +505,7 @@ static const struct steelseries_device_info arctis_7_plus_p_info = {
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_CHATMIX,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_7_plus_x_info = {
@@ -455,6 +515,7 @@ static const struct steelseries_device_info arctis_7_plus_x_info = {
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_CHATMIX,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_7_plus_destiny_info = {
@@ -464,6 +525,7 @@ static const struct steelseries_device_info arctis_7_plus_destiny_info = {
.valid_interfaces = BIT(3),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_CHATMIX,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_9_info = {
@@ -473,6 +535,7 @@ static const struct steelseries_device_info arctis_9_info = {
.valid_interfaces = 0,
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_CHATMIX,
+ .report_data = &report_data__9,
};
static const struct steelseries_device_info arctis_pro_info = {
@@ -481,6 +544,7 @@ static const struct steelseries_device_info arctis_pro_info = {
.interface_binding_mode = 0,
.valid_interfaces = 0,
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__pro,
};
static const struct steelseries_device_info arctis_nova_3_info = {
@@ -490,6 +554,7 @@ static const struct steelseries_device_info arctis_nova_3_info = {
.valid_interfaces = BIT(4),
.capabilities = SS_CAP_SIDETONE | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_3_p_info = {
@@ -499,6 +564,7 @@ static const struct steelseries_device_info arctis_nova_3_p_info = {
.valid_interfaces = BIT(0),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_VOLUME,
+ .report_data = &report_data__nova_3p_3x,
};
static const struct steelseries_device_info arctis_nova_3_x_info = {
@@ -508,6 +574,7 @@ static const struct steelseries_device_info arctis_nova_3_x_info = {
.valid_interfaces = BIT(0),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY |
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_VOLUME,
+ .report_data = &report_data__nova_3p_3x,
};
static const struct steelseries_device_info arctis_nova_5_info = {
@@ -518,6 +585,7 @@ static const struct steelseries_device_info arctis_nova_5_info = {
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_CHATMIX |
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_5_x_info = {
@@ -528,6 +596,7 @@ static const struct steelseries_device_info arctis_nova_5_x_info = {
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_CHATMIX |
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_info = {
@@ -539,6 +608,7 @@ static const struct steelseries_device_info arctis_nova_7_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_x_info = {
@@ -550,6 +620,7 @@ static const struct steelseries_device_info arctis_nova_7_x_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_p_info = {
@@ -561,6 +632,7 @@ static const struct steelseries_device_info arctis_nova_7_p_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_x_rev2_info = {
@@ -572,6 +644,7 @@ static const struct steelseries_device_info arctis_nova_7_x_rev2_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_diablo_info = {
@@ -583,6 +656,7 @@ static const struct steelseries_device_info arctis_nova_7_diablo_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_wow_info = {
@@ -594,6 +668,7 @@ static const struct steelseries_device_info arctis_nova_7_wow_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_gen2_info = {
@@ -605,6 +680,7 @@ static const struct steelseries_device_info arctis_nova_7_gen2_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_7_x_gen2_info = {
@@ -616,6 +692,7 @@ static const struct steelseries_device_info arctis_nova_7_x_gen2_info = {
SS_CAP_INACTIVE_TIME | SS_CAP_MIC_MUTE_LED |
SS_CAP_MIC_VOLUME | SS_CAP_VOLUME_LIMITER |
SS_CAP_BT_POWER_ON | SS_CAP_BT_CALL_VOL,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_pro_info = {
@@ -624,6 +701,7 @@ static const struct steelseries_device_info arctis_nova_pro_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(4),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__7plus_nova,
};
static const struct steelseries_device_info arctis_nova_pro_x_info = {
@@ -632,6 +710,7 @@ static const struct steelseries_device_info arctis_nova_pro_x_info = {
.interface_binding_mode = 1,
.valid_interfaces = BIT(4),
.capabilities = SS_CAP_SIDETONE | SS_CAP_BATTERY | SS_CAP_INACTIVE_TIME,
+ .report_data = &report_data__7plus_nova,
};
#define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS 3000
--
2.52.0
This eliminates several functions that are no longer needed.
When making a battery request, the required data to do so is simply
pulled from the device struct.
Signed-off-by: Benjamin Wheeler <benjaminwheeler0510@gmail.com>
---
drivers/hid/hid-steelseries.c | 93 +++++------------------------------
1 file changed, 11 insertions(+), 82 deletions(-)
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index dabc4763f072..1200213bc8f3 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -809,44 +809,17 @@ static enum power_supply_property steelseries_battery_props[] = {
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
};
-/* Forward declarations for battery request functions */
-static int steelseries_arctis_1_request_battery(struct hid_device *hdev);
-static int steelseries_arctis_7_plus_request_battery(struct hid_device *hdev);
-static int steelseries_arctis_9_request_battery(struct hid_device *hdev);
-static int steelseries_arctis_nova_request_battery(struct hid_device *hdev);
-static int steelseries_arctis_nova_3p_request_battery(struct hid_device *hdev);
-static int
-steelseries_arctis_pro_wireless_request_battery(struct hid_device *hdev);
+static int __steelseries_send_report(struct hid_device *const hdev,
+ const u8 *const data, const size_t len,
+ const enum hid_report_type type);
-static int steelseries_request_battery(struct hid_device *hdev)
+static int
+steelseries_request_battery(const struct steelseries_device *const sd)
{
- u16 product = hdev->product;
-
- /* Route to device-specific battery request handler */
- if (product == USB_DEVICE_ID_STEELSERIES_ARCTIS_1 ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_1_X ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_P ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_X)
- return steelseries_arctis_1_request_battery(hdev);
-
- if (product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_PLUS ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_PLUS_P ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_PLUS_X ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_7_PLUS_DESTINY)
- return steelseries_arctis_7_plus_request_battery(hdev);
-
- if (product == USB_DEVICE_ID_STEELSERIES_ARCTIS_9)
- return steelseries_arctis_9_request_battery(hdev);
-
- if (product == USB_DEVICE_ID_STEELSERIES_ARCTIS_PRO)
- return steelseries_arctis_pro_wireless_request_battery(hdev);
-
- if (product == USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_3_P ||
- product == USB_DEVICE_ID_STEELSERIES_ARCTIS_NOVA_3_X)
- return steelseries_arctis_nova_3p_request_battery(hdev);
-
- /* All other Nova series use the same battery request */
- return steelseries_arctis_nova_request_battery(hdev);
+ const struct steelseries_report_data *const report_data =
+ sd->info->report_data; // Alias
+ return __steelseries_send_report(sd->hdev, report_data->data,
+ report_data->len, report_data->type);
}
static void steelseries_battery_timer_tick(struct work_struct *work)
@@ -854,7 +827,7 @@ static void steelseries_battery_timer_tick(struct work_struct *work)
struct steelseries_device *sd = container_of(
work, struct steelseries_device, battery_work.work);
- steelseries_request_battery(sd->hdev);
+ steelseries_request_battery(sd);
}
static int steelseries_battery_register(struct steelseries_device *sd)
@@ -895,7 +868,7 @@ static int steelseries_battery_register(struct steelseries_device *sd)
power_supply_powers(sd->battery, &sd->hdev->dev);
INIT_DELAYED_WORK(&sd->battery_work, steelseries_battery_timer_tick);
- steelseries_request_battery(sd->hdev);
+ steelseries_request_battery(sd);
/* Arctis 9 may need a retry */
if (sd->hdev->product == USB_DEVICE_ID_STEELSERIES_ARCTIS_9) {
@@ -1685,50 +1658,6 @@ static const struct attribute_group steelseries_attr_group = {
.is_visible = steelseries_attr_is_visible,
};
-static int steelseries_arctis_1_request_battery(struct hid_device *hdev)
-{
- const u8 data[] = { 0x06, 0x12 };
-
- return steelseries_send_feature_report(hdev, data, sizeof(data));
-}
-
-static int steelseries_arctis_7_plus_request_battery(struct hid_device *hdev)
-{
- const u8 data[] = { 0x00, 0xb0 };
-
- return steelseries_send_output_report(hdev, data, sizeof(data));
-}
-
-static int steelseries_arctis_9_request_battery(struct hid_device *hdev)
-{
- const u8 data[] = { 0x00, 0x20 };
-
- return steelseries_send_feature_report(hdev, data, sizeof(data));
-}
-
-static int steelseries_arctis_nova_request_battery(struct hid_device *hdev)
-{
- const u8 data[] = { 0x00, 0xb0 };
-
- return steelseries_send_output_report(hdev, data, sizeof(data));
-}
-
-static int steelseries_arctis_nova_3p_request_battery(struct hid_device *hdev)
-{
- const u8 data[] = { 0xb0 };
-
- return steelseries_send_output_report(hdev, data, sizeof(data));
-}
-
-static int
-steelseries_arctis_pro_wireless_request_battery(struct hid_device *hdev)
-{
- /* Request battery - response will arrive asynchronously via raw_event */
- const u8 data[] = { 0x40, 0xAA };
-
- return steelseries_send_output_report(hdev, data, sizeof(data));
-}
-
static int steelseries_raw_event(struct hid_device *hdev,
struct hid_report *report, u8 *data, int size)
{
--
2.52.0
Hello, I'm Benjamin, and I coincidentally have also been looking into this driver. Sriman, if you would like, I'd be happy to work together on this driver with you! In reviewing your patches, I have found and fixed a bug in my local tree regarding battery requests. The Steelseries Arctis 7 and Arctis 7 (2019 ed.) are not implemented in the battery request logic, and simply report 100% (the default value during battery registration). I discovered this bug while testing your driver with my Arctis 7 :-) Would you like me to send a formal patch for this? I also have some patches I can send that clean up the battery logic in general that make the code less complex. I am also happy to look into creating ALSA mixers/switches as well. Please let me know how I can help! Excellent work so far, and smart choice in using HeadsetControl, they've done most of the heavy lifting for us. Sincerely, Benjamin Wheeler On 1/11/26 11:19 PM, Sriman Achanta wrote: > This patch series adds comprehensive support for the SteelSeries Arctis > wireless gaming headset lineup to the hid-steelseries driver. > > The current driver provides only basic battery monitoring for Arctis 1 > and Arctis 9. This series extends support to 25+ Arctis models with > full feature control including sidetone, auto-sleep, microphone > controls, volume limiting, and Bluetooth settings. > > The driver restructure uses a capability-based device info system to > cleanly handle the varying feature sets across different Arctis > generations while maintaining support for the legacy SRW-S1 racing > wheel. > > Patch 1: Add 27 new device IDs to hid-ids.h > Patch 2: Add HID quirks for proper device initialization > Patch 3: Update ABI documentation for new sysfs attributes > Patch 4: Complete driver implementation with all features > > Tested on Arctis Nova 7 (0x2202). All other implementation details are > based on the reverse engineering done in the HeadsetControl library > (abe3ac8). > > V2: > - Fix Documentation formatting issues > > Sriman Achanta (4): > HID: hid-ids: Add SteelSeries Arctis headset device IDs > HID: quirks: Add INPUT_CONFIGURED quirk for SteelSeries Arctis > headsets > Documentation: ABI: Document SteelSeries headset sysfs attributes > HID: steelseries: Add support for Arctis headset lineup > > .../ABI/testing/sysfs-driver-hid-srws1 | 21 - > .../ABI/testing/sysfs-driver-hid-steelseries | 131 ++ > drivers/hid/hid-ids.h | 33 +- > drivers/hid/hid-quirks.c | 25 + > drivers/hid/hid-steelseries.c | 2061 ++++++++++++++--- > 5 files changed, 1925 insertions(+), 346 deletions(-) > delete mode 100644 Documentation/ABI/testing/sysfs-driver-hid-srws1 > create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-steelseries >
© 2016 - 2026 Red Hat, Inc.