Linux Sound subsystem development
 help / color / mirror / Atom feed
* [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
@ 2026-08-14 10:41 Alexander N.
  2026-08-14 11:53 ` Takashi Iwai
  2026-08-14 13:17 ` Rong Zhang
  0 siblings, 2 replies; 5+ messages in thread
From: Alexander N. @ 2026-08-14 10:41 UTC (permalink / raw)
  To: linux-sound; +Cc: regressions, tiwai, perex, i

[-- Attachment #1: Type: text/plain, Size: 4710 bytes --]

Hello,

I found a regression in snd-usb-audio affecting the Logitech PRO X
Wireless Gaming Headset (USB ID 046d:0aba).

The device has a valid UAC1 playback volume control, but the sticky mixer
detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
expose sticky mixers") rejects it.

Hardware
========

   Logitech PRO X Wireless Gaming Headset
   USB ID: 046d:0aba

Observed kernel
===============

   7.1.5-ogc5.1.fc44.x86_64
   Bazzite/Fedora 44 OGC kernel

The OGC patch for this kernel does not modify sound/usb, and the relevant
mixer.c code matches upstream Linux 7.1.5.

I have not hardware-tested current mainline 7.2-rc7, but current upstream
mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
test and I could not find a device quirk for 046d:0aba.

Symptom
=======

Without a workaround, ALSA only exposes:

   Simple mixer control 'PCM',0
     Capabilities: pswitch pswitch-joined

There is no PCM Playback Volume control.

The kernel logs:

   usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling

I have also observed the same message ending in "=> 0", depending on the
hardware volume at probe time.

Because the playback volume control is removed, the physical volume wheel
changes the headset's hardware volume independently of the PipeWire/KDE
system volume.

USB Audio control behavior
==========================

The device is UAC1.

Feature Unit 2 exposes a master playback volume control.

Direct control requests, after temporarily unbinding AudioControl
interface 0 from snd-usb-audio, report:

   GET_MIN = -16384  (-64.00 dB)
   GET_MAX =      0  (  0.00 dB)
   GET_RES =    256  (  1.00 dB)

GET_CUR and SET_CUR both work, but the device has two quirks relevant to
the new sticky detection.

1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.

Measured from 0 dB:

   target     result   first visible GET_CUR change

    -1 dB     OK       81.3 ms
    -2 dB     OK       51.9 ms
    -4 dB     OK       47.3 ms
    -8 dB     OK       47.1 ms
   -16 dB     OK       51.7 ms
   -32 dB     OK       47.2 ms

2. The advertised minimum value -64 dB is not functional.

A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
even after 1000 ms.

This appears to cause a false positive in check_sticky_volume_control():

- cval->min is -16384 (-64 dB)
- cval->max is 0
- if the saved value is 0, max is skipped
- SET_CUR(min) returns success
- an immediate GET_CUR still returns the saved value
- the mixer is classified as sticky and is not registered

mixer_get_cur_broken is not appropriate
=======================================

I tested the mixer_get_cur_broken quirk.

GET_CUR on this device is not broken or constant. It correctly reports
host SET_CUR changes after the device delay, and it also reports volume
changes caused by the physical headset wheel.

Using an internal-only cached value would therefore lose useful hardware
state.

Local proof-of-concept fix
==========================

I built a local snd-usb-audio.ko against the running 7.1.5 kernel.

For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:

- clamp the unusable minimum from -64 dB to -63 dB
- skip the probe-time sticky/resolution checks for this control

With that module, ALSA exposes:

   Simple mixer control 'PCM',0
     Capabilities: pvolume pvolume-joined pswitch pswitch-joined
     Playback channels: Mono
     Limits: Playback 0 - 63

/proc/asound/card*/usbmixer shows:

   Unit: 2
     Control: name="PCM Playback Volume", index=0
     Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
     Volume: min=-16128, max=0, dBmin=-6300, dBmax=0

Most importantly, no userspace workaround is required once the mixer
control is restored.

Example before rotating the physical headset wheel:

   ALSA:     -27 dB / 57%
   PipeWire: 0.35

After rotating the headset wheel:

   ALSA:     -11 dB / 83%
   PipeWire: 0.65

KDE system volume follows the physical wheel as expected.

I attached the proof-of-concept diff and the measured results. I am happy
to test a maintainer-preferred implementation or additional diagnostics.

My suspicion is that this device exposes two assumptions in the sticky
mixer probe that are not universally safe:

1. GET_CUR is assumed to reflect SET_CUR immediately.
2. advertised min/max values are assumed to be usable test values.

Thanks.

#regzbot introduced: 86aa1ea1f15ce6b56ac1b4c0d9b88a07a5b9bf03

[-- Attachment #2: measurements.txt --]
[-- Type: text/plain, Size: 1619 bytes --]

Logitech PRO X Wireless Gaming Headset
USB ID: 046d:0aba

UAC1 playback control
---------------------
Feature Unit: 2
Control: UAC_FU_VOLUME
Channel: master (0)

GET_MIN: -16384 = -64.00 dB
GET_MAX:      0 =   0.00 dB
GET_RES:    256 =   1.00 dB

SET_CUR / GET_CUR timing
------------------------
Start: 0 dB

Target   Result   First visible GET_CUR change
 -1 dB   OK       81.3 ms
 -2 dB   OK       51.9 ms
 -4 dB   OK       47.3 ms
 -8 dB   OK       47.1 ms
-16 dB   OK       51.7 ms
-32 dB   OK       47.2 ms
-64 dB   FAIL     GET_CUR stayed at 0 dB after 1000 ms

Observed stock kernel message
-----------------------------
usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling

Also observed depending on current hardware volume:
usb 1-10: 2:0: sticky mixer values (-16384/0/256 => 0), disabling

Stock ALSA mixer
----------------
Simple mixer control 'PCM',0
  Capabilities: pswitch pswitch-joined
  Playback channels: Mono
  Mono: Playback [on]

Patched ALSA mixer
------------------
Simple mixer control 'PCM',0
  Capabilities: pvolume pvolume-joined pswitch pswitch-joined
  Playback channels: Mono
  Limits: Playback 0 - 63

/proc/asound/card*/usbmixer:
Unit: 2
  Control: name="PCM Playback Volume", index=0
  Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
  Volume: min=-16128, max=0, dBmin=-6300, dBmax=0

Physical volume wheel integration after PoC fix
-----------------------------------------------
Before:
  ALSA:     -27 dB / 57%
  PipeWire: 0.35

After wheel rotation:
  ALSA:     -11 dB / 83%
  PipeWire: 0.65

KDE follows the headset wheel after the control is restored.

[-- Attachment #3: poc-fix.diff --]
[-- Type: text/x-patch, Size: 888 bytes --]

Proof-of-concept only; not proposed as the final upstream implementation.

--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1,3 +1,3 @@
@@
 		if (cval->res == 0)
 			cval->res = 1;

+		/*
+		 * Logitech PRO X Wireless volume quirk (046d:0aba)
+		 *
+		 * The device advertises -64 dB as minimum playback volume, but
+		 * SET_CUR(-64 dB) is ineffective. Working values are reflected by
+		 * GET_CUR only after roughly 50 ms, so the probe-time sticky and
+		 * resolution tests can mis-detect this valid control.
+		 */
+		if (cval->head.mixer->chip->usb_id == USB_ID(0x046d, 0x0aba) &&
+		    cval->head.id == 2 &&
+		    cval->control == UAC_FU_VOLUME) {
+			usb_audio_info(cval->head.mixer->chip,
+				       "Logitech PRO X Wireless: applying playback volume quirk\n");
+			cval->min = -16128; /* -63 dB */
+			goto no_checks;
+		}
+
 		if (cval->min < cval->max) {
 			int saved;

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

* Re: [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
  2026-08-14 10:41 [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky Alexander N.
@ 2026-08-14 11:53 ` Takashi Iwai
  2026-08-14 13:17 ` Rong Zhang
  1 sibling, 0 replies; 5+ messages in thread
From: Takashi Iwai @ 2026-08-14 11:53 UTC (permalink / raw)
  To: Alexander N.; +Cc: linux-sound, regressions, tiwai, perex, i

On Fri, 14 Aug 2026 12:41:54 +0200,
Alexander N. wrote:
> 
> Hello,
> 
> I found a regression in snd-usb-audio affecting the Logitech PRO X
> Wireless Gaming Headset (USB ID 046d:0aba).
> 
> The device has a valid UAC1 playback volume control, but the sticky mixer
> detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
> expose sticky mixers") rejects it.
> 
> Hardware
> ========
> 
>   Logitech PRO X Wireless Gaming Headset
>   USB ID: 046d:0aba
> 
> Observed kernel
> ===============
> 
>   7.1.5-ogc5.1.fc44.x86_64
>   Bazzite/Fedora 44 OGC kernel
> 
> The OGC patch for this kernel does not modify sound/usb, and the relevant
> mixer.c code matches upstream Linux 7.1.5.
> 
> I have not hardware-tested current mainline 7.2-rc7, but current upstream
> mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
> test and I could not find a device quirk for 046d:0aba.
> 
> Symptom
> =======
> 
> Without a workaround, ALSA only exposes:
> 
>   Simple mixer control 'PCM',0
>     Capabilities: pswitch pswitch-joined
> 
> There is no PCM Playback Volume control.
> 
> The kernel logs:
> 
>   usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling
> 
> I have also observed the same message ending in "=> 0", depending on the
> hardware volume at probe time.
> 
> Because the playback volume control is removed, the physical volume wheel
> changes the headset's hardware volume independently of the PipeWire/KDE
> system volume.
> 
> USB Audio control behavior
> ==========================
> 
> The device is UAC1.
> 
> Feature Unit 2 exposes a master playback volume control.
> 
> Direct control requests, after temporarily unbinding AudioControl
> interface 0 from snd-usb-audio, report:
> 
>   GET_MIN = -16384  (-64.00 dB)
>   GET_MAX =      0  (  0.00 dB)
>   GET_RES =    256  (  1.00 dB)
> 
> GET_CUR and SET_CUR both work, but the device has two quirks relevant to
> the new sticky detection.
> 
> 1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.
> 
> Measured from 0 dB:
> 
>   target     result   first visible GET_CUR change
> 
>    -1 dB     OK       81.3 ms
>    -2 dB     OK       51.9 ms
>    -4 dB     OK       47.3 ms
>    -8 dB     OK       47.1 ms
>   -16 dB     OK       51.7 ms
>   -32 dB     OK       47.2 ms
> 
> 2. The advertised minimum value -64 dB is not functional.
> 
> A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
> even after 1000 ms.
> 
> This appears to cause a false positive in check_sticky_volume_control():
> 
> - cval->min is -16384 (-64 dB)
> - cval->max is 0
> - if the saved value is 0, max is skipped
> - SET_CUR(min) returns success
> - an immediate GET_CUR still returns the saved value
> - the mixer is classified as sticky and is not registered
> 
> mixer_get_cur_broken is not appropriate
> =======================================
> 
> I tested the mixer_get_cur_broken quirk.
> 
> GET_CUR on this device is not broken or constant. It correctly reports
> host SET_CUR changes after the device delay, and it also reports volume
> changes caused by the physical headset wheel.
> 
> Using an internal-only cached value would therefore lose useful hardware
> state.
> 
> Local proof-of-concept fix
> ==========================
> 
> I built a local snd-usb-audio.ko against the running 7.1.5 kernel.
> 
> For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:
> 
> - clamp the unusable minimum from -64 dB to -63 dB
> - skip the probe-time sticky/resolution checks for this control
> 
> With that module, ALSA exposes:
> 
>   Simple mixer control 'PCM',0
>     Capabilities: pvolume pvolume-joined pswitch pswitch-joined
>     Playback channels: Mono
>     Limits: Playback 0 - 63
> 
> /proc/asound/card*/usbmixer shows:
> 
>   Unit: 2
>     Control: name="PCM Playback Volume", index=0
>     Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
>     Volume: min=-16128, max=0, dBmin=-6300, dBmax=0
> 
> Most importantly, no userspace workaround is required once the mixer
> control is restored.
> 
> Example before rotating the physical headset wheel:
> 
>   ALSA:     -27 dB / 57%
>   PipeWire: 0.35
> 
> After rotating the headset wheel:
> 
>   ALSA:     -11 dB / 83%
>   PipeWire: 0.65
> 
> KDE system volume follows the physical wheel as expected.
> 
> I attached the proof-of-concept diff and the measured results. I am happy
> to test a maintainer-preferred implementation or additional diagnostics.
> 
> My suspicion is that this device exposes two assumptions in the sticky
> mixer probe that are not universally safe:
> 
> 1. GET_CUR is assumed to reflect SET_CUR immediately.
> 2. advertised min/max values are assumed to be usable test values.
> 
> Thanks.

The patch looks simple and safe enough, so if this works for you, it's
fine to take.  In that case, please submit a proper patch.


thanks,

Takashi

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

* Re: [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
  2026-08-14 10:41 [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky Alexander N.
  2026-08-14 11:53 ` Takashi Iwai
@ 2026-08-14 13:17 ` Rong Zhang
  2026-08-14 14:02   ` Alexander Niemeyer
  2026-09-24 20:49   ` Faaris Ansari
  1 sibling, 2 replies; 5+ messages in thread
From: Rong Zhang @ 2026-08-14 13:17 UTC (permalink / raw)
  To: Alexander N., linux-sound; +Cc: regressions, tiwai, perex

Hi Alexander,

Thanks for the report.

On Fri, 2026-08-14 at 12:41 +0200, Alexander N. wrote:
> Hello,
> 
> I found a regression in snd-usb-audio affecting the Logitech PRO X
> Wireless Gaming Headset (USB ID 046d:0aba).
> 
> The device has a valid UAC1 playback volume control, but the sticky mixer
> detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
> expose sticky mixers") rejects it.
> 
> Hardware
> ========
> 
>    Logitech PRO X Wireless Gaming Headset
>    USB ID: 046d:0aba
> 
> Observed kernel
> ===============
> 
>    7.1.5-ogc5.1.fc44.x86_64
>    Bazzite/Fedora 44 OGC kernel
> 
> The OGC patch for this kernel does not modify sound/usb, and the relevant
> mixer.c code matches upstream Linux 7.1.5.
> 
> I have not hardware-tested current mainline 7.2-rc7, but current upstream
> mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
> test and I could not find a device quirk for 046d:0aba.
> 
> Symptom
> =======
> 
> Without a workaround, ALSA only exposes:
> 
>    Simple mixer control 'PCM',0
>      Capabilities: pswitch pswitch-joined
> 
> There is no PCM Playback Volume control.
> 
> The kernel logs:
> 
>    usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling
> 
> I have also observed the same message ending in "=> 0", depending on the
> hardware volume at probe time.
> 
> Because the playback volume control is removed, the physical volume wheel
> changes the headset's hardware volume independently of the PipeWire/KDE
> system volume.
> 
> USB Audio control behavior
> ==========================
> 
> The device is UAC1.
> 
> Feature Unit 2 exposes a master playback volume control.
> 
> Direct control requests, after temporarily unbinding AudioControl
> interface 0 from snd-usb-audio, report:
> 
>    GET_MIN = -16384  (-64.00 dB)
>    GET_MAX =      0  (  0.00 dB)
>    GET_RES =    256  (  1.00 dB)
> 
> GET_CUR and SET_CUR both work, but the device has two quirks relevant to
> the new sticky detection.
> 
> 1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.

Interesting.

> 
> Measured from 0 dB:
> 
>    target     result   first visible GET_CUR change
> 
>     -1 dB     OK       81.3 ms
>     -2 dB     OK       51.9 ms
>     -4 dB     OK       47.3 ms
>     -8 dB     OK       47.1 ms
>    -16 dB     OK       51.7 ms
>    -32 dB     OK       47.2 ms
> 
> 2. The advertised minimum value -64 dB is not functional.
> 
> A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
> even after 1000 ms.
> 
> This appears to cause a false positive in check_sticky_volume_control():
> 
> - cval->min is -16384 (-64 dB)
> - cval->max is 0
> - if the saved value is 0, max is skipped
> - SET_CUR(min) returns success
> - an immediate GET_CUR still returns the saved value
> - the mixer is classified as sticky and is not registered

Super interesting.

Maybe some previously reported devices were broken because of the same
reason.

I think, the sticky check could be more precise in this manner:

   res = (cval->max - cval->min) / 16; /* Check approximately 16 values. */
   if (res < cval->res)
   	res = cval->res;
   else
   	res = roundup(res, cval->res);
   
   for (i = cval->min; i+= res; i < cval->max) {
   	if (i == saved)
   		continue;
   	SET_CUR(i);
   	check = GET_CUR(i);
   	if (check != saved)
   		break;	/* Fast path. */
   	/*
   	 * Wait for asynchronous mixers. This sleeps for no more than 160ms
   	 * in total, which should provide some time for the mixer to change
   	 * its value.
   	 * Note that there is no need to wait between SET_CUR and GET_CUR,
   	 * as we don't care whether the GET_CUR value matches the SET_CUR one.
   	 * What we expect is just a GET_CUR value differing from the saved one.
   	 * It this manner, most devices should go through the fast path without
   	 * extra sleep.
   	 */
   	msleep(10);
   }
   [...]

This should classify your device as non-sticky.

I will find some time to write a patch for that. I would be grateful if
you can test it then.

Thanks,
Rong

> 
> mixer_get_cur_broken is not appropriate
> =======================================
> 
> I tested the mixer_get_cur_broken quirk.
> 
> GET_CUR on this device is not broken or constant. It correctly reports
> host SET_CUR changes after the device delay, and it also reports volume
> changes caused by the physical headset wheel.
> 
> Using an internal-only cached value would therefore lose useful hardware
> state.
> 
> Local proof-of-concept fix
> ==========================
> 
> I built a local snd-usb-audio.ko against the running 7.1.5 kernel.
> 
> For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:
> 
> - clamp the unusable minimum from -64 dB to -63 dB
> - skip the probe-time sticky/resolution checks for this control
> 
> With that module, ALSA exposes:
> 
>    Simple mixer control 'PCM',0
>      Capabilities: pvolume pvolume-joined pswitch pswitch-joined
>      Playback channels: Mono
>      Limits: Playback 0 - 63
> 
> /proc/asound/card*/usbmixer shows:
> 
>    Unit: 2
>      Control: name="PCM Playback Volume", index=0
>      Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
>      Volume: min=-16128, max=0, dBmin=-6300, dBmax=0
> 
> Most importantly, no userspace workaround is required once the mixer
> control is restored.
> 
> Example before rotating the physical headset wheel:
> 
>    ALSA:     -27 dB / 57%
>    PipeWire: 0.35
> 
> After rotating the headset wheel:
> 
>    ALSA:     -11 dB / 83%
>    PipeWire: 0.65
> 
> KDE system volume follows the physical wheel as expected.
> 
> I attached the proof-of-concept diff and the measured results. I am happy
> to test a maintainer-preferred implementation or additional diagnostics.
> 
> My suspicion is that this device exposes two assumptions in the sticky
> mixer probe that are not universally safe:
> 
> 1. GET_CUR is assumed to reflect SET_CUR immediately.
> 2. advertised min/max values are assumed to be usable test values.
> 
> Thanks.
> 
> #regzbot introduced: 86aa1ea1f15ce6b56ac1b4c0d9b88a07a5b9bf03

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

* Re: [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
  2026-08-14 13:17 ` Rong Zhang
@ 2026-08-14 14:02   ` Alexander Niemeyer
  2026-09-24 20:49   ` Faaris Ansari
  1 sibling, 0 replies; 5+ messages in thread
From: Alexander Niemeyer @ 2026-08-14 14:02 UTC (permalink / raw)
  To: linux-sound; +Cc: regressions, tiwai, perex

Thanks Rong.
I'd be happy to test your patch on the Logitech PRO X Wireless as soon 
as it's ready.

Am 14.08.26 um 15:17 schrieb Rong Zhang:
> Hi Alexander,
>
> Thanks for the report.
>
> On Fri, 2026-08-14 at 12:41 +0200, Alexander N. wrote:
>> Hello,
>>
>> I found a regression in snd-usb-audio affecting the Logitech PRO X
>> Wireless Gaming Headset (USB ID 046d:0aba).
>>
>> The device has a valid UAC1 playback volume control, but the sticky mixer
>> detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
>> expose sticky mixers") rejects it.
>>
>> Hardware
>> ========
>>
>>     Logitech PRO X Wireless Gaming Headset
>>     USB ID: 046d:0aba
>>
>> Observed kernel
>> ===============
>>
>>     7.1.5-ogc5.1.fc44.x86_64
>>     Bazzite/Fedora 44 OGC kernel
>>
>> The OGC patch for this kernel does not modify sound/usb, and the relevant
>> mixer.c code matches upstream Linux 7.1.5.
>>
>> I have not hardware-tested current mainline 7.2-rc7, but current upstream
>> mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
>> test and I could not find a device quirk for 046d:0aba.
>>
>> Symptom
>> =======
>>
>> Without a workaround, ALSA only exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pswitch pswitch-joined
>>
>> There is no PCM Playback Volume control.
>>
>> The kernel logs:
>>
>>     usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling
>>
>> I have also observed the same message ending in "=> 0", depending on the
>> hardware volume at probe time.
>>
>> Because the playback volume control is removed, the physical volume wheel
>> changes the headset's hardware volume independently of the PipeWire/KDE
>> system volume.
>>
>> USB Audio control behavior
>> ==========================
>>
>> The device is UAC1.
>>
>> Feature Unit 2 exposes a master playback volume control.
>>
>> Direct control requests, after temporarily unbinding AudioControl
>> interface 0 from snd-usb-audio, report:
>>
>>     GET_MIN = -16384  (-64.00 dB)
>>     GET_MAX =      0  (  0.00 dB)
>>     GET_RES =    256  (  1.00 dB)
>>
>> GET_CUR and SET_CUR both work, but the device has two quirks relevant to
>> the new sticky detection.
>>
>> 1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.
> Interesting.
>
>> Measured from 0 dB:
>>
>>     target     result   first visible GET_CUR change
>>
>>      -1 dB     OK       81.3 ms
>>      -2 dB     OK       51.9 ms
>>      -4 dB     OK       47.3 ms
>>      -8 dB     OK       47.1 ms
>>     -16 dB     OK       51.7 ms
>>     -32 dB     OK       47.2 ms
>>
>> 2. The advertised minimum value -64 dB is not functional.
>>
>> A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
>> even after 1000 ms.
>>
>> This appears to cause a false positive in check_sticky_volume_control():
>>
>> - cval->min is -16384 (-64 dB)
>> - cval->max is 0
>> - if the saved value is 0, max is skipped
>> - SET_CUR(min) returns success
>> - an immediate GET_CUR still returns the saved value
>> - the mixer is classified as sticky and is not registered
> Super interesting.
>
> Maybe some previously reported devices were broken because of the same
> reason.
>
> I think, the sticky check could be more precise in this manner:
>
>     res = (cval->max - cval->min) / 16; /* Check approximately 16 values. */
>     if (res < cval->res)
>     	res = cval->res;
>     else
>     	res = roundup(res, cval->res);
>     
>     for (i = cval->min; i+= res; i < cval->max) {
>     	if (i == saved)
>     		continue;
>     	SET_CUR(i);
>     	check = GET_CUR(i);
>     	if (check != saved)
>     		break;	/* Fast path. */
>     	/*
>     	 * Wait for asynchronous mixers. This sleeps for no more than 160ms
>     	 * in total, which should provide some time for the mixer to change
>     	 * its value.
>     	 * Note that there is no need to wait between SET_CUR and GET_CUR,
>     	 * as we don't care whether the GET_CUR value matches the SET_CUR one.
>     	 * What we expect is just a GET_CUR value differing from the saved one.
>     	 * It this manner, most devices should go through the fast path without
>     	 * extra sleep.
>     	 */
>     	msleep(10);
>     }
>     [...]
>
> This should classify your device as non-sticky.
>
> I will find some time to write a patch for that. I would be grateful if
> you can test it then.
>
> Thanks,
> Rong
>
>> mixer_get_cur_broken is not appropriate
>> =======================================
>>
>> I tested the mixer_get_cur_broken quirk.
>>
>> GET_CUR on this device is not broken or constant. It correctly reports
>> host SET_CUR changes after the device delay, and it also reports volume
>> changes caused by the physical headset wheel.
>>
>> Using an internal-only cached value would therefore lose useful hardware
>> state.
>>
>> Local proof-of-concept fix
>> ==========================
>>
>> I built a local snd-usb-audio.ko against the running 7.1.5 kernel.
>>
>> For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:
>>
>> - clamp the unusable minimum from -64 dB to -63 dB
>> - skip the probe-time sticky/resolution checks for this control
>>
>> With that module, ALSA exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pvolume pvolume-joined pswitch pswitch-joined
>>       Playback channels: Mono
>>       Limits: Playback 0 - 63
>>
>> /proc/asound/card*/usbmixer shows:
>>
>>     Unit: 2
>>       Control: name="PCM Playback Volume", index=0
>>       Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
>>       Volume: min=-16128, max=0, dBmin=-6300, dBmax=0
>>
>> Most importantly, no userspace workaround is required once the mixer
>> control is restored.
>>
>> Example before rotating the physical headset wheel:
>>
>>     ALSA:     -27 dB / 57%
>>     PipeWire: 0.35
>>
>> After rotating the headset wheel:
>>
>>     ALSA:     -11 dB / 83%
>>     PipeWire: 0.65
>>
>> KDE system volume follows the physical wheel as expected.
>>
>> I attached the proof-of-concept diff and the measured results. I am happy
>> to test a maintainer-preferred implementation or additional diagnostics.
>>
>> My suspicion is that this device exposes two assumptions in the sticky
>> mixer probe that are not universally safe:
>>
>> 1. GET_CUR is assumed to reflect SET_CUR immediately.
>> 2. advertised min/max values are assumed to be usable test values.
>>
>> Thanks.
>>
>> #regzbot introduced: 86aa1ea1f15ce6b56ac1b4c0d9b88a07a5b9bf03

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

* Re: [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
  2026-08-14 13:17 ` Rong Zhang
  2026-08-14 14:02   ` Alexander Niemeyer
@ 2026-09-24 20:49   ` Faaris Ansari
  1 sibling, 0 replies; 5+ messages in thread
From: Faaris Ansari @ 2026-09-24 20:49 UTC (permalink / raw)
  To: Rong Zhang, Alexander N., linux-sound; +Cc: regressions, tiwai, perex

Hi there,

It seems I'm experiencing this same bug with my Audient EVO4 interface.

The volume when controlling it via the hardware knob is as normal, but 
trying to modify the hardware volume through software like pwvucontrol 
or wpctl causes the volume to decrease drastically.

I originally reported that here as I thought it was a wireplumber issue, 
it appears instead to be a kernel regression between 7.1.13 and 7.2.4 
somewhere.

https://gitlab.freedesktop.org/pipewire/wireplumber/-/work_items/1022

On 14/08/2026 14:17, Rong Zhang wrote:
> Hi Alexander,
>
> Thanks for the report.
>
> On Fri, 2026-08-14 at 12:41 +0200, Alexander N. wrote:
>> Hello,
>>
>> I found a regression in snd-usb-audio affecting the Logitech PRO X
>> Wireless Gaming Headset (USB ID 046d:0aba).
>>
>> The device has a valid UAC1 playback volume control, but the sticky mixer
>> detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
>> expose sticky mixers") rejects it.
>>
>> Hardware
>> ========
>>
>>     Logitech PRO X Wireless Gaming Headset
>>     USB ID: 046d:0aba
>>
>> Observed kernel
>> ===============
>>
>>     7.1.5-ogc5.1.fc44.x86_64
>>     Bazzite/Fedora 44 OGC kernel
>>
>> The OGC patch for this kernel does not modify sound/usb, and the relevant
>> mixer.c code matches upstream Linux 7.1.5.
>>
>> I have not hardware-tested current mainline 7.2-rc7, but current upstream
>> mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
>> test and I could not find a device quirk for 046d:0aba.
>>
>> Symptom
>> =======
>>
>> Without a workaround, ALSA only exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pswitch pswitch-joined
>>
>> There is no PCM Playback Volume control.
>>
>> The kernel logs:
>>
>>     usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling
>>
>> I have also observed the same message ending in "=> 0", depending on the
>> hardware volume at probe time.
>>
>> Because the playback volume control is removed, the physical volume wheel
>> changes the headset's hardware volume independently of the PipeWire/KDE
>> system volume.
>>
>> USB Audio control behavior
>> ==========================
>>
>> The device is UAC1.
>>
>> Feature Unit 2 exposes a master playback volume control.
>>
>> Direct control requests, after temporarily unbinding AudioControl
>> interface 0 from snd-usb-audio, report:
>>
>>     GET_MIN = -16384  (-64.00 dB)
>>     GET_MAX =      0  (  0.00 dB)
>>     GET_RES =    256  (  1.00 dB)
>>
>> GET_CUR and SET_CUR both work, but the device has two quirks relevant to
>> the new sticky detection.
>>
>> 1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.
> Interesting.
>
>> Measured from 0 dB:
>>
>>     target     result   first visible GET_CUR change
>>
>>      -1 dB     OK       81.3 ms
>>      -2 dB     OK       51.9 ms
>>      -4 dB     OK       47.3 ms
>>      -8 dB     OK       47.1 ms
>>     -16 dB     OK       51.7 ms
>>     -32 dB     OK       47.2 ms
>>
>> 2. The advertised minimum value -64 dB is not functional.
>>
>> A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
>> even after 1000 ms.
>>
>> This appears to cause a false positive in check_sticky_volume_control():
>>
>> - cval->min is -16384 (-64 dB)
>> - cval->max is 0
>> - if the saved value is 0, max is skipped
>> - SET_CUR(min) returns success
>> - an immediate GET_CUR still returns the saved value
>> - the mixer is classified as sticky and is not registered
> Super interesting.
>
> Maybe some previously reported devices were broken because of the same
> reason.
>
> I think, the sticky check could be more precise in this manner:
>
>     res = (cval->max - cval->min) / 16; /* Check approximately 16 values. */
>     if (res < cval->res)
>     	res = cval->res;
>     else
>     	res = roundup(res, cval->res);
>     
>     for (i = cval->min; i+= res; i < cval->max) {
>     	if (i == saved)
>     		continue;
>     	SET_CUR(i);
>     	check = GET_CUR(i);
>     	if (check != saved)
>     		break;	/* Fast path. */
>     	/*
>     	 * Wait for asynchronous mixers. This sleeps for no more than 160ms
>     	 * in total, which should provide some time for the mixer to change
>     	 * its value.
>     	 * Note that there is no need to wait between SET_CUR and GET_CUR,
>     	 * as we don't care whether the GET_CUR value matches the SET_CUR one.
>     	 * What we expect is just a GET_CUR value differing from the saved one.
>     	 * It this manner, most devices should go through the fast path without
>     	 * extra sleep.
>     	 */
>     	msleep(10);
>     }
>     [...]
>
> This should classify your device as non-sticky.
>
> I will find some time to write a patch for that. I would be grateful if
> you can test it then.
>
> Thanks,
> Rong
>
>> mixer_get_cur_broken is not appropriate
>> =======================================
>>
>> I tested the mixer_get_cur_broken quirk.
>>
>> GET_CUR on this device is not broken or constant. It correctly reports
>> host SET_CUR changes after the device delay, and it also reports volume
>> changes caused by the physical headset wheel.
>>
>> Using an internal-only cached value would therefore lose useful hardware
>> state.
>>
>> Local proof-of-concept fix
>> ==========================
>>
>> I built a local snd-usb-audio.ko against the running 7.1.5 kernel.
>>
>> For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:
>>
>> - clamp the unusable minimum from -64 dB to -63 dB
>> - skip the probe-time sticky/resolution checks for this control
>>
>> With that module, ALSA exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pvolume pvolume-joined pswitch pswitch-joined
>>       Playback channels: Mono
>>       Limits: Playback 0 - 63
>>
>> /proc/asound/card*/usbmixer shows:
>>
>>     Unit: 2
>>       Control: name="PCM Playback Volume", index=0
>>       Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
>>       Volume: min=-16128, max=0, dBmin=-6300, dBmax=0
>>
>> Most importantly, no userspace workaround is required once the mixer
>> control is restored.
>>
>> Example before rotating the physical headset wheel:
>>
>>     ALSA:     -27 dB / 57%
>>     PipeWire: 0.35
>>
>> After rotating the headset wheel:
>>
>>     ALSA:     -11 dB / 83%
>>     PipeWire: 0.65
>>
>> KDE system volume follows the physical wheel as expected.
>>
>> I attached the proof-of-concept diff and the measured results. I am happy
>> to test a maintainer-preferred implementation or additional diagnostics.
>>
>> My suspicion is that this device exposes two assumptions in the sticky
>> mixer probe that are not universally safe:
>>
>> 1. GET_CUR is assumed to reflect SET_CUR immediately.
>> 2. advertised min/max values are assumed to be usable test values.
>>
>> Thanks.
>>
>> #regzbot introduced: 86aa1ea1f15ce6b56ac1b4c0d9b88a07a5b9bf03

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

end of thread, other threads:[~2026-09-24 20:49 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14 10:41 [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky Alexander N.
2026-08-14 11:53 ` Takashi Iwai
2026-08-14 13:17 ` Rong Zhang
2026-08-14 14:02   ` Alexander Niemeyer
2026-09-24 20:49   ` Faaris Ansari

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox