Skip to content

Add sidetone status reading for Arctis Nova 7 Gen 2 - #560

Open
flexusjan wants to merge 2 commits into
Sapd:masterfrom
flexusjan:feature/nova7-gen2-sidetone-status
Open

Add sidetone status reading for Arctis Nova 7 Gen 2#560
flexusjan wants to merge 2 commits into
Sapd:masterfrom
flexusjan:feature/nova7-gen2-sidetone-status

Conversation

@flexusjan

@flexusjan flexusjan commented Aug 13, 2026

Copy link
Copy Markdown

Changes made

Adds a generic read-only sidetone status capability and implements it for the verified SteelSeries Arctis Nova 7 Gen 2 (1038:227e).

Device protocol

  • Sends the 64-byte Nova settings request beginning with 00 20.
  • Accepts settings responses beginning with 20 and reads sidetone from byte 2.
  • Maps native Off/Low/Medium/High values 0/1/2/3 to HeadsetControl values 0/43/85/128 using an explicit table.
  • Validates response length, response type, and native value range.
  • Skips known asynchronous Nova status reports (b0) while waiting for the settings response.
  • Restricts sidetone reading to PID 0x227e; other Nova 7 PIDs do not advertise the capability.
  • Sends the confirmed 00 09 persistence command after setting sidetone only for PID 0x227e.

The protocol was captured from SteelSeries GG on Windows and is independently corroborated by the proposed Linux SteelSeries driver implementation:
https://patchew.org/linux/20260227235042.410062-1-srimanachanta%40gmail.com/20260227235042.410062-15-srimanachanta%40gmail.com/

Public interfaces

  • New internal query capability: CAP_SIDETONE_STATUS
  • CLI: headsetcontrol -s / headsetcontrol --sidetone queries; providing LEVEL continues to set sidetone
  • C++: Headset::getSidetone()
  • C: hsc_get_sidetone()
  • Text, short, JSON, YAML, and ENV output support
  • CLI output API version increased from 1.4 to 1.5 for the additive structured-output field

CLI examples:

headsetcontrol -s             # query sidetone
headsetcontrol -s 43          # set sidetone
headsetcontrol --sidetone     # query sidetone
headsetcontrol --sidetone 43  # set sidetone

Example text output:

Sidetone: Low (43; device level 1)

Example JSON field:

"sidetone": {
  "level": 43,
  "device_level": 1,
  "name": "Low"
}

Tests

  • Unit tests cover all four native levels.
  • Protocol tests cover short responses, unexpected response types, invalid values, asynchronous status reports, HID write/read errors, and timeouts.
  • Tests verify the Gen 2 save command and ensure other Nova 7 PIDs neither save nor advertise the read capability.
  • C++, C API, CLI, and structured-output tests cover the new public interfaces.
  • CLI tests cover short/long query and setter forms and verify that the separate --sidetone-status option is not exposed.
  • cmake --build build --parallel: passed
  • cmake --build build --target check: 2/2 tests passed
  • clang-format 18.1.8 dry-run: passed
  • git diff --check: passed

Real hardware acceptance test on 1038:227e:

SteelSeries GG: Low
HeadsetControl: Sidetone: Low (43; device level 1)

The optional-value CLI behavior was also verified on the same device with both -s and --sidetone.

Closes #559

Checklist

@Sapd

Sapd commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Thanks looks good so far, will do a more detailed review.

However im not sure if it should be --sidetone-status or just the existing -s giving a possible hint also in the CLI.

@flexusjan

Copy link
Copy Markdown
Author

Thanks! Reusing the existing -s / --sidetone option sounds better to me as well.

My preferred CLI behavior would be:

headsetcontrol -s 43          # set sidetone
headsetcontrol -s             # query sidetone
headsetcontrol --sidetone 43  # set sidetone
headsetcontrol --sidetone     # query sidetone

That keeps the existing setter syntax compatible and avoids adding a separate public --sidetone-status option. The help could describe it as -s, --sidetone [LEVEL] with “Get the current sidetone level, or set it to LEVEL (0-128)”.

Internally I would keep the read capability separate, since some devices can set sidetone but cannot query it. Calling -s without a value on such a device would then return a clear “reading sidetone is not supported” error.

I can update the PR accordingly after your detailed review, or right away if this is the direction you prefer.

@Sapd

Sapd commented Aug 14, 2026

Copy link
Copy Markdown
Owner

That keeps the existing setter syntax compatible and avoids adding a separate public --sidetone-status option. The help could describe it as -s, --sidetone [LEVEL] with “Get the current sidetone level, or set it to LEVEL (0-128)”.

Yes

Internally I would keep the read capability separate, since some devices can set sidetone but cannot query it. Calling -s without a value on such a device would then return a clear “reading sidetone is not supported” error.

Yes, sounds good keeping it separate.

Feel free to implement, I will review next week.

@flexusjan

Copy link
Copy Markdown
Author

Implemented in 2144ea9. The CLI now uses -s / --sidetone without a value to query, while the existing forms with a value continue to set sidetone. I added regression coverage for all four short/long query/set forms, updated help and docs, and verified the behavior on the real 1038:227e device. Build, 2/2 tests, clang-format 18, and whitespace checks pass locally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read sidetone status on SteelSeries Arctis Nova 7 Gen 2

2 participants