public inbox for linux-input@vger.kernel.org
 help / color / mirror / Atom feed
From: Bastien Nocera <hadess@hadess.net>
To: Sriman Achanta <srimanachanta@gmail.com>,
	Jiri Kosina <jikos@kernel.org>,
	 Benjamin Tissoires	 <bentiss@kernel.org>
Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,
	Simon Wood <simon@mungewell.org>,
	Christian Mayer <git@mayer-bgk.de>
Subject: Re: [PATCH v3 09/18] HID: steelseries: Add Bluetooth state sysfs attributes
Date: Tue, 03 Mar 2026 11:58:41 +0100	[thread overview]
Message-ID: <545b7301f828ec022937c2bc53df0ae7eab285b1.camel@hadess.net> (raw)
In-Reply-To: <20260227235042.410062-10-srimanachanta@gmail.com>

On Fri, 2026-02-27 at 18:50 -0500, Sriman Achanta wrote:
> Add read-only sysfs attributes bt_enabled and bt_device_connected
> that
> reflect the current Bluetooth radio state for headsets that support
> it.
> Attributes are registered via an attribute group with an is_visible
> callback so they only appear on capable devices.

This needs a longer explanation as to what that "Bluetooth state" is,
so folks that aren't familiar with the Steelseries products'
capabilities.

> Bluetooth state is decoded from the following HID reports:
> - Arctis Nova 7 Gen2: 0xb0 initial status packet and 0xb5 async
> events
> - Arctis Nova Pro: initial 0x06/0x14 status packet
> 
> Returns -ENODEV if the headset is not currently connected.

Do you have any ideas on how it might be used? Maybe a link to a
product page that shows the Windows or macOS software using the
feature, or another manufacturer using something similar?

Adding sysfs files like this is pretty frowned upon, so you probably
want to make sure that this is the last or close to last patch in your
patchset so maintainers can easily defer it without blocking the rest.



> 
> Signed-off-by: Sriman Achanta <srimanachanta@gmail.com>
> ---
>  drivers/hid/hid-steelseries.c | 111
> +++++++++++++++++++++++++++++++++-
>  1 file changed, 109 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-
> steelseries.c
> index 3de8e1555263..8c6116d02f19 100644
> --- a/drivers/hid/hid-steelseries.c
> +++ b/drivers/hid/hid-steelseries.c
> @@ -24,6 +24,8 @@
>  #define SS_CAP_BATTERY			BIT(0)
>  #define SS_CAP_CHATMIX			BIT(1)
>  #define SS_CAP_MIC_MUTE			BIT(2)
> +#define SS_CAP_BT_ENABLED		BIT(3)
> +#define SS_CAP_BT_DEVICE_CONNECTED	BIT(4)
>  
>  #define SS_QUIRK_STATUS_SYNC_POLL	BIT(0)
>  
> @@ -62,6 +64,9 @@ struct steelseries_device {
>  	u8 chatmix_game;
>  	bool mic_muted;
>  
> +	bool bt_enabled;
> +	bool bt_device_connected;
> +
>  	spinlock_t lock;
>  	bool removed;
>  };
> @@ -641,6 +646,20 @@ static void
> steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_devic
>  		sd->battery_charging = (data[3] == 0x01);
>  		sd->chatmix_game = data[4];
>  		sd->chatmix_chat = data[5];
> +		switch (data[6]) {
> +		case 0x00:
> +			sd->bt_enabled = false;
> +			sd->bt_device_connected = false;
> +			break;
> +		case 0x03:
> +			sd->bt_enabled = true;
> +			sd->bt_device_connected = false;
> +			break;
> +		case 0x02:
> +			sd->bt_enabled = true;
> +			sd->bt_device_connected = true;
> +			break;
> +		}
>  		sd->mic_muted = (data[9] == 0x01);
>  		break;
>  	case 0xb7:
> @@ -659,6 +678,15 @@ static void
> steelseries_arctis_nova_7_gen2_parse_status(struct steelseries_devic
>  	case 0x52:
>  		sd->mic_muted = (data[2] == 0x01);
>  		break;
> +	case 0xb5:
> +		if (data[1] == 0x01) {
> +			sd->bt_enabled = false;
> +			sd->bt_device_connected = false;
> +		} else if (data[1] == 0x04) {
> +			sd->bt_enabled = true;
> +			sd->bt_device_connected = (data[2] == 0x01);
> +		}
> +		break;
>  	}
>  }
>  
> @@ -673,6 +701,8 @@ static void
> steelseries_arctis_nova_pro_parse_status(struct steelseries_device *
>  		sd->battery_capacity =
> steelseries_map_capacity(data[6], 0x00, 0x08);
>  		sd->battery_charging = (data[15] == 0x02);
>  		sd->mic_muted = (data[9] == 0x01);
> +		sd->bt_enabled = (data[4] == 0x00);
> +		sd->bt_device_connected = (data[5] == 0x01);
>  	} else if (data[0] == 0x07 && data[1] == 0x45) {
>  		sd->chatmix_game = data[2];
>  		sd->chatmix_chat = data[3];
> @@ -760,14 +790,16 @@ static const struct steelseries_device_info
> arctis_nova_7p_info = {
>  static const struct steelseries_device_info arctis_nova_7_gen2_info
> = {
>  	.sync_interface = 3,
>  	.async_interface = 5,
> -	.capabilities = SS_CAP_BATTERY | SS_CAP_CHATMIX |
> SS_CAP_MIC_MUTE,
> +	.capabilities = SS_CAP_BATTERY | SS_CAP_CHATMIX |
> SS_CAP_MIC_MUTE |
> +			SS_CAP_BT_ENABLED |
> SS_CAP_BT_DEVICE_CONNECTED,
>  	.request_status = steelseries_arctis_nova_request_status,
>  	.parse_status = steelseries_arctis_nova_7_gen2_parse_status,
>  };
>  
>  static const struct steelseries_device_info arctis_nova_pro_info = {
>  	.sync_interface = 4,
> -	.capabilities = SS_CAP_BATTERY | SS_CAP_CHATMIX |
> SS_CAP_MIC_MUTE,
> +	.capabilities = SS_CAP_BATTERY | SS_CAP_CHATMIX |
> SS_CAP_MIC_MUTE |
> +			SS_CAP_BT_ENABLED |
> SS_CAP_BT_DEVICE_CONNECTED,
>  	.quirks = SS_QUIRK_STATUS_SYNC_POLL,
>  	.request_status =
> steelseries_arctis_nova_pro_request_status,
>  	.parse_status = steelseries_arctis_nova_pro_parse_status,
> @@ -908,6 +940,70 @@ static int steelseries_battery_register(struct
> steelseries_device *sd)
>  	return 0;
>  }
>  
> +/*
> + * Sysfs attributes for device state
> + */
> +
> +static ssize_t bt_enabled_show(struct device *dev,
> +			       struct device_attribute *attr, char
> *buf)
> +{
> +	struct hid_device *hdev = to_hid_device(dev);
> +	struct steelseries_device *sd = hid_get_drvdata(hdev);
> +
> +	if (!sd->headset_connected)
> +		return -ENODEV;
> +
> +	return sysfs_emit(buf, "%d\n", sd->bt_enabled);
> +}
> +
> +static ssize_t bt_device_connected_show(struct device *dev,
> +					struct device_attribute
> *attr, char *buf)
> +{
> +	struct hid_device *hdev = to_hid_device(dev);
> +	struct steelseries_device *sd = hid_get_drvdata(hdev);
> +
> +	if (!sd->headset_connected)
> +		return -ENODEV;
> +
> +	return sysfs_emit(buf, "%d\n", sd->bt_device_connected);
> +}
> +
> +static DEVICE_ATTR_RO(bt_enabled);
> +static DEVICE_ATTR_RO(bt_device_connected);
> +
> +static struct attribute *steelseries_headset_attrs[] = {
> +	&dev_attr_bt_enabled.attr,
> +	&dev_attr_bt_device_connected.attr,
> +	NULL,
> +};
> +
> +static umode_t steelseries_headset_attr_is_visible(struct kobject
> *kobj,
> +						   struct attribute
> *attr,
> +						   int index)
> +{
> +	struct device *dev = kobj_to_dev(kobj);
> +	struct hid_device *hdev = to_hid_device(dev);
> +	struct steelseries_device *sd = hid_get_drvdata(hdev);
> +	unsigned long caps;
> +
> +	if (!sd)
> +		return 0;
> +
> +	caps = sd->info->capabilities;
> +
> +	if (attr == &dev_attr_bt_enabled.attr)
> +		return (caps & SS_CAP_BT_ENABLED) ? attr->mode : 0;
> +	if (attr == &dev_attr_bt_device_connected.attr)
> +		return (caps & SS_CAP_BT_DEVICE_CONNECTED) ? attr-
> >mode : 0;
> +
> +	return 0;
> +}
> +
> +static const struct attribute_group steelseries_headset_attr_group =
> {
> +	.attrs = steelseries_headset_attrs,
> +	.is_visible = steelseries_headset_attr_is_visible,
> +};
> +
>  #if IS_BUILTIN(CONFIG_SND) || \
>  	(IS_MODULE(CONFIG_SND) && IS_MODULE(CONFIG_HID_STEELSERIES))
>  
> @@ -1218,6 +1314,13 @@ static int steelseries_probe(struct hid_device
> *hdev,
>  				hid_warn(hdev, "Failed to register
> battery: %d\n", ret);
>  		}
>  
> +		if (info->capabilities & (SS_CAP_BT_ENABLED |
> SS_CAP_BT_DEVICE_CONNECTED)) {
> +			ret = sysfs_create_group(&hdev->dev.kobj,
> +						
> &steelseries_headset_attr_group);
> +			if (ret)
> +				hid_warn(hdev, "Failed to create
> sysfs group: %d\n", ret);
> +		}
> +
>  #if IS_BUILTIN(CONFIG_SND) || \
>  	(IS_MODULE(CONFIG_SND) && IS_MODULE(CONFIG_HID_STEELSERIES))
>  		ret = steelseries_snd_register(sd);
> @@ -1289,6 +1392,10 @@ static void steelseries_remove(struct
> hid_device *hdev)
>  	}
>  
>  	if (interface_num == sd->info->sync_interface) {
> +		if (sd->info->capabilities & (SS_CAP_BT_ENABLED |
> SS_CAP_BT_DEVICE_CONNECTED))
> +			sysfs_remove_group(&hdev->dev.kobj,
> +					  
> &steelseries_headset_attr_group);
> +
>  		if (sd->info->async_interface) {
>  			struct hid_device *sibling;
>  

  reply	other threads:[~2026-03-03 11:01 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-27 23:50 [PATCH v3 00/18] HID: steelseries: Add support for Arctis headset lineup Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 01/18] HID: steelseries: Fix ARCTIS_1_X device mislabeling Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 02/18] HID: hid-ids: Add SteelSeries Arctis headset device IDs Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 03/18] HID: quirks: Add additional " Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 04/18] HID: steelseries: Add async support and unify device definitions Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 05/18] HID: steelseries: Update Kconfig help text for expanded headset support Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 06/18] HID: steelseries: Add ALSA sound card infrastructure Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 07/18] HID: steelseries: Add ChatMix ALSA mixer controls Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 08/18] HID: steelseries: Add mic mute ALSA mixer control Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 09/18] HID: steelseries: Add Bluetooth state sysfs attributes Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera [this message]
2026-02-27 23:50 ` [PATCH v3 10/18] HID: steelseries: Add settings poll infrastructure Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 11/18] HID: steelseries: Add sidetone ALSA mixer control Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 12/18] HID: steelseries: Add mic volume " Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 13/18] HID: steelseries: Add volume limiter " Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 14/18] HID: steelseries: Add Bluetooth call audio ducking control Sriman Achanta
2026-03-03 10:59   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 15/18] HID: steelseries: Add inactive time sysfs attribute Sriman Achanta
2026-03-03 10:59   ` Bastien Nocera
2026-02-27 23:50 ` [PATCH v3 16/18] HID: steelseries: Add Bluetooth auto-enable " Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 17/18] HID: steelseries: Add mic mute LED brightness control Sriman Achanta
2026-02-27 23:50 ` [PATCH v3 18/18] HID: steelseries: Document sysfs ABI Sriman Achanta
2026-03-03 10:58   ` Bastien Nocera
2026-03-03 10:59 ` [PATCH v3 00/18] HID: steelseries: Add support for Arctis headset lineup Bastien Nocera

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=545b7301f828ec022937c2bc53df0ae7eab285b1.camel@hadess.net \
    --to=hadess@hadess.net \
    --cc=bentiss@kernel.org \
    --cc=git@mayer-bgk.de \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=simon@mungewell.org \
    --cc=srimanachanta@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox