Add G560 audio features: bass level, working equalizer, jack detection
Add the BassTone feature (0x8305) as a 0-100 slider — subwoofer level
on the G560, hardware-verified.
Fix the Equalizer setting (0x8310), which never built on devices
reporting signed dB limits: getEQInfo dbMin/dbMax are signed (the G560
reports -20..+6) but were unpacked unsigned, tripping the validator's
min/max assertion. The reported bounds are also exclusive — the G560
NACKs writes at exactly dbMin/dbMax — so present dbMin+1..dbMax-1.
Render with the vertical-slider graphic EQ panel. Note: on the G560
the stored curve round-trips but has no audible effect on USB
playback; whether it shapes the aux input path is still unknown.
Rename HEADSET_OUT (0x8320) to JACK_DETECTION: the feature reports
3.5mm jack presence (getJackStatus statuses/available bitmasks), it
is not an output-mode control.
Fix solaar show sending little-endian feature IDs to ROOT.getFeature,
which silently dropped the flags/version column for every
non-palindromic feature ID and displayed unknown features byte-swapped
(the G560's 0x8305 rendered as "unknown:8305 {0583}").
This commit is contained in:
parent
38b5665e51
commit
0cc048cdf6
|
|
@ -4,12 +4,12 @@ G560 Gaming Speaker
|
|||
Codename : G560 Gaming Speaker
|
||||
Kind : speaker
|
||||
Protocol : HID++ 4.2
|
||||
Serial number:
|
||||
Serial number:
|
||||
Model ID: 000000000A78
|
||||
Unit ID: FFFFFFFF
|
||||
0: U1 22.04.B0370
|
||||
Supports 10 HID++ 2.0 features:
|
||||
0: ROOT {0000} V0
|
||||
0: ROOT {0000} V0
|
||||
1: FEATURE SET {0001}
|
||||
2: DEVICE FW VERSION {0003}
|
||||
Firmware: 0 U1 22.04.B0370 0A78
|
||||
|
|
@ -60,5 +60,5 @@ G560 Gaming Speaker
|
|||
8: BRIGHTNESS CONTROL {8040}
|
||||
Brightness Control (saved): 100
|
||||
Brightness Control : 100
|
||||
9: unknown:8305 {0583} V0
|
||||
9: unknown:8305 {0583} V0
|
||||
Battery status unavailable.
|
||||
|
|
|
|||
|
|
@ -175,10 +175,11 @@ class SupportedFeature(IntEnum):
|
|||
OPERATING_RANGE = 0x8138
|
||||
TRUE_FORCE = 0x8139
|
||||
FFB_FILTER = 0x8140
|
||||
# Headsets
|
||||
# Headsets / speakers
|
||||
SIDETONE = 0x8300
|
||||
BASS_TONE = 0x8305
|
||||
EQUALIZER = 0x8310
|
||||
HEADSET_OUT = 0x8320
|
||||
JACK_DETECTION = 0x8320 # jack presence (was HEADSET_OUT)
|
||||
# Centurion core
|
||||
CENTURION_DEVICE_INFO = 0x0100
|
||||
CENTURION_DEVICE_NAME = 0x0101
|
||||
|
|
|
|||
|
|
@ -1587,6 +1587,16 @@ class Sidetone(settings.Setting):
|
|||
max_value = 100
|
||||
|
||||
|
||||
class BassTone(settings.Setting):
|
||||
name = "bass_tone"
|
||||
label = _("Bass Level")
|
||||
description = _("Set subwoofer bass level.")
|
||||
feature = _F.BASS_TONE
|
||||
validator_class = settings_validator.RangeValidator
|
||||
min_value = 0
|
||||
max_value = 100
|
||||
|
||||
|
||||
class Equalizer(settings.RangeFieldSetting):
|
||||
name = "equalizer"
|
||||
label = _("Equalizer")
|
||||
|
|
@ -1596,16 +1606,21 @@ class Equalizer(settings.RangeFieldSetting):
|
|||
keys_universe = []
|
||||
|
||||
class validator_class(settings_validator.PackedRangeValidator):
|
||||
kind = settings.Kind.GRAPHIC_EQ
|
||||
|
||||
@classmethod
|
||||
def build(cls, setting_class, device):
|
||||
data = device.feature_request(_F.EQUALIZER, 0x00)
|
||||
if not data:
|
||||
return None
|
||||
count, dbRange, _x, dbMin, dbMax = struct.unpack("!BBBBB", data[:5])
|
||||
if dbMin == 0:
|
||||
dbMin = -dbRange
|
||||
if dbMax == 0:
|
||||
dbMax = dbRange
|
||||
# dbMin/dbMax are signed; the G560 reports an asymmetric -20..+6
|
||||
count, dbRange, _x, dbMin, dbMax = struct.unpack("!BBBbb", data[:5])
|
||||
if dbMin == 0 and dbMax == 0:
|
||||
dbMin, dbMax = -dbRange, dbRange
|
||||
else:
|
||||
# reported bounds are exclusive: the G560 NACKs writes at
|
||||
# exactly dbMin/dbMax but accepts dbMin+1..dbMax-1
|
||||
dbMin, dbMax = dbMin + 1, dbMax - 1
|
||||
map = common.NamedInts()
|
||||
for g in range((count + 6) // 7):
|
||||
freqs = device.feature_request(_F.EQUALIZER, 0x10, g * 7)
|
||||
|
|
@ -4520,6 +4535,7 @@ SETTINGS: list[settings.Setting] = [
|
|||
HapticLevel,
|
||||
PlayHapticWaveForm,
|
||||
Sidetone,
|
||||
BassTone,
|
||||
Equalizer,
|
||||
ADCPower,
|
||||
HeadsetEcoMode,
|
||||
|
|
|
|||
|
|
@ -239,11 +239,9 @@ def _print_device(dev, num=None):
|
|||
# For centurion child, skip dongle features (already shown on the receiver)
|
||||
if is_centurion_child and not in_sub_device:
|
||||
continue
|
||||
if isinstance(feature, str):
|
||||
feature_bytes = bytes.fromhex(feature[-4:])
|
||||
else:
|
||||
feature_bytes = feature.to_bytes(2, byteorder="little")
|
||||
feature_int = int.from_bytes(feature_bytes, byteorder="little")
|
||||
# ROOT.getFeature takes the feature ID big-endian.
|
||||
feature_int = int(feature[-4:], 16) if isinstance(feature, str) else int(feature)
|
||||
feature_bytes = feature_int.to_bytes(2, byteorder="big")
|
||||
display_name = feature
|
||||
if is_centurion_child and in_sub_device:
|
||||
# Use cached version — skip slow bridge ROOT queries
|
||||
|
|
|
|||
|
|
@ -271,6 +271,11 @@ simple_tests = [
|
|||
fake_hidpp.Response("05", 0x0400),
|
||||
fake_hidpp.Response("0A", 0x0410, "0A"),
|
||||
),
|
||||
Setup(
|
||||
FeatureTest(settings_templates.BassTone, 0x46, 0x50),
|
||||
fake_hidpp.Response("46", 0x0400),
|
||||
fake_hidpp.Response("50", 0x0410, "50"),
|
||||
),
|
||||
Setup(
|
||||
FeatureTest(settings_templates.ADCPower, 5, 0xA, version=0x03),
|
||||
fake_hidpp.Response("05", 0x0410),
|
||||
|
|
@ -662,6 +667,15 @@ key_tests = [
|
|||
fake_hidpp.Response("E010", 0x0430, "02E010"),
|
||||
fake_hidpp.Response("E018", 0x0430, "02E018"),
|
||||
),
|
||||
Setup( # signed asymmetric dB range as reported by the G560 (-20..+6, bounds exclusive)
|
||||
FeatureTest(settings_templates.Equalizer, {0: -4, 1: 2}, {1: 5}, 2),
|
||||
[-19, 5],
|
||||
fake_hidpp.Response("021A00EC06", 0x0400),
|
||||
fake_hidpp.Response("0000200040", 0x0410, "00"),
|
||||
fake_hidpp.Response("FC02", 0x0420, "00"),
|
||||
fake_hidpp.Response("FC02", 0x0430, "02FC02"),
|
||||
fake_hidpp.Response("FC05", 0x0430, "02FC05"),
|
||||
),
|
||||
Setup( # HeadsetOnboardEQ: 2 bands, 128Hz/-2dB/Q10 and 256Hz/+3dB/Q10
|
||||
FeatureTest(settings_templates.HeadsetOnboardEQ, {0: -2, 1: 3}, {1: 5}, 2),
|
||||
[-12, 12],
|
||||
|
|
|
|||
Loading…
Reference in New Issue