From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
To: linux-sound@vger.kernel.org
Cc: tiwai@suse.com, perex@perex.cz, g@b4.vu, jikos@kernel.org,
bentiss@kernel.org, linux-input@vger.kernel.org
Subject: snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c)
Date: Wed, 12 Aug 2026 22:10:34 +0500 [thread overview]
Message-ID: <20260812171036.144085-1-mikhail.v.gavrilov@gmail.com> (raw)
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
next reply other threads:[~2026-08-12 17:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 17:10 Mikhail Gavrilov [this message]
2026-08-13 7:24 ` snd-usb-audio: exposing a vendor HID control channel as mixer controls (Topping M62, 152a:875c) Takashi Iwai
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=20260812171036.144085-1-mikhail.v.gavrilov@gmail.com \
--to=mikhail.v.gavrilov@gmail.com \
--cc=bentiss@kernel.org \
--cc=g@b4.vu \
--cc=jikos@kernel.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.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