[RFC PATCH 0/1] RME Babyface Pro FS driver (proprietary mode)

Ismaïl Bahloul posted 1 patch 4 weeks ago
MAINTAINERS                             |    6 +
sound/usb/Kconfig                       |   18 +
sound/usb/Makefile                      |    2 +-
sound/usb/babyfacepro/Makefile          |    2 +
sound/usb/babyfacepro/babyfacepro-ctl.c | 2782 +++++++++++++++++++++++
sound/usb/babyfacepro/babyfacepro.c     | 1449 ++++++++++++
sound/usb/babyfacepro/babyfacepro.h     |  391 ++++
7 files changed, 4649 insertions(+), 1 deletion(-)
create mode 100644 sound/usb/babyfacepro/Makefile
create mode 100644 sound/usb/babyfacepro/babyfacepro-ctl.c
create mode 100644 sound/usb/babyfacepro/babyfacepro.c
create mode 100644 sound/usb/babyfacepro/babyfacepro.h
[RFC PATCH 0/1] RME Babyface Pro FS driver (proprietary mode)
Posted by Ismaïl Bahloul 4 weeks ago
Hi,

I'm sending this as an RFC for a driver I've been working on for the
RME Babyface Pro FS in its proprietary USB mode (VID 0x2a39, PID
0x3fc0). In that mode the PCM stream runs on interrupt endpoints
(interface 5, ep 0x01 OUT / 0x82 IN) instead of the class-compliant
isochronous path, so it can't be handled as a quirk on top of
snd-usb-audio. It needs a standalone driver, and I modeled it on
snd-usb-caiaq, which is the existing in-tree precedent for
interrupt-based USB audio streaming. The driver is hardware-validated
on a real unit and the code is checkpatch, sparse and W=1 clean.

The vendor protocol (control requests, register map, front-panel
readback) was reverse-engineered from Windows USB captures and
verified bit by bit on hardware. The capture analysis, the calibrated
laws, and a userspace reference implementation live in the sibling
TuxMix repo (https://github.com/ismail-bahloul/TuxMix). This driver is
the kernel side of that effort.

What's included:

 - Interrupt-URB PCM streaming, full-duplex, 2-12 channels, S24_LE,
   9 sample rates from 32 to 192 kHz across 3 USB bandwidth classes.
 - ALSA mixer: 6 output masters and mutes, the 6x14 crosspoint routing
   matrix, 4 mic/instrument preamp gains with phantom power and PAD,
   pitch/varispeed, loopback, and a few device-specific toggles
   (AN 1>2, input link, MS processor, DIM, width, FX send).
 - Front-panel emulation. The unit has no onboard DSP for its own
   panel, so the host mirrors TotalMix's role: it translates physical
   wheel/button events into mixer writes and exposes the decoded panel
   state as read-only ALSA controls.
 - A hardware 3-band plus low-cut parametric EQ for the 4 analog-input
   strips, computed in fixed-point (no FPU use) and uploaded as
   coefficient blocks.
 - Mixer-state persistence across interface re-probes and system
   suspend/resume, because the firmware has no state readback of its
   own.

Validation: a full-duplex sweep across the whole rate x period matrix
with a signal-integrity tap, start/stop stress (30 cycles), mixer-state
restore across an interface unbind/rebind, and a mid-stream disconnect.
All of that runs through the automated regression suite kept in the
driver's development tree.

Known limitations, stated up front:

 - USB autosuspend is not supported yet. I disable it explicitly
   (usb_disable_autosuspend at probe, balanced at disconnect) rather
   than ship something untested. The front-panel poll and keepalive
   work items run continuously, and nothing pairs usb_autopm_get/put
   around the stream, so an autosuspend request could race a live
   stream. S3 suspend/resume works and is tested. Full autosuspend
   (pausing the panel/keepalive work plus autopm pairing) is a
   follow-up.
 - A few protocol items aren't fully pinned down, but they don't affect
   the shipped controls; the relevant paths are hardware-verified. They
   are documented as open in PROTOCOL.md: the preamp readback index
   semantics (0x003F vs 0x0000), a width strip-ownership edge case, and
   the exact high-frequency warping of the EQ coefficient computation
   versus TotalMix's curve.
 - The latency profile is selected at load time via the frames_per_urb
   and nurbs module params. Default is 256 frames/URB, matching
   TotalMix's 256-sample buffer; frames_per_urb=16 nurbs=16 gives a
   0.33 ms monitoring-grade floor. Changing profile currently means a
   module reload. A runtime reconfiguration (like RME's own Fireface
   USB Settings panel) is a post-merge follow-up.

This is an RFC. I'm mainly after feedback on the interrupt-URB PCM
design, the control naming and topology, the two-file split, and
whether a subdirectory (sound/usb/babyfacepro/) is the right layout.
I sent it as a single patch (4651 lines, 7 files) because that's how a
wholesale new-driver addition is usually submitted, but I can split it
into a series if that's preferred.

Thanks for reading,
Ismaïl

Ismaïl Bahloul (1):
  ALSA: usb: add RME Babyface Pro FS driver (proprietary mode)

 MAINTAINERS                             |    6 +
 sound/usb/Kconfig                       |   18 +
 sound/usb/Makefile                      |    2 +-
 sound/usb/babyfacepro/Makefile          |    2 +
 sound/usb/babyfacepro/babyfacepro-ctl.c | 2782 +++++++++++++++++++++++
 sound/usb/babyfacepro/babyfacepro.c     | 1449 ++++++++++++
 sound/usb/babyfacepro/babyfacepro.h     |  391 ++++
 7 files changed, 4649 insertions(+), 1 deletion(-)
 create mode 100644 sound/usb/babyfacepro/Makefile
 create mode 100644 sound/usb/babyfacepro/babyfacepro-ctl.c
 create mode 100644 sound/usb/babyfacepro/babyfacepro.c
 create mode 100644 sound/usb/babyfacepro/babyfacepro.h

-- 
2.55.0

Re: [RFC PATCH 0/1] RME Babyface Pro FS driver (proprietary mode)
Posted by Takashi Iwai 3 weeks, 5 days ago
On Sat, 29 Aug 2026 12:03:32 +0200,
Ismaïl Bahloul wrote:
> 
> Hi,
> 
> I'm sending this as an RFC for a driver I've been working on for the
> RME Babyface Pro FS in its proprietary USB mode (VID 0x2a39, PID
> 0x3fc0). In that mode the PCM stream runs on interrupt endpoints
> (interface 5, ep 0x01 OUT / 0x82 IN) instead of the class-compliant
> isochronous path, so it can't be handled as a quirk on top of
> snd-usb-audio. It needs a standalone driver, and I modeled it on
> snd-usb-caiaq, which is the existing in-tree precedent for
> interrupt-based USB audio streaming. The driver is hardware-validated
> on a real unit and the code is checkpatch, sparse and W=1 clean.
> 
> The vendor protocol (control requests, register map, front-panel
> readback) was reverse-engineered from Windows USB captures and
> verified bit by bit on hardware. The capture analysis, the calibrated
> laws, and a userspace reference implementation live in the sibling
> TuxMix repo (https://github.com/ismail-bahloul/TuxMix). This driver is
> the kernel side of that effort.
> 
> What's included:
> 
>  - Interrupt-URB PCM streaming, full-duplex, 2-12 channels, S24_LE,
>    9 sample rates from 32 to 192 kHz across 3 USB bandwidth classes.
>  - ALSA mixer: 6 output masters and mutes, the 6x14 crosspoint routing
>    matrix, 4 mic/instrument preamp gains with phantom power and PAD,
>    pitch/varispeed, loopback, and a few device-specific toggles
>    (AN 1>2, input link, MS processor, DIM, width, FX send).
>  - Front-panel emulation. The unit has no onboard DSP for its own
>    panel, so the host mirrors TotalMix's role: it translates physical
>    wheel/button events into mixer writes and exposes the decoded panel
>    state as read-only ALSA controls.
>  - A hardware 3-band plus low-cut parametric EQ for the 4 analog-input
>    strips, computed in fixed-point (no FPU use) and uploaded as
>    coefficient blocks.
>  - Mixer-state persistence across interface re-probes and system
>    suspend/resume, because the firmware has no state readback of its
>    own.
> 
> Validation: a full-duplex sweep across the whole rate x period matrix
> with a signal-integrity tap, start/stop stress (30 cycles), mixer-state
> restore across an interface unbind/rebind, and a mid-stream disconnect.
> All of that runs through the automated regression suite kept in the
> driver's development tree.
> 
> Known limitations, stated up front:
> 
>  - USB autosuspend is not supported yet. I disable it explicitly
>    (usb_disable_autosuspend at probe, balanced at disconnect) rather
>    than ship something untested. The front-panel poll and keepalive
>    work items run continuously, and nothing pairs usb_autopm_get/put
>    around the stream, so an autosuspend request could race a live
>    stream. S3 suspend/resume works and is tested. Full autosuspend
>    (pausing the panel/keepalive work plus autopm pairing) is a
>    follow-up.
>  - A few protocol items aren't fully pinned down, but they don't affect
>    the shipped controls; the relevant paths are hardware-verified. They
>    are documented as open in PROTOCOL.md: the preamp readback index
>    semantics (0x003F vs 0x0000), a width strip-ownership edge case, and
>    the exact high-frequency warping of the EQ coefficient computation
>    versus TotalMix's curve.
>  - The latency profile is selected at load time via the frames_per_urb
>    and nurbs module params. Default is 256 frames/URB, matching
>    TotalMix's 256-sample buffer; frames_per_urb=16 nurbs=16 gives a
>    0.33 ms monitoring-grade floor. Changing profile currently means a
>    module reload. A runtime reconfiguration (like RME's own Fireface
>    USB Settings panel) is a post-merge follow-up.
> 
> This is an RFC. I'm mainly after feedback on the interrupt-URB PCM
> design, the control naming and topology, the two-file split, and
> whether a subdirectory (sound/usb/babyfacepro/) is the right layout.
> I sent it as a single patch (4651 lines, 7 files) because that's how a
> wholesale new-driver addition is usually submitted, but I can split it
> into a series if that's preferred.

Splitting would be better in general for this level of the code size,
yes.  It'll make easier to review.

About the basic code design: do we have to handle the volume
conversions in the driver?  Doing such in the kernel driver is usually
avoided as much as possible.

The use of interrupt EPs should be fine, as long as it actually works.
The implementation with work might need more consideration, though.

BTW, is the code generated / assisted via LLM?  Or is it purely
written by you alone?  If LLM is used for coding, please add a proper
Assisted-by tag.


thanks,

Takashi