linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support
@ 2025-01-12 11:44 Christian Mayer
  2025-01-12 11:44 ` [PATCH v2 1/5] HID: steelseries: preparation for adding " Christian Mayer
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

Hi,

i added support for the SteelSeries Arctis 9 headset.

Changes in v2:
* Use constants instead of magic numbers for cleaning up model name.
* Remove unnecessary whitespace changes.
* Split up preparations and actual adding suport for the device 
in separate patches.
* Call hid_hw_open/hid_hw_close for all devices
* Fix code style issues
* Optimize capacity mapping for min and max values

Christian Mayer (5):
  HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  HID: steelseries: add SteelSeries Arctis 9 support
  HID: steelseries: export charging state for the SteelSeries Arctis 9
    headset
  HID: steelseries: export model and manufacturer
  HID: steelseries: remove unnecessary return

 drivers/hid/hid-steelseries.c | 120 +++++++++++++++++++++++++++++++---
 1 file changed, 110 insertions(+), 10 deletions(-)

Christian

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/5] HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
@ 2025-01-12 11:44 ` Christian Mayer
  2025-01-12 12:02   ` Christophe JAILLET
  2025-01-12 11:44 ` [PATCH v2 2/5] HID: steelseries: add " Christian Mayer
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

Refactor code and add calls to hid_hw_open/hid_hw_closed in preparation
for adding support for the SteelSeries Arctis 9 headset.

Signed-off-by: Christian Mayer <git@mayer-bgk.de>
---
 drivers/hid/hid-steelseries.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index f9ff5be94309..dc4ab55d7c22 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -377,20 +377,21 @@ static void steelseries_srws1_remove(struct hid_device *hdev)
 #define ARCTIS_1_BATTERY_RESPONSE_LEN		8
 static const char arctis_1_battery_request[] = { 0x06, 0x12 };
 
-static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev)
+static int steelseries_headset_request_battery(struct hid_device *hdev,
+	const char *request, size_t len)
 {
 	u8 *write_buf;
 	int ret;
 
 	/* Request battery information */
-	write_buf = kmemdup(arctis_1_battery_request, sizeof(arctis_1_battery_request), GFP_KERNEL);
+	write_buf = kmemdup(request, len, GFP_KERNEL);
 	if (!write_buf)
 		return -ENOMEM;
 
-	ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0],
-				 write_buf, sizeof(arctis_1_battery_request),
+	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)sizeof(arctis_1_battery_request)) {
+	if (ret < (int)len) {
 		hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
 		ret = -ENODATA;
 	}
@@ -404,7 +405,8 @@ static void steelseries_headset_fetch_battery(struct hid_device *hdev)
 	int ret = 0;
 
 	if (sd->quirks & STEELSERIES_ARCTIS_1)
-		ret = steelseries_headset_arctis_1_fetch_battery(hdev);
+		ret = steelseries_headset_request_battery(hdev,
+			arctis_1_battery_request, sizeof(arctis_1_battery_request));
 
 	if (ret < 0)
 		hid_dbg(hdev,
@@ -554,6 +556,10 @@ static int steelseries_probe(struct hid_device *hdev, const struct hid_device_id
 	if (ret)
 		return ret;
 
+	ret = hid_hw_open(hdev);
+	if (ret)
+		return ret;
+
 	if (steelseries_headset_battery_register(sd) < 0)
 		hid_err(sd->hdev,
 			"Failed to register battery for headset\n");
@@ -580,6 +586,7 @@ static void steelseries_remove(struct hid_device *hdev)
 
 	cancel_delayed_work_sync(&sd->battery_work);
 
+	hid_hw_close(hdev);
 	hid_hw_stop(hdev);
 }
 
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/5] HID: steelseries: add SteelSeries Arctis 9 support
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
  2025-01-12 11:44 ` [PATCH v2 1/5] HID: steelseries: preparation for adding " Christian Mayer
@ 2025-01-12 11:44 ` Christian Mayer
  2025-01-13 13:42   ` Bastien Nocera
  2025-01-12 11:44 ` [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset Christian Mayer
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

Add support for the SteelSeries Arctis 9 headset. This driver
will export the battery information like it already does for
the Arcits 1 headset.

Signed-off-by: Christian Mayer <git@mayer-bgk.de>
---
 drivers/hid/hid-steelseries.c | 64 +++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index dc4ab55d7c22..2b98db7f8911 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -19,6 +19,7 @@
 
 #define STEELSERIES_SRWS1		BIT(0)
 #define STEELSERIES_ARCTIS_1		BIT(1)
+#define STEELSERIES_ARCTIS_9		BIT(2)
 
 struct steelseries_device {
 	struct hid_device *hdev;
@@ -375,7 +376,9 @@ static void steelseries_srws1_remove(struct hid_device *hdev)
 #define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS	3000
 
 #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 };
 
 static int steelseries_headset_request_battery(struct hid_device *hdev,
 	const char *request, size_t len)
@@ -395,6 +398,7 @@ static int steelseries_headset_request_battery(struct hid_device *hdev,
 		hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
 		ret = -ENODATA;
 	}
+
 	kfree(write_buf);
 	return ret;
 }
@@ -407,6 +411,9 @@ static void steelseries_headset_fetch_battery(struct hid_device *hdev)
 	if (sd->quirks & STEELSERIES_ARCTIS_1)
 		ret = steelseries_headset_request_battery(hdev,
 			arctis_1_battery_request, sizeof(arctis_1_battery_request));
+	else if (sd->quirks & STEELSERIES_ARCTIS_9)
+		ret = steelseries_headset_request_battery(hdev,
+			arctis_9_battery_request, sizeof(arctis_9_battery_request));
 
 	if (ret < 0)
 		hid_dbg(hdev,
@@ -522,9 +529,22 @@ static int steelseries_headset_battery_register(struct steelseries_device *sd)
 	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_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
 	struct steelseries_device *sd;
@@ -550,6 +570,10 @@ static int steelseries_probe(struct hid_device *hdev, const struct hid_device_id
 	if (ret)
 		return ret;
 
+	if (sd->quirks & STEELSERIES_ARCTIS_9 &&
+			!steelseries_is_vendor_usage_page(hdev, 0xc0))
+		return -ENODEV;
+
 	spin_lock_init(&sd->lock);
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
@@ -606,6 +630,15 @@ static const __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev,
 	return rdesc;
 }
 
+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_headset_raw_event(struct hid_device *hdev,
 					struct hid_report *report, u8 *read_buf,
 					int size)
@@ -637,6 +670,32 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
 		}
 	}
 
+	if (sd->quirks & 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;
+		}
+
+		if (read_buf[0] == 0xaa && read_buf[1] == 0x01) {
+			connected = true;
+
+			/*
+			 * 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;
+		}
+	}
+
 	if (connected != sd->headset_connected) {
 		hid_dbg(sd->hdev,
 			"Connected status changed from %sconnected to %sconnected\n",
@@ -672,6 +731,10 @@ static const struct hid_device_id steelseries_devices[] = {
 	  HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12b6),
 	.driver_data = STEELSERIES_ARCTIS_1 },
 
+	{ /* SteelSeries Arctis 9 Wireless for XBox */
+	  HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12c2),
+	  .driver_data = STEELSERIES_ARCTIS_9 },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, steelseries_devices);
@@ -690,3 +753,4 @@ MODULE_DESCRIPTION("HID driver for Steelseries devices");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
 MODULE_AUTHOR("Simon Wood <simon@mungewell.org>");
+MODULE_AUTHOR("Christian Mayer <git@mayer-bgk.de>");
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
  2025-01-12 11:44 ` [PATCH v2 1/5] HID: steelseries: preparation for adding " Christian Mayer
  2025-01-12 11:44 ` [PATCH v2 2/5] HID: steelseries: add " Christian Mayer
@ 2025-01-12 11:44 ` Christian Mayer
  2025-01-13 13:42   ` Bastien Nocera
  2025-01-12 11:44 ` [PATCH v2 4/5] HID: steelseries: export model and manufacturer Christian Mayer
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

The Arctis 9 headset provides the information if
the power cable is plugged in and charging via the battery report.
This information can be exported.

Signed-off-by: Christian Mayer <git@mayer-bgk.de>
---
 drivers/hid/hid-steelseries.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 2b98db7f8911..2ee1a6f01852 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -33,6 +33,7 @@ struct steelseries_device {
 	struct power_supply *battery;
 	uint8_t battery_capacity;
 	bool headset_connected;
+	bool battery_charging;
 };
 
 #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \
@@ -450,9 +451,12 @@ static int steelseries_headset_battery_get_property(struct power_supply *psy,
 		val->intval = 1;
 		break;
 	case POWER_SUPPLY_PROP_STATUS:
-		val->intval = sd->headset_connected ?
-			POWER_SUPPLY_STATUS_DISCHARGING :
-			POWER_SUPPLY_STATUS_UNKNOWN;
+		if (sd->headset_connected) {
+			val->intval = sd->battery_charging ?
+				POWER_SUPPLY_STATUS_CHARGING :
+				POWER_SUPPLY_STATUS_DISCHARGING;
+		} else
+			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
 		break;
 	case POWER_SUPPLY_PROP_SCOPE:
 		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
@@ -514,6 +518,7 @@ static int steelseries_headset_battery_register(struct steelseries_device *sd)
 	/* 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->battery = devm_power_supply_register(&sd->hdev->dev,
 			&sd->battery_desc, &battery_cfg);
@@ -646,6 +651,7 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
 	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;
 
 	/* Not a headset */
@@ -681,6 +687,7 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
 
 		if (read_buf[0] == 0xaa && read_buf[1] == 0x01) {
 			connected = true;
+			charging = read_buf[4] == 0x01;
 
 			/*
 			 * Found no official documentation about min and max.
@@ -693,6 +700,7 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
 			 * there is no known status of the device read_buf[0] == 0x55
 			 */
 			connected = false;
+			charging = false;
 		}
 	}
 
@@ -713,6 +721,15 @@ static int steelseries_headset_raw_event(struct hid_device *hdev,
 		power_supply_changed(sd->battery);
 	}
 
+	if (charging != sd->battery_charging) {
+		hid_dbg(sd->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);
+	}
+
 request_battery:
 	spin_lock_irqsave(&sd->lock, flags);
 	if (!sd->removed)
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 4/5] HID: steelseries: export model and manufacturer
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
                   ` (2 preceding siblings ...)
  2025-01-12 11:44 ` [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset Christian Mayer
@ 2025-01-12 11:44 ` Christian Mayer
  2025-01-13 13:42   ` Bastien Nocera
  2025-01-12 11:44 ` [PATCH v2 5/5] HID: steelseries: remove unnecessary return Christian Mayer
  2025-01-16 10:04 ` [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Jiri Kosina
  5 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

Export model and manufacturer with the power supply properties.
This helps identifing the device in the battery overview.
In the case of the Arctis 9 headset, the manufacturer is prefixed twice in
the device name.

Signed-off-by: Christian Mayer <git@mayer-bgk.de>
---
 drivers/hid/hid-steelseries.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 2ee1a6f01852..1a935802880a 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -439,6 +439,9 @@ static void steelseries_headset_battery_timer_tick(struct work_struct *work)
 	steelseries_headset_fetch_battery(hdev);
 }
 
+#define STEELSERIES_PREFIX "SteelSeries "
+#define STEELSERIES_PREFIX_LEN strlen(STEELSERIES_PREFIX)
+
 static int steelseries_headset_battery_get_property(struct power_supply *psy,
 				enum power_supply_property psp,
 				union power_supply_propval *val)
@@ -447,6 +450,14 @@ static int steelseries_headset_battery_get_property(struct power_supply *psy,
 	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;
+		break;
+	case POWER_SUPPLY_PROP_MANUFACTURER:
+		val->strval = "SteelSeries";
+		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = 1;
 		break;
@@ -490,6 +501,8 @@ steelseries_headset_set_wireless_status(struct hid_device *hdev,
 }
 
 static enum power_supply_property steelseries_headset_battery_props[] = {
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_MANUFACTURER,
 	POWER_SUPPLY_PROP_PRESENT,
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_SCOPE,
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 5/5] HID: steelseries: remove unnecessary return
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
                   ` (3 preceding siblings ...)
  2025-01-12 11:44 ` [PATCH v2 4/5] HID: steelseries: export model and manufacturer Christian Mayer
@ 2025-01-12 11:44 ` Christian Mayer
  2025-01-13 13:42   ` Bastien Nocera
  2025-01-16 10:04 ` [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Jiri Kosina
  5 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-12 11:44 UTC (permalink / raw)
  To: linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera,
	Christian Mayer

Remove unnecessary return in a void function.

Signed-off-by: Christian Mayer <git@mayer-bgk.de>
---
 drivers/hid/hid-steelseries.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 1a935802880a..d4bd7848b8c6 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -370,7 +370,6 @@ static void steelseries_srws1_remove(struct hid_device *hdev)
 
 	hid_hw_stop(hdev);
 	kfree(drv_data);
-	return;
 }
 #endif
 
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/5] HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  2025-01-12 11:44 ` [PATCH v2 1/5] HID: steelseries: preparation for adding " Christian Mayer
@ 2025-01-12 12:02   ` Christophe JAILLET
  2025-01-13 13:42     ` Bastien Nocera
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe JAILLET @ 2025-01-12 12:02 UTC (permalink / raw)
  To: Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires, Bastien Nocera

Le 12/01/2025 à 12:44, Christian Mayer a écrit :
> Refactor code and add calls to hid_hw_open/hid_hw_closed in preparation
> for adding support for the SteelSeries Arctis 9 headset.
> 
> Signed-off-by: Christian Mayer <git@mayer-bgk.de>
> ---
>   drivers/hid/hid-steelseries.c | 19 +++++++++++++------
>   1 file changed, 13 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
> index f9ff5be94309..dc4ab55d7c22 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -377,20 +377,21 @@ static void steelseries_srws1_remove(struct hid_device *hdev)
>   #define ARCTIS_1_BATTERY_RESPONSE_LEN		8
>   static const char arctis_1_battery_request[] = { 0x06, 0x12 };
>   
> -static int steelseries_headset_arctis_1_fetch_battery(struct hid_device *hdev)
> +static int steelseries_headset_request_battery(struct hid_device *hdev,
> +	const char *request, size_t len)
>   {
>   	u8 *write_buf;
>   	int ret;
>   
>   	/* Request battery information */
> -	write_buf = kmemdup(arctis_1_battery_request, sizeof(arctis_1_battery_request), GFP_KERNEL);
> +	write_buf = kmemdup(request, len, GFP_KERNEL);
>   	if (!write_buf)
>   		return -ENOMEM;
>   
> -	ret = hid_hw_raw_request(hdev, arctis_1_battery_request[0],
> -				 write_buf, sizeof(arctis_1_battery_request),
> +	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)sizeof(arctis_1_battery_request)) {
> +	if (ret < (int)len) {
>   		hid_err(hdev, "hid_hw_raw_request() failed with %d\n", ret);
>   		ret = -ENODATA;
>   	}
> @@ -404,7 +405,8 @@ static void steelseries_headset_fetch_battery(struct hid_device *hdev)
>   	int ret = 0;
>   
>   	if (sd->quirks & STEELSERIES_ARCTIS_1)
> -		ret = steelseries_headset_arctis_1_fetch_battery(hdev);
> +		ret = steelseries_headset_request_battery(hdev,
> +			arctis_1_battery_request, sizeof(arctis_1_battery_request));
>   
>   	if (ret < 0)
>   		hid_dbg(hdev,
> @@ -554,6 +556,10 @@ static int steelseries_probe(struct hid_device *hdev, const struct hid_device_id
>   	if (ret)
>   		return ret;
>   
> +	ret = hid_hw_open(hdev);
> +	if (ret)
> +		return ret;

Should we call hid_hw_stop() if steelseries_headset_battery_register() 
below fails, as done in the remove funcion?

> +
>   	if (steelseries_headset_battery_register(sd) < 0)
>   		hid_err(sd->hdev,
>   			"Failed to register battery for headset\n");
> @@ -580,6 +586,7 @@ static void steelseries_remove(struct hid_device *hdev)
>   
>   	cancel_delayed_work_sync(&sd->battery_work);
>   
> +	hid_hw_close(hdev);
>   	hid_hw_stop(hdev);
>   }
>   


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/5] HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  2025-01-12 12:02   ` Christophe JAILLET
@ 2025-01-13 13:42     ` Bastien Nocera
  2025-01-15 17:20       ` Christian Mayer
  0 siblings, 1 reply; 15+ messages in thread
From: Bastien Nocera @ 2025-01-13 13:42 UTC (permalink / raw)
  To: Christophe JAILLET, Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

On Sun, 2025-01-12 at 13:02 +0100, Christophe JAILLET wrote:
> Le 12/01/2025 à 12:44, Christian Mayer a écrit :
> > Refactor code and add calls to hid_hw_open/hid_hw_closed in
> > preparation
> > for adding support for the SteelSeries Arctis 9 headset.
> > 
> > Signed-off-by: Christian Mayer <git@mayer-bgk.de>

Feel free to add my:
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Tested-by: Bastien Nocera <hadess@hadess.net>

once you've made the change Christophe mentions.

> > ---
> >   drivers/hid/hid-steelseries.c | 19 +++++++++++++------
> >   1 file changed, 13 insertions(+), 6 deletions(-)
> > 
> > diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> > steelseries.c
> > index f9ff5be94309..dc4ab55d7c22 100644
> > --- a/drivers/hid/hid-steelseries.c
> > +++ b/drivers/hid/hid-steelseries.c
> > @@ -377,20 +377,21 @@ static void steelseries_srws1_remove(struct
> > hid_device *hdev)
> >   #define ARCTIS_1_BATTERY_RESPONSE_LEN		8
> >   static const char arctis_1_battery_request[] = { 0x06, 0x12 };
> >   
> > -static int steelseries_headset_arctis_1_fetch_battery(struct
> > hid_device *hdev)
> > +static int steelseries_headset_request_battery(struct hid_device
> > *hdev,
> > +	const char *request, size_t len)
> >   {
> >   	u8 *write_buf;
> >   	int ret;
> >   
> >   	/* Request battery information */
> > -	write_buf = kmemdup(arctis_1_battery_request,
> > sizeof(arctis_1_battery_request), GFP_KERNEL);
> > +	write_buf = kmemdup(request, len, GFP_KERNEL);
> >   	if (!write_buf)
> >   		return -ENOMEM;
> >   
> > -	ret = hid_hw_raw_request(hdev,
> > arctis_1_battery_request[0],
> > -				 write_buf,
> > sizeof(arctis_1_battery_request),
> > +	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)sizeof(arctis_1_battery_request)) {
> > +	if (ret < (int)len) {
> >   		hid_err(hdev, "hid_hw_raw_request() failed with
> > %d\n", ret);
> >   		ret = -ENODATA;
> >   	}
> > @@ -404,7 +405,8 @@ static void
> > steelseries_headset_fetch_battery(struct hid_device *hdev)
> >   	int ret = 0;
> >   
> >   	if (sd->quirks & STEELSERIES_ARCTIS_1)
> > -		ret =
> > steelseries_headset_arctis_1_fetch_battery(hdev);
> > +		ret = steelseries_headset_request_battery(hdev,
> > +			arctis_1_battery_request,
> > sizeof(arctis_1_battery_request));
> >   
> >   	if (ret < 0)
> >   		hid_dbg(hdev,
> > @@ -554,6 +556,10 @@ static int steelseries_probe(struct hid_device
> > *hdev, const struct hid_device_id
> >   	if (ret)
> >   		return ret;
> >   
> > +	ret = hid_hw_open(hdev);
> > +	if (ret)
> > +		return ret;
> 
> Should we call hid_hw_stop() if
> steelseries_headset_battery_register() 
> below fails, as done in the remove funcion?
> 
> > +
> >   	if (steelseries_headset_battery_register(sd) < 0)
> >   		hid_err(sd->hdev,
> >   			"Failed to register battery for
> > headset\n");
> > @@ -580,6 +586,7 @@ static void steelseries_remove(struct
> > hid_device *hdev)
> >   
> >   	cancel_delayed_work_sync(&sd->battery_work);
> >   
> > +	hid_hw_close(hdev);
> >   	hid_hw_stop(hdev);
> >   }
> >   
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 2/5] HID: steelseries: add SteelSeries Arctis 9 support
  2025-01-12 11:44 ` [PATCH v2 2/5] HID: steelseries: add " Christian Mayer
@ 2025-01-13 13:42   ` Bastien Nocera
  0 siblings, 0 replies; 15+ messages in thread
From: Bastien Nocera @ 2025-01-13 13:42 UTC (permalink / raw)
  To: Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

On Sun, 2025-01-12 at 11:44 +0000, Christian Mayer wrote:
> Add support for the SteelSeries Arctis 9 headset. This driver
> will export the battery information like it already does for
> the Arcits 1 headset.
> 
> Signed-off-by: Christian Mayer <git@mayer-bgk.de>

Feel free to add my signoffs once you've remove the one unnecessary
whitespace change.
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Tested-by: Bastien Nocera <hadess@hadess.net>

> ---
>  drivers/hid/hid-steelseries.c | 64
> +++++++++++++++++++++++++++++++++++
>  1 file changed, 64 insertions(+)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> steelseries.c
> index dc4ab55d7c22..2b98db7f8911 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -19,6 +19,7 @@
>  
>  #define STEELSERIES_SRWS1		BIT(0)
>  #define STEELSERIES_ARCTIS_1		BIT(1)
> +#define STEELSERIES_ARCTIS_9		BIT(2)
>  
>  struct steelseries_device {
>  	struct hid_device *hdev;
> @@ -375,7 +376,9 @@ static void steelseries_srws1_remove(struct
> hid_device *hdev)
>  #define STEELSERIES_HEADSET_BATTERY_TIMEOUT_MS	3000
>  
>  #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 };
>  
>  static int steelseries_headset_request_battery(struct hid_device
> *hdev,
>  	const char *request, size_t len)
> @@ -395,6 +398,7 @@ static int
> steelseries_headset_request_battery(struct hid_device *hdev,
>  		hid_err(hdev, "hid_hw_raw_request() failed with
> %d\n", ret);
>  		ret = -ENODATA;
>  	}
> +
>  	kfree(write_buf);
>  	return ret;
>  }

Whitespace change.

> @@ -407,6 +411,9 @@ static void
> steelseries_headset_fetch_battery(struct hid_device *hdev)
>  	if (sd->quirks & STEELSERIES_ARCTIS_1)
>  		ret = steelseries_headset_request_battery(hdev,
>  			arctis_1_battery_request,
> sizeof(arctis_1_battery_request));
> +	else if (sd->quirks & STEELSERIES_ARCTIS_9)
> +		ret = steelseries_headset_request_battery(hdev,
> +			arctis_9_battery_request,
> sizeof(arctis_9_battery_request));
>  
>  	if (ret < 0)
>  		hid_dbg(hdev,
> @@ -522,9 +529,22 @@ static int
> steelseries_headset_battery_register(struct steelseries_device *sd)
>  	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_probe(struct hid_device *hdev, const struct
> hid_device_id *id)
>  {
>  	struct steelseries_device *sd;
> @@ -550,6 +570,10 @@ static int steelseries_probe(struct hid_device
> *hdev, const struct hid_device_id
>  	if (ret)
>  		return ret;
>  
> +	if (sd->quirks & STEELSERIES_ARCTIS_9 &&
> +			!steelseries_is_vendor_usage_page(hdev,
> 0xc0))
> +		return -ENODEV;
> +
>  	spin_lock_init(&sd->lock);
>  
>  	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> @@ -606,6 +630,15 @@ static const __u8
> *steelseries_srws1_report_fixup(struct hid_device *hdev,
>  	return rdesc;
>  }
>  
> +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_headset_raw_event(struct hid_device *hdev,
>  					struct hid_report *report,
> u8 *read_buf,
>  					int size)
> @@ -637,6 +670,32 @@ static int steelseries_headset_raw_event(struct
> hid_device *hdev,
>  		}
>  	}
>  
> +	if (sd->quirks & 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;
> +		}
> +
> +		if (read_buf[0] == 0xaa && read_buf[1] == 0x01) {
> +			connected = true;
> +
> +			/*
> +			 * 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;
> +		}
> +	}
> +
>  	if (connected != sd->headset_connected) {
>  		hid_dbg(sd->hdev,
>  			"Connected status changed from %sconnected
> to %sconnected\n",
> @@ -672,6 +731,10 @@ static const struct hid_device_id
> steelseries_devices[] = {
>  	  HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12b6),
>  	.driver_data = STEELSERIES_ARCTIS_1 },
>  
> +	{ /* SteelSeries Arctis 9 Wireless for XBox */
> +	  HID_USB_DEVICE(USB_VENDOR_ID_STEELSERIES, 0x12c2),
> +	  .driver_data = STEELSERIES_ARCTIS_9 },
> +
>  	{ }
>  };
>  MODULE_DEVICE_TABLE(hid, steelseries_devices);
> @@ -690,3 +753,4 @@ MODULE_DESCRIPTION("HID driver for Steelseries
> devices");
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Bastien Nocera <hadess@hadess.net>");
>  MODULE_AUTHOR("Simon Wood <simon@mungewell.org>");
> +MODULE_AUTHOR("Christian Mayer <git@mayer-bgk.de>");


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset
  2025-01-12 11:44 ` [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset Christian Mayer
@ 2025-01-13 13:42   ` Bastien Nocera
  0 siblings, 0 replies; 15+ messages in thread
From: Bastien Nocera @ 2025-01-13 13:42 UTC (permalink / raw)
  To: Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

On Sun, 2025-01-12 at 11:44 +0000, Christian Mayer wrote:
> The Arctis 9 headset provides the information if
> the power cable is plugged in and charging via the battery report.
> This information can be exported.
> 
> Signed-off-by: Christian Mayer <git@mayer-bgk.de>
> ---
>  drivers/hid/hid-steelseries.c | 23 ++++++++++++++++++++---
>  1 file changed, 20 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> steelseries.c
> index 2b98db7f8911..2ee1a6f01852 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -33,6 +33,7 @@ struct steelseries_device {
>  	struct power_supply *battery;
>  	uint8_t battery_capacity;
>  	bool headset_connected;
> +	bool battery_charging;
>  };
>  
>  #if IS_BUILTIN(CONFIG_LEDS_CLASS) || \
> @@ -450,9 +451,12 @@ static int
> steelseries_headset_battery_get_property(struct power_supply *psy,
>  		val->intval = 1;
>  		break;
>  	case POWER_SUPPLY_PROP_STATUS:
> -		val->intval = sd->headset_connected ?
> -			POWER_SUPPLY_STATUS_DISCHARGING :
> -			POWER_SUPPLY_STATUS_UNKNOWN;
> +		if (sd->headset_connected) {
> +			val->intval = sd->battery_charging ?
> +				POWER_SUPPLY_STATUS_CHARGING :
> +				POWER_SUPPLY_STATUS_DISCHARGING;
> +		} else
> +			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
>  		break;
>  	case POWER_SUPPLY_PROP_SCOPE:
>  		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
> @@ -514,6 +518,7 @@ static int
> steelseries_headset_battery_register(struct steelseries_device *sd)
>  	/* 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->battery = devm_power_supply_register(&sd->hdev->dev,
>  			&sd->battery_desc, &battery_cfg);
> @@ -646,6 +651,7 @@ static int steelseries_headset_raw_event(struct
> hid_device *hdev,
>  	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;
>  
>  	/* Not a headset */
> @@ -681,6 +687,7 @@ static int steelseries_headset_raw_event(struct
> hid_device *hdev,
>  
>  		if (read_buf[0] == 0xaa && read_buf[1] == 0x01) {
>  			connected = true;
> +			charging = read_buf[4] == 0x01;

I would prefer parenthesis around that, but feel free to ignore if it's
in the kernel coding style.

Feel free to add those signoffs once that's either fixed or verified:
Reviewed-by: Bastien Nocera <hadess@hadess.net>
Tested-by: Bastien Nocera <hadess@hadess.net>

>  
>  			/*
>  			 * Found no official documentation about min
> and max.
> @@ -693,6 +700,7 @@ static int steelseries_headset_raw_event(struct
> hid_device *hdev,
>  			 * there is no known status of the device
> read_buf[0] == 0x55
>  			 */
>  			connected = false;
> +			charging = false;
>  		}
>  	}
>  
> @@ -713,6 +721,15 @@ static int steelseries_headset_raw_event(struct
> hid_device *hdev,
>  		power_supply_changed(sd->battery);
>  	}
>  
> +	if (charging != sd->battery_charging) {
> +		hid_dbg(sd->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);
> +	}
> +
>  request_battery:
>  	spin_lock_irqsave(&sd->lock, flags);
>  	if (!sd->removed)


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 4/5] HID: steelseries: export model and manufacturer
  2025-01-12 11:44 ` [PATCH v2 4/5] HID: steelseries: export model and manufacturer Christian Mayer
@ 2025-01-13 13:42   ` Bastien Nocera
  0 siblings, 0 replies; 15+ messages in thread
From: Bastien Nocera @ 2025-01-13 13:42 UTC (permalink / raw)
  To: Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

On Sun, 2025-01-12 at 11:44 +0000, Christian Mayer wrote:
> Export model and manufacturer with the power supply properties.
> This helps identifing the device in the battery overview.
> In the case of the Arctis 9 headset, the manufacturer is prefixed
> twice in
> the device name.
> 
> Signed-off-by: Christian Mayer <git@mayer-bgk.de>

Reviewed-by: Bastien Nocera <hadess@hadess.net>
Tested-by: Bastien Nocera <hadess@hadess.net>

> ---
>  drivers/hid/hid-steelseries.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> steelseries.c
> index 2ee1a6f01852..1a935802880a 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -439,6 +439,9 @@ static void
> steelseries_headset_battery_timer_tick(struct work_struct *work)
>  	steelseries_headset_fetch_battery(hdev);
>  }
>  
> +#define STEELSERIES_PREFIX "SteelSeries "
> +#define STEELSERIES_PREFIX_LEN strlen(STEELSERIES_PREFIX)
> +
>  static int steelseries_headset_battery_get_property(struct
> power_supply *psy,
>  				enum power_supply_property psp,
>  				union power_supply_propval *val)
> @@ -447,6 +450,14 @@ static int
> steelseries_headset_battery_get_property(struct power_supply *psy,
>  	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;
> +		break;
> +	case POWER_SUPPLY_PROP_MANUFACTURER:
> +		val->strval = "SteelSeries";
> +		break;
>  	case POWER_SUPPLY_PROP_PRESENT:
>  		val->intval = 1;
>  		break;
> @@ -490,6 +501,8 @@ steelseries_headset_set_wireless_status(struct
> hid_device *hdev,
>  }
>  
>  static enum power_supply_property
> steelseries_headset_battery_props[] = {
> +	POWER_SUPPLY_PROP_MODEL_NAME,
> +	POWER_SUPPLY_PROP_MANUFACTURER,
>  	POWER_SUPPLY_PROP_PRESENT,
>  	POWER_SUPPLY_PROP_STATUS,
>  	POWER_SUPPLY_PROP_SCOPE,


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 5/5] HID: steelseries: remove unnecessary return
  2025-01-12 11:44 ` [PATCH v2 5/5] HID: steelseries: remove unnecessary return Christian Mayer
@ 2025-01-13 13:42   ` Bastien Nocera
  0 siblings, 0 replies; 15+ messages in thread
From: Bastien Nocera @ 2025-01-13 13:42 UTC (permalink / raw)
  To: Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

On Sun, 2025-01-12 at 11:44 +0000, Christian Mayer wrote:
> Remove unnecessary return in a void function.
> 
> Signed-off-by: Christian Mayer <git@mayer-bgk.de>

Reviewed-by: Bastien Nocera <hadess@hadess.net>
Tested-by: Bastien Nocera <hadess@hadess.net>

> ---
>  drivers/hid/hid-steelseries.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> steelseries.c
> index 1a935802880a..d4bd7848b8c6 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -370,7 +370,6 @@ static void steelseries_srws1_remove(struct
> hid_device *hdev)
>  
>   hid_hw_stop(hdev);
>   kfree(drv_data);
> - return;
>  }
>  #endif
>  


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/5] HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  2025-01-13 13:42     ` Bastien Nocera
@ 2025-01-15 17:20       ` Christian Mayer
  2025-01-16 17:38         ` Christophe JAILLET
  0 siblings, 1 reply; 15+ messages in thread
From: Christian Mayer @ 2025-01-15 17:20 UTC (permalink / raw)
  To: Bastien Nocera, Christophe JAILLET, Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires



Am 13.01.25 um 14:42 schrieb Bastien Nocera:
> On Sun, 2025-01-12 at 13:02 +0100, Christophe JAILLET wrote:
>> Le 12/01/2025 à 12:44, Christian Mayer a écrit :
>>> Refactor code and add calls to hid_hw_open/hid_hw_closed in
>>> preparation
>>> for adding support for the SteelSeries Arctis 9 headset.
>>>
>>> Signed-off-by: Christian Mayer <git@mayer-bgk.de>
> 
> Feel free to add my:
> Reviewed-by: Bastien Nocera <hadess@hadess.net>
> Tested-by: Bastien Nocera <hadess@hadess.net>
> 
> once you've made the change Christophe mentions.
> 
>>> ---
>>>    drivers/hid/hid-steelseries.c | 19 +++++++++++++------
>>>    1 file changed, 13 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
>>> steelseries.c
>>> index f9ff5be94309..dc4ab55d7c22 100644
>>> --- a/drivers/hid/hid-steelseries.c
>>> +++ b/drivers/hid/hid-steelseries.c
>>> @@ -377,20 +377,21 @@ static void steelseries_srws1_remove(struct
>>> hid_device *hdev)
>>>    #define ARCTIS_1_BATTERY_RESPONSE_LEN		8
>>>    static const char arctis_1_battery_request[] = { 0x06, 0x12 };
>>>    
>>> -static int steelseries_headset_arctis_1_fetch_battery(struct
>>> hid_device *hdev)
>>> +static int steelseries_headset_request_battery(struct hid_device
>>> *hdev,
>>> +	const char *request, size_t len)
>>>    {
>>>    	u8 *write_buf;
>>>    	int ret;
>>>    
>>>    	/* Request battery information */
>>> -	write_buf = kmemdup(arctis_1_battery_request,
>>> sizeof(arctis_1_battery_request), GFP_KERNEL);
>>> +	write_buf = kmemdup(request, len, GFP_KERNEL);
>>>    	if (!write_buf)
>>>    		return -ENOMEM;
>>>    
>>> -	ret = hid_hw_raw_request(hdev,
>>> arctis_1_battery_request[0],
>>> -				 write_buf,
>>> sizeof(arctis_1_battery_request),
>>> +	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)sizeof(arctis_1_battery_request)) {
>>> +	if (ret < (int)len) {
>>>    		hid_err(hdev, "hid_hw_raw_request() failed with
>>> %d\n", ret);
>>>    		ret = -ENODATA;
>>>    	}
>>> @@ -404,7 +405,8 @@ static void
>>> steelseries_headset_fetch_battery(struct hid_device *hdev)
>>>    	int ret = 0;
>>>    
>>>    	if (sd->quirks & STEELSERIES_ARCTIS_1)
>>> -		ret =
>>> steelseries_headset_arctis_1_fetch_battery(hdev);
>>> +		ret = steelseries_headset_request_battery(hdev,
>>> +			arctis_1_battery_request,
>>> sizeof(arctis_1_battery_request));
>>>    
>>>    	if (ret < 0)
>>>    		hid_dbg(hdev,
>>> @@ -554,6 +556,10 @@ static int steelseries_probe(struct hid_device
>>> *hdev, const struct hid_device_id
>>>    	if (ret)
>>>    		return ret;
>>>    
>>> +	ret = hid_hw_open(hdev);
>>> +	if (ret)
>>> +		return ret;
>>
>> Should we call hid_hw_stop() if
>> steelseries_headset_battery_register()
>> below fails, as done in the remove funcion?
Did you mean hid_hw_close instead of hid_hw_stop?
If the battery_register fails, the driver will still get assigned to the 
device, because ret is not getting set and is still 0 from hid_hw_open, 
right?

hid_hw_close doesn't get called before hid_hw_stop and the remove 
function will get called when the device disconnects.
That doesn't seem right to me, or am i wrong?

>>
>>> +
>>>    	if (steelseries_headset_battery_register(sd) < 0)
>>>    		hid_err(sd->hdev,
>>>    			"Failed to register battery for
>>> headset\n");
>>> @@ -580,6 +586,7 @@ static void steelseries_remove(struct
>>> hid_device *hdev)
>>>    
>>>    	cancel_delayed_work_sync(&sd->battery_work);
>>>    
>>> +	hid_hw_close(hdev);
>>>    	hid_hw_stop(hdev);
>>>    }
>>>    
>>
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support
  2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
                   ` (4 preceding siblings ...)
  2025-01-12 11:44 ` [PATCH v2 5/5] HID: steelseries: remove unnecessary return Christian Mayer
@ 2025-01-16 10:04 ` Jiri Kosina
  5 siblings, 0 replies; 15+ messages in thread
From: Jiri Kosina @ 2025-01-16 10:04 UTC (permalink / raw)
  To: Christian Mayer
  Cc: linux-input, linux-kernel, Benjamin Tissoires, Bastien Nocera

On Sun, 12 Jan 2025, Christian Mayer wrote:

> Hi,
> 
> i added support for the SteelSeries Arctis 9 headset.
> 
> Changes in v2:
> * Use constants instead of magic numbers for cleaning up model name.
> * Remove unnecessary whitespace changes.
> * Split up preparations and actual adding suport for the device 
> in separate patches.
> * Call hid_hw_open/hid_hw_close for all devices
> * Fix code style issues
> * Optimize capacity mapping for min and max values
> 
> Christian Mayer (5):
>   HID: steelseries: preparation for adding SteelSeries Arctis 9 support
>   HID: steelseries: add SteelSeries Arctis 9 support
>   HID: steelseries: export charging state for the SteelSeries Arctis 9
>     headset
>   HID: steelseries: export model and manufacturer
>   HID: steelseries: remove unnecessary return
> 
>  drivers/hid/hid-steelseries.c | 120 +++++++++++++++++++++++++++++++---
>  1 file changed, 110 insertions(+), 10 deletions(-)

Now in hid.git#for-6.14/steelseries. Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/5] HID: steelseries: preparation for adding SteelSeries Arctis 9 support
  2025-01-15 17:20       ` Christian Mayer
@ 2025-01-16 17:38         ` Christophe JAILLET
  0 siblings, 0 replies; 15+ messages in thread
From: Christophe JAILLET @ 2025-01-16 17:38 UTC (permalink / raw)
  To: Christian Mayer, Bastien Nocera, Christian Mayer, linux-input
  Cc: linux-kernel, Jiri Kosina, Benjamin Tissoires

Le 15/01/2025 à 18:20, Christian Mayer a écrit :
> 
> 
> Am 13.01.25 um 14:42 schrieb Bastien Nocera:
>> On Sun, 2025-01-12 at 13:02 +0100, Christophe JAILLET wrote:
>>> Le 12/01/2025 à 12:44, Christian Mayer a écrit :
>>>> Refactor code and add calls to hid_hw_open/hid_hw_closed in
>>>> preparation
>>>> for adding support for the SteelSeries Arctis 9 headset.
>>>>
>>>> Signed-off-by: Christian Mayer <git@mayer-bgk.de>
>>
>> Feel free to add my:
>> Reviewed-by: Bastien Nocera <hadess@hadess.net>
>> Tested-by: Bastien Nocera <hadess@hadess.net>
>>
>> once you've made the change Christophe mentions.
>>
>>>> ---
>>>>    drivers/hid/hid-steelseries.c | 19 +++++++++++++------
>>>>    1 file changed, 13 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
>>>> steelseries.c
>>>> index f9ff5be94309..dc4ab55d7c22 100644
>>>> --- a/drivers/hid/hid-steelseries.c
>>>> +++ b/drivers/hid/hid-steelseries.c
>>>> @@ -377,20 +377,21 @@ static void steelseries_srws1_remove(struct
>>>> hid_device *hdev)
>>>>    #define ARCTIS_1_BATTERY_RESPONSE_LEN        8
>>>>    static const char arctis_1_battery_request[] = { 0x06, 0x12 };
>>>> -static int steelseries_headset_arctis_1_fetch_battery(struct
>>>> hid_device *hdev)
>>>> +static int steelseries_headset_request_battery(struct hid_device
>>>> *hdev,
>>>> +    const char *request, size_t len)
>>>>    {
>>>>        u8 *write_buf;
>>>>        int ret;
>>>>        /* Request battery information */
>>>> -    write_buf = kmemdup(arctis_1_battery_request,
>>>> sizeof(arctis_1_battery_request), GFP_KERNEL);
>>>> +    write_buf = kmemdup(request, len, GFP_KERNEL);
>>>>        if (!write_buf)
>>>>            return -ENOMEM;
>>>> -    ret = hid_hw_raw_request(hdev,
>>>> arctis_1_battery_request[0],
>>>> -                 write_buf,
>>>> sizeof(arctis_1_battery_request),
>>>> +    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)sizeof(arctis_1_battery_request)) {
>>>> +    if (ret < (int)len) {
>>>>            hid_err(hdev, "hid_hw_raw_request() failed with
>>>> %d\n", ret);
>>>>            ret = -ENODATA;
>>>>        }
>>>> @@ -404,7 +405,8 @@ static void
>>>> steelseries_headset_fetch_battery(struct hid_device *hdev)
>>>>        int ret = 0;
>>>>        if (sd->quirks & STEELSERIES_ARCTIS_1)
>>>> -        ret =
>>>> steelseries_headset_arctis_1_fetch_battery(hdev);
>>>> +        ret = steelseries_headset_request_battery(hdev,
>>>> +            arctis_1_battery_request,
>>>> sizeof(arctis_1_battery_request));
>>>>        if (ret < 0)
>>>>            hid_dbg(hdev,
>>>> @@ -554,6 +556,10 @@ static int steelseries_probe(struct hid_device
>>>> *hdev, const struct hid_device_id
>>>>        if (ret)
>>>>            return ret;
>>>> +    ret = hid_hw_open(hdev);
>>>> +    if (ret)
>>>> +        return ret;
>>>
>>> Should we call hid_hw_stop() if
>>> steelseries_headset_battery_register()
>>> below fails, as done in the remove funcion?
> Did you mean hid_hw_close instead of hid_hw_stop?

Yes, I mean hid_hw_close()

> If the battery_register fails, the driver will still get assigned to the 
> device, because ret is not getting set and is still 0 from hid_hw_open, 
> right?

Correct. I miss-read this part.
If steelseries_headset_battery_register() fails, the probe still succeeds.

> 
> hid_hw_close doesn't get called before hid_hw_stop and the remove 
> function will get called when the device disconnects.
> That doesn't seem right to me, or am i wrong?

I think you are right.

Not sure it is 100% future proof, but it looks correct.

Sorry for the noise.

CJ

> 
>>>
>>>> +
>>>>        if (steelseries_headset_battery_register(sd) < 0)
>>>>            hid_err(sd->hdev,
>>>>                "Failed to register battery for
>>>> headset\n");
>>>> @@ -580,6 +586,7 @@ static void steelseries_remove(struct
>>>> hid_device *hdev)
>>>>        cancel_delayed_work_sync(&sd->battery_work);
>>>> +    hid_hw_close(hdev);
>>>>        hid_hw_stop(hdev);
>>>>    }
>>>
>>
> 
> 
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-01-16 17:39 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-12 11:44 [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Christian Mayer
2025-01-12 11:44 ` [PATCH v2 1/5] HID: steelseries: preparation for adding " Christian Mayer
2025-01-12 12:02   ` Christophe JAILLET
2025-01-13 13:42     ` Bastien Nocera
2025-01-15 17:20       ` Christian Mayer
2025-01-16 17:38         ` Christophe JAILLET
2025-01-12 11:44 ` [PATCH v2 2/5] HID: steelseries: add " Christian Mayer
2025-01-13 13:42   ` Bastien Nocera
2025-01-12 11:44 ` [PATCH v2 3/5] HID: steelseries: export charging state for the SteelSeries Arctis 9 headset Christian Mayer
2025-01-13 13:42   ` Bastien Nocera
2025-01-12 11:44 ` [PATCH v2 4/5] HID: steelseries: export model and manufacturer Christian Mayer
2025-01-13 13:42   ` Bastien Nocera
2025-01-12 11:44 ` [PATCH v2 5/5] HID: steelseries: remove unnecessary return Christian Mayer
2025-01-13 13:42   ` Bastien Nocera
2025-01-16 10:04 ` [PATCH v2 0/5] HID: steelseries: add SteelSeries Arctis 9 support Jiri Kosina

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).