Linux Input/HID development
 help / color / mirror / Atom feed
* snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c)
@ 2026-08-12 17:10 Mikhail Gavrilov
  2026-08-13  7:24 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Mikhail Gavrilov @ 2026-08-12 17:10 UTC (permalink / raw)
  To: linux-sound; +Cc: tiwai, perex, g, jikos, bentiss, linux-input

Hello,

I would like to add ALSA mixer controls for the analogue input gain of a
USB audio interface whose control channel is a vendor-specific HID
interface, and I would like to agree on the shape before writing code,
because it crosses into drivers/hid.

The device is a Topping Professional M62, USB 152a:875c. In its
multichannel modes it presents 10 playback and 16 capture channels on
interfaces 1 and 2, a DFU interface, and interface 4 of class 3 (HID)
with a vendor-defined usage page, one 16-byte Input report and one
16-byte Output report, and no report IDs.

The problem: the microphone preamplifier gain, 0..88 dB per the
specification, is not reachable through ALSA. The card does expose a
'Mic Capture Volume', but a gain ladder measured in silence shows that
control to be a digital trim after the converter. The recorded noise
floor is flat at about -172 dBFS at the bottom of its range, far below
any converter's own noise floor, so what is being measured there is the
sample word running out of bits; above that the floor rises with unity
slope, i.e. one fixed analogue noise being divided down. The analogue
stage is reachable only over the HID interface, which is what the
vendor's own application uses.

I have the protocol. It was reverse engineered from captures of the
vendor application's traffic, the same way sound/usb/mixer_scarlett2.c
describes in its header. Frames are 15 bytes:

  22 33 | 20 01 01 | target | property | s32 big endian | CRC | 66 77

with CRC-16/MODBUS over bytes 2..10, stored big endian. Rebuilding
every frame of a capture from the decoded fields reproduces all 2619 of
them byte for byte. Inbound reports are that frame plus one pad byte.
The device stays silent until the host sends a subscription frame,
after which it reports every state change including front-panel button
presses, and it answers a "report your state" frame with a full dump.
The analogue gain of each microphone input is a single property carrying
whole decibels, 0..88, so a plain TLV_DB_SCALE fits it.

The constraint, and my question. This device accepts nothing on the
control pipe: SET_REPORT and GET_REPORT both stall with EPIPE, for
report types Output, Input and Feature alike. So the pattern used by
snd_soundblaster_e1_switch_update() in sound/usb/mixer_quirks.c, which
sends HID_REQ_SET_REPORT through snd_usb_ctl_msg(), is not available
here. The only usable transport is the interrupt endpoints of interface
4, which usbhid binds.

Would it be acceptable for a mixer quirk in sound/usb to own that
interface? Concretely: an entry in hid_ignore_list so that usbhid stays
away, the quirk claiming interface 4, an interrupt IN URB whose
completion handler parses the vendor frame, updates cached values and
calls snd_ctl_notify(), and usb_interrupt_msg() in the put callbacks.
The notification half looks like what snd_usb_mixer_status_create()
already does for the audio control interface's status endpoint. Or would
you prefer a different layout for this?

A first patch would be deliberately minimal: two controls for the
analogue gain of the two microphone inputs, with a dB TLV, and nothing
else. The line-level inputs and the outputs use index scales with a
piecewise taper, which I have measured but would rather submit
separately.

For context, an ALSA UCM configuration for the same card is already
proposed as alsa-project/alsa-ucm-conf#826. That is what would designate
the new control as the capture volume, so that userspace moves the
hardware gain instead of the digital trim.

I can post the full protocol notes and the captures if that would be
useful.

-- 
Thanks,
Mikhail Gavrilov

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

* Re: snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c)
  2026-08-12 17:10 snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c) Mikhail Gavrilov
@ 2026-08-13  7:24 ` Takashi Iwai
  0 siblings, 0 replies; 2+ messages in thread
From: Takashi Iwai @ 2026-08-13  7:24 UTC (permalink / raw)
  To: Mikhail Gavrilov
  Cc: linux-sound, tiwai, perex, g, jikos, bentiss, linux-input

On Wed, 12 Aug 2026 19:10:34 +0200,
Mikhail Gavrilov wrote:
> 
> Hello,
> 
> I would like to add ALSA mixer controls for the analogue input gain of a
> USB audio interface whose control channel is a vendor-specific HID
> interface, and I would like to agree on the shape before writing code,
> because it crosses into drivers/hid.
> 
> The device is a Topping Professional M62, USB 152a:875c. In its
> multichannel modes it presents 10 playback and 16 capture channels on
> interfaces 1 and 2, a DFU interface, and interface 4 of class 3 (HID)
> with a vendor-defined usage page, one 16-byte Input report and one
> 16-byte Output report, and no report IDs.
> 
> The problem: the microphone preamplifier gain, 0..88 dB per the
> specification, is not reachable through ALSA. The card does expose a
> 'Mic Capture Volume', but a gain ladder measured in silence shows that
> control to be a digital trim after the converter. The recorded noise
> floor is flat at about -172 dBFS at the bottom of its range, far below
> any converter's own noise floor, so what is being measured there is the
> sample word running out of bits; above that the floor rises with unity
> slope, i.e. one fixed analogue noise being divided down. The analogue
> stage is reachable only over the HID interface, which is what the
> vendor's own application uses.
> 
> I have the protocol. It was reverse engineered from captures of the
> vendor application's traffic, the same way sound/usb/mixer_scarlett2.c
> describes in its header. Frames are 15 bytes:
> 
>   22 33 | 20 01 01 | target | property | s32 big endian | CRC | 66 77
> 
> with CRC-16/MODBUS over bytes 2..10, stored big endian. Rebuilding
> every frame of a capture from the decoded fields reproduces all 2619 of
> them byte for byte. Inbound reports are that frame plus one pad byte.
> The device stays silent until the host sends a subscription frame,
> after which it reports every state change including front-panel button
> presses, and it answers a "report your state" frame with a full dump.
> The analogue gain of each microphone input is a single property carrying
> whole decibels, 0..88, so a plain TLV_DB_SCALE fits it.
> 
> The constraint, and my question. This device accepts nothing on the
> control pipe: SET_REPORT and GET_REPORT both stall with EPIPE, for
> report types Output, Input and Feature alike. So the pattern used by
> snd_soundblaster_e1_switch_update() in sound/usb/mixer_quirks.c, which
> sends HID_REQ_SET_REPORT through snd_usb_ctl_msg(), is not available
> here. The only usable transport is the interrupt endpoints of interface
> 4, which usbhid binds.
> 
> Would it be acceptable for a mixer quirk in sound/usb to own that
> interface? Concretely: an entry in hid_ignore_list so that usbhid stays
> away, the quirk claiming interface 4, an interrupt IN URB whose
> completion handler parses the vendor frame, updates cached values and
> calls snd_ctl_notify(), and usb_interrupt_msg() in the put callbacks.
> The notification half looks like what snd_usb_mixer_status_create()
> already does for the audio control interface's status endpoint. Or would
> you prefer a different layout for this?
> 
> A first patch would be deliberately minimal: two controls for the
> analogue gain of the two microphone inputs, with a dB TLV, and nothing
> else. The line-level inputs and the outputs use index scales with a
> piecewise taper, which I have measured but would rather submit
> separately.
> 
> For context, an ALSA UCM configuration for the same card is already
> proposed as alsa-project/alsa-ucm-conf#826. That is what would designate
> the new control as the capture volume, so that userspace moves the
> hardware gain instead of the digital trim.
> 
> I can post the full protocol notes and the captures if that would be
> useful.

I believe we can judge better with the comparison of the actual code.
You can try implementing PoC's for both usb-audio mixer quirk and a
HID driver, then compare which would fit better.  If either of them
looks significantly harder, you don't fulfill the implementation, of
course.

My gut feeling is that we can take it as a mixer quirk, but it really
depends on the complexity.


thanks,

Takashi

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

end of thread, other threads:[~2026-08-13  7:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 17:10 snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c) Mikhail Gavrilov
2026-08-13  7:24 ` Takashi Iwai

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