Skip to content

Add conditional channel count on Scarlett 18i20 version#660

Draft
dathegreat wants to merge 1 commit intoalsa-project:masterfrom
dathegreat:fix-alsa-ucm-error-for-scarlett-18i20
Draft

Add conditional channel count on Scarlett 18i20 version#660
dathegreat wants to merge 1 commit intoalsa-project:masterfrom
dathegreat:fix-alsa-ucm-error-for-scarlett-18i20

Conversation

@dathegreat
Copy link
Copy Markdown
Contributor

Resolves #559

@perexg
Copy link
Copy Markdown
Member

perexg commented Dec 15, 2025

My understanding from #559 is that the channel count also depends on the flashed firmware version. The raw USB descriptors can be matched using new syscard/type=hex substitutions (alsa-lib 1.2.15+) like used in 0515e5b .

If you can collect contents of /sys/class/sound/cardX/device/../descriptors (X = card numbers) for different firmware files, we can add proper channel matching.

@dathegreat
Copy link
Copy Markdown
Contributor Author

My understanding from #559 is that the channel count also depends on the flashed firmware version. The raw USB descriptors can be matched using new syscard/type=hex substitutions (alsa-lib 1.2.15+) like used in 0515e5b .

If you can collect contents of /sys/class/sound/cardX/device/../descriptors (X = card numbers) for different firmware files, we can add proper channel matching.

Based on what geoffreybennett said, it seems like the firmware is only relevant for the 4th gen model. I unfortunately only have a 2nd gen, so I can't provide the descriptor files myself.

@geoffreybennett do you have a 4th gen handy to get the descriptors from? (Side note, I use alsa-scarlett-gui every day. Thank you so much for all your work making Scarlett interfaces plug-and-play on Linux).

It looks like @zzzeek also mentioned having a 4th gen. Could you supply the descriptors too, zzzeek?

@zzzeek
Copy link
Copy Markdown

zzzeek commented Jan 4, 2026

Hi -

Sure, let me know if this is what you need, this file is /sys/class/sound/card0/device/../descriptors attached (as a gz to appease github)

descriptors.gz

@geoffreybennett
Copy link
Copy Markdown
Contributor

FWIW, here are the descriptors from the 2464 firmware for 18i20 4th Gen.
descriptors-2464.gz

I still think that trying to build a specific 18i20 config is a lost cause and 7283759 should be reverted.

@perexg I see your argument about having something working out of the box, and I agree. That's what the Pro Audio configuration already did for people. Now it's broken depending on the channel count of your device and there is this incomprehensible selection between HiFi and HiFi:
image
(let me know if this indicates I installed something wrong, but I see no difference in qpwgraph when I switch between those two profiles)

I think that anyone with an 18i20 is going to have their own specific use case, and the only sort of configuration that comes close to being standard/generic/usable out of the box for most people will be having Stereo Out on channels 1-2 and Mono or Stereo In on channels 1-2. Creating separate virtual devices for every pair of outputs becomes overwhelming:
image
That's not a nice out-of-the-box experience either (and why is Line Out 9-10 duplicated for Headphones 2, but there's no Headphones 1?).

Especially on the 4th Gen now, the default routing has changed, with PCM 1&2 going to line outputs 1&2 and headphones 1&2. So the Pro Audio configuration even gives you headphone output out of the box for free.

There's also no way to avoid extended tools with the big 4th Gen units - the firmware shipped with them is unusable enough that the units ship with an "Update Required" sticker over the USB port.

@zzzeek
Copy link
Copy Markdown

zzzeek commented Jan 4, 2026

the 1.2.13 behavior for me is completely perfect whereas the 1.2.14/15 behavior is unusable for me. I use it with qjackctl to route the actual PCM in/out to things, I have full access to the device and that all works great with 1.2.13 (and with 1.2.14/15 explodes where I dont really know what's going on) so from my (very outside end-user) perspective I don't see what needs to be changed exactly from what 1.2.13 does.

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 4, 2026

@geoffreybennett : There's conflicting device "Line 6" with "Line 1" defined in current UCM configuration. It's the reason why you see two HiFi profiles:

ConflictingDevice [
"Line 1"
]

PipeWire shows the "internal" UCM device names (Headpone 1 / Line 1 etc.). Those names should not be ideally exposed to users - you may contact pipewire developers, why they chose this way and discuss this to get a better solution.

@zzzeek : What you mean with unusable? You cannot select "Direct" or "Pro" profiles ? I assume that you may hit the channel detection bug. In this case, pipewire might fail to probe the card.

Thank you all for the descriptors. I will give a look (I was hoping someone would show the difference between USB descriptors and analyze it to focus only on the UCM part).

Note that I'm not author of those configurations files. If there should be any correction, I'm open to it.

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 4, 2026

Difference between descriptors provided from @zzzeek and @geoffreybennett :

Diff bcdDevice 18.65 -> 19.00
--- /tmp/descriptors.txt	2026-01-04 17:41:04.830652352 +0100
+++ /tmp/descriptors-2464.txt	2026-01-04 17:41:59.178172140 +0100
@@ -7,7 +7,7 @@
 0x40,        // bMaxPacketSize0 64
 0x35, 0x12,  // idVendor 0x1235
 0x1D, 0x82,  // idProduct 0x821D
-0x5F, 0x09,  // bcdDevice 18.65
+0xA0, 0x09,  // bcdDevice 19.00
 0x01,        // iManufacturer (String Index)
 0x03,        // iProduct (String Index)
 0x02,        // iSerialNumber (String Index)
@@ -15,7 +15,7 @@
 
 0x09,        // bLength
 0x02,        // bDescriptorType (Configuration)
-0x83, 0x02,  // wTotalLength 643
+0xA4, 0x02,  // wTotalLength 676
 0x06,        // bNumInterfaces 6
 0x01,        // bConfigurationValue
 0x09,        // iConfiguration (String Index)
@@ -39,7 +39,7 @@
 0x24,        // bDescriptorType (See Next Line)
 0x01,        // bDescriptorSubtype (CS_INTERFACE -> HEADER)
 0x00, 0x02,  // bcdADC 2.00
-0x08, 0xBF,  // wTotalLength 48904
+0x08, 0xE0,  // wTotalLength 57352
 0x00,        // binCollection 0x00
 0x00,        // baInterfaceNr 0
 
@@ -55,10 +55,14 @@
 0x24,        // bDescriptorType (See Next Line)
 0x0A,        // bDescriptorSubtype Unknown
 0x2B, 0x00, 0x07, 0x00, 0x0C, 
-0x0A,        // bLength
+0x08,        // bLength
+0x24,        // bDescriptorType (See Next Line)
+0x0A,        // bDescriptorSubtype Unknown
+0x2C, 0x00, 0x07, 0x00, 0x0D, 
+0x0B,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x0B,        // bDescriptorSubtype Unknown
-0x28, 0x03, 0x29, 0x2A, 0x2B, 0x03, 0x08, 
+0x28, 0x04, 0x29, 0x2A, 0x2B, 0x2C, 0x03, 0x08, 
 0x11,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> INPUT_TERMINAL)
@@ -66,10 +70,10 @@
 0x01, 0x01,  // wTerminalType (USB Streaming)
 0x00,        // bAssocTerminal
 0x28,        // bNrChannels 40
-0x18, 0x00,  // wChannelConfig (Low Freq Enh,Left Surround)
+0x1A, 0x00,  // wChannelConfig (Right Front,Low Freq Enh,Left Surround)
 0x00,        // iChannelNames
 0x00,        // iTerminal
-0x00, 0x13, 0x00, 0x00, 0x06, 
+0x00, 0x14, 0x00, 0x00, 0x06, 
 0x0C,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x03,        // bDescriptorSubtype (CS_INTERFACE -> OUTPUT_TERMINAL)
@@ -86,11 +90,11 @@
 0x01, 0x02,  // wTerminalType (Microphone)
 0x00,        // bAssocTerminal
 0x28,        // bNrChannels 40
-0x14, 0x00,  // wChannelConfig (Center Front,Left Surround)
+0x1A, 0x00,  // wChannelConfig (Right Front,Low Freq Enh,Left Surround)
 0x00,        // iChannelNames
 0x00,        // iTerminal
-0x00, 0x2B, 0x00, 0x00, 0x00, 
-0x5A,        // bLength
+0x00, 0x2E, 0x00, 0x00, 0x00, 
+0x72,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x06,        // bDescriptorSubtype (CS_INTERFACE -> FEATURE_UNIT)
 0x0B,        // bUnitID
@@ -138,6 +142,18 @@
 0x00, 0x00,  // bmaControls[39] (None)
 0x00, 0x00,  // bmaControls[40] (None)
 0x00, 0x00,  // bmaControls[41] (None)
+0x00, 0x00,  // bmaControls[42] (None)
+0x00, 0x00,  // bmaControls[43] (None)
+0x00, 0x00,  // bmaControls[44] (None)
+0x00, 0x00,  // bmaControls[45] (None)
+0x00, 0x00,  // bmaControls[46] (None)
+0x00, 0x00,  // bmaControls[47] (None)
+0x00, 0x00,  // bmaControls[48] (None)
+0x00, 0x00,  // bmaControls[49] (None)
+0x00, 0x00,  // bmaControls[50] (None)
+0x00, 0x00,  // bmaControls[51] (None)
+0x00, 0x00,  // bmaControls[52] (None)
+0x00, 0x00,  // bmaControls[53] (None)
 
 0x0C,        // bLength
 0x24,        // bDescriptorType (See Next Line)
@@ -174,7 +190,7 @@
 0x02,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x13, 
+0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x14, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -188,7 +204,7 @@
 0x05,        // bDescriptorType (See Next Line)
 0x01,        // bEndpointAddress (OUT/H2D)
 0x05,        // bmAttributes (Isochronous, Async, Data EP)
-0xA0, 0x02,  // wMaxPacketSize 672
+0xD8, 0x02,  // wMaxPacketSize 728
 0x01,        // bInterval 1 (unit depends on device speed)
 
 0x08,        // bLength
@@ -214,7 +230,7 @@
 0x02,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x13, 
+0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x14, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -254,7 +270,7 @@
 0x02,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x13, 
+0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x14, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -304,7 +320,7 @@
 0x16,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x2B, 
+0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x2E, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -318,7 +334,7 @@
 0x05,        // bDescriptorType (See Next Line)
 0x81,        // bEndpointAddress (IN/D2H)
 0x25,        // bmAttributes (Isochronous, Async, Implicit Feedback EP)
-0x30, 0x02,  // wMaxPacketSize 560
+0xD8, 0x02,  // wMaxPacketSize 728
 0x01,        // bInterval 1 (unit depends on device speed)
 
 0x08,        // bLength
@@ -344,7 +360,7 @@
 0x16,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x2B, 
+0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x2E, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -384,7 +400,7 @@
 0x16,        // bTerminalLink
 0x04,        // bDelay 4
 0x01, 0x01,  // wFormatTag
-0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2B, 
+0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x2E, 
 0x0A,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x02,        // bDescriptorSubtype (CS_INTERFACE -> FORMAT_TYPE)
@@ -416,7 +432,7 @@
 0xFF,        // bInterfaceClass
 0x01,        // bInterfaceSubClass
 0x20,        // bInterfaceProtocol
-0x0F,        // iInterface (String Index)
+0x10,        // iInterface (String Index)
 
 0x07,        // bLength
 0x05,        // bDescriptorType (Endpoint)
@@ -461,13 +477,13 @@
 0x02, 0x01, 0x01, 0x00, 
 0x06,        // bLength
 0x24,        // bDescriptorType (See Next Line)
-0x02, 0x02, 0x02, 0x0E, 
+0x02, 0x02, 0x02, 0x0F, 
 0x09,        // bLength
 0x24,        // bDescriptorType (See Next Line)
 0x03, 0x01, 0x03, 0x01, 0x02, 0x01, 0x00, 
 0x09,        // bLength
 0x24,        // bDescriptorType (See Next Line)
-0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x0D, 
+0x03, 0x02, 0x04, 0x01, 0x01, 0x01, 0x0E, 
 0x09,        // bLength
 0x05,        // bDescriptorType (See Next Line)
 0x02,        // bEndpointAddress (OUT/H2D)
@@ -488,4 +504,4 @@
 0x05,        // bLength
 0x25,        // bDescriptorType (See Next Line)
 0x01, 0x01, 0x03, 
-// 661 bytes
+// 694 bytes

Used tool: https://eleccelerator.com/usbdescreqparser/

@Zzeek : Could you also provide output from /proc/asound/card2/stream0 (replace card2 with your 18i20 ALSA card)?

@zzzeek
Copy link
Copy Markdown

zzzeek commented Jan 4, 2026

Difference between descriptors provided from @zzzeek and @geoffreybennett :
Diff bcdDevice 18.65 -> 19.00

Used tool: https://eleccelerator.com/usbdescreqparser/

@Zzeek : Could you also provide output from /proc/asound/card2/stream0 (replace card2 with your 18i20 ALSA card)?

ALSA stream0 dump for Scarlett 18i20 4th Gen bcdDevice 18.65
Focusrite Scarlett 18i20 4th Gen at usb-0000:00:14.0-1, high speed : USB Audio

Playback:
  Status: Running
    Interface = 1
    Altset = 1
    Packet Size = 672
    Momentary freq = 48000 Hz (0x6.0000)
  Interface 1
    Altset 1
    Format: S32_LE
    Channels: 24
    Endpoint: 0x01 (1 OUT) (ASYNC)
    Rates: 44100, 48000
    Data packet interval: 125 us
    Bits: 24
    Sync Endpoint: 0x81 (1 IN)
    Sync EP Interface: 2
    Sync EP Altset: 1
    Implicit Feedback Mode: Yes
  Interface 1
    Altset 2
    Format: S32_LE
    Channels: 18
    Endpoint: 0x01 (1 OUT) (ASYNC)
    Rates: 88200, 96000
    Data packet interval: 125 us
    Bits: 24
    Sync Endpoint: 0x81 (1 IN)
    Sync EP Interface: 2
    Sync EP Altset: 2
    Implicit Feedback Mode: Yes
  Interface 1
    Altset 3
    Format: S32_LE
    Channels: 10
    Endpoint: 0x01 (1 OUT) (ASYNC)
    Rates: 176400, 192000
    Data packet interval: 125 us
    Bits: 24
    Channel map: FL FR FC LFE RL RR FLC FRC RC SL
    Sync Endpoint: 0x81 (1 IN)
    Sync EP Interface: 2
    Sync EP Altset: 3
    Implicit Feedback Mode: Yes

Capture:
  Status: Running
    Interface = 2
    Altset = 1
    Packet Size = 560
    Momentary freq = 48000 Hz (0x6.0000)
  Interface 2
    Altset 1
    Format: S32_LE
    Channels: 20
    Endpoint: 0x81 (1 IN) (ASYNC)
    Rates: 44100, 48000
    Data packet interval: 125 us
    Bits: 24
  Interface 2
    Altset 2
    Format: S32_LE
    Channels: 18
    Endpoint: 0x81 (1 IN) (ASYNC)
    Rates: 88200, 96000
    Data packet interval: 125 us
    Bits: 24
  Interface 2
    Altset 3
    Format: S32_LE
    Channels: 10
    Endpoint: 0x81 (1 IN) (ASYNC)
    Rates: 176400, 192000
    Data packet interval: 125 us
    Bits: 24
    Channel map: FL FR FC LFE RL RR FLC FRC RC SL

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 4, 2026

Table with channel counts (p = playback, c = capture):

Generation bcdDevice 48kHz 96kHz 192kHz Descriptors file
4th 8.fd 26p/20c 18p/18c 10p/10c descriptors-2301.gz
4th 9.5f 24p/20c 18p/18c 10p/10c descriptors-2399.gz
4th 9.7a 24p/20c 18p/18c 10p/10c descriptors-2426.gz
4th 9.7f 26p/26c 18p/18c 10p/10c descriptors-2431.gz
4th 9.92 26p/26c 18p/18c 10p/10c descriptors-2450.gz
4th 9.a0 26p/26c 18p/18c 10p/10c descriptors-2464.gz

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 4, 2026

@dathegreat : Could you also show your stream0 procfs file contents ? Just for a reference to make the above table more complete.

@geoffreybennett
Copy link
Copy Markdown
Contributor

@perexg here are all the values I could find. This seems super-difficult though; surely there's a better way?

If you think we really need a HiFi conf for all models, could we just have a simple one like this?

SectionDevice."Out1-2" {
        Comment "Line Out 1-2"

        Value {
                PlaybackPriority 200
        }
        Macro.pcm_split.SplitPCMDevice {
                Name "scarlett_18i20_stereo_out"
                Direction Playback
                HWChannels [auto-assign value]
                Channels 2
                Channel0 0
                Channel1 1
                ChannelPos0 FL
                ChannelPos1 FR
        }
}

SectionDevice."In1" {
        Comment "Mic/Line/Inst In 1"

        Value {
                CapturePriority 200
        }
        Macro.pcm_split.SplitPCMDevice {
                Name "scarlett_18i20_mono_in"
                Direction Capture
                HWChannels [auto-assign value]
                Channels 1
                Channel0 0
                ChannelPos0 MONO
        }
}

SectionDevice."In2" {
        Comment "Mic/Line/Inst In 2"

        Value {
                CapturePriority 100
        }
        Macro.pcm_split.SplitPCMDevice {
                Name "scarlett_18i20_mono_in"
                Direction Capture
                HWChannels [auto-assign value]
                Channels 1
                Channel0 1
                ChannelPos0 MONO
        }
}

SectionDevice."In1-2" {
        Comment "Mic/Line/Inst In 1-2"

        Value {
                CapturePriority 100
        }
        Macro.pcm_split.SplitPCMDevice {
                Name "scarlett_18i20_stereo_in"
                Direction Capture
                HWChannels [auto-assign value]
                Channels 2
                Channel0 0
                Channel1 1
                ChannelPos0 FL
                ChannelPos1 FR
        }
}

descriptors-2301.gz
descriptors-2399.gz
descriptors-2426.gz
descriptors-2431.gz
descriptors-2450.gz
descriptors-2464.gz

$ fcp-tool -f scarlett4-1235-821d-2301.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            8.fd
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 20 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2301.gz

$ fcp-tool -f scarlett4-1235-821d-2399.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            9.5f
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 24 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 20 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2399.gz

$ fcp-tool -f scarlett4-1235-821d-2426.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            9.7a
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 24 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 20 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2426.gz

$ fcp-tool -f scarlett4-1235-821d-2431.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            9.7f
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2431.gz

$ fcp-tool -f scarlett4-1235-821d-2450.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            9.92
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2450.gz

$ fcp-tool -f scarlett4-1235-821d-2464.bin update
$ lsusb -v -d1235: | grep bcdDevice
  bcdDevice            9.a0
$ cat /proc/asound/card0/stream0 | grep -e Playback -e Capture -e Rates -e Channels
Playback: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
Capture: Channels: 26 Rates: 44100, 48000 Channels: 18 Rates: 88200, 96000 Channels: 10 Rates: 176400, 192000
$ cat /sys/class/sound/card0/device/../descriptors | gzip > /tmp/descriptors-2464.gz

perexg pushed a commit to perexg/alsa-ucm-conf that referenced this pull request Jan 5, 2026
Link: alsa-project#660
Signed-off-by: dathegreat <d.a.thegreat123@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
perexg added a commit to perexg/alsa-ucm-conf that referenced this pull request Jan 5, 2026
Use bcdDevice number (using sysfs) to detect the right
channel count. Information is taken from the pull request
comments bellow.

Link: alsa-project#660
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 5, 2026

I updated table in #660 (comment) and created PR #675 with bcdDevice number matching to set the correct channel count. Any feedback is appreciated.

If you think we really need a HiFi conf for all models, could we just have a simple one like this?

The question is why pipewire does not offer better identifiers in qpwgraph / pulseaudio sink/source mappings. UCM does the right job with the channel split IMHO.

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 5, 2026

Also, if someone has a clue about routing (meaning) of the additional 6 channels, please, keep a note.

Also, channel mapping for 96kHz and 192kHz is missing. I would like to try create UCM configs (profiles) for those combinations, too.

perexg pushed a commit to perexg/alsa-ucm-conf that referenced this pull request Jan 5, 2026
Link: alsa-project#660
Signed-off-by: dathegreat <d.a.thegreat123@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
perexg added a commit to perexg/alsa-ucm-conf that referenced this pull request Jan 5, 2026
Use bcdDevice number (using sysfs) to detect the right
channel count. Information is taken from the pull request
comments bellow.

Link: alsa-project#660
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 6, 2026

@geoffreybennett
Copy link
Copy Markdown
Contributor

Also, if someone has a clue about routing (meaning) of the additional 6 channels, please, keep a note.

The extra 2 playback and 6 capture channels are for supporting dual-ADAT I/O (16 channels).

Why 2p/6c extra when dual-ADAT should require an 8 extra channels? It could be an artificial limitation, or maybe the hardware couldn't support more than 26 PCM channels each way, but 26 channels is enough to run 16 ADAT and 10 analogue playback channels and 16 ADAT, 8 analogue, and 2 loopback recording channels independently. You just need to reassign some of the channels away from (e.g.) headphones to ADAT.

There is no inherent meaning to the channels, only the purpose the user assigns them to in the device, either in Linux with alsa-scarlett-gui, or in Windows/Mac with Focusrite Control 2. The device remembers its configuration, and so it's a bad assumption to think that any PCM channel is going to correspond with any particular input or output.

FWIW, this is the 2464 firmware default routing for 48kHz:

image

Also, channel mapping for 96kHz and 192kHz is missing. I would like to try create UCM configs (profiles) for those combinations, too.

The firmware has independent channel maps for 96kHz and 192kHz, but I've never looked up (until just now) what those defaults are because the Linux driver always sets the the 96kHz and 192kHz routing tables equal to the 48kHz routing table upon any edit (obviously just leaving out the sinks that don't exist at the higher sample rates). The Focusrite Control 2 application does the same.

Also FWIW, here are the channel maps (format: sink <- source from the hardware's POV) directly after an erase-config. Most interestingly, the firmware defaults for the different sample rates are actually different! So once you make any change, it is not possible to get back to exactly the same firmware default settings using alsa-scarlett-gui or Focusrite Control 2.

48kHz:
PCM 1 <- Analogue 1       PCM 2 <- Analogue 2       PCM 3 <- Analogue 3       PCM 4 <- Analogue 4
PCM 5 <- Analogue 5       PCM 6 <- Analogue 6       PCM 7 <- Analogue 7       PCM 8 <- Analogue 8
PCM 9 <- PCM 1            PCM 10 <- PCM 2           PCM 11 <- S/PDIF 1        PCM 12 <- S/PDIF 2
PCM 13 <- ADAT 1          PCM 14 <- ADAT 2          PCM 15 <- ADAT 3          PCM 16 <- ADAT 4
PCM 17 <- ADAT 5          PCM 18 <- ADAT 6          PCM 19 <- ADAT 7          PCM 20 <- ADAT 8
PCM 21 <- None            PCM 22 <- None            PCM 23 <- None            PCM 24 <- None
PCM 25 <- None            PCM 26 <- None            Analogue 1 <- Mix A       Analogue 2 <- Mix B
Analogue 3 <- PCM 3       Analogue 4 <- PCM 4       Analogue 5 <- PCM 5       Analogue 6 <- PCM 6
Analogue 7 <- PCM 7       Analogue 8 <- PCM 8       Analogue 9 <- PCM 9       Analogue 10 <- PCM 10
Analogue 11 <- Mix A      Analogue 12 <- Mix B      Analogue 13 <- Mix A      Analogue 14 <- Mix B
Analogue 15 <- None       Analogue 16 <- None       S/PDIF 1 <- PCM 11        S/PDIF 2 <- PCM 12
ADAT 1 <- PCM 13          ADAT 2 <- PCM 14          ADAT 3 <- PCM 15          ADAT 4 <- PCM 16
ADAT 5 <- PCM 17          ADAT 6 <- PCM 18          ADAT 7 <- PCM 19          ADAT 8 <- PCM 20
ADAT 9 <- PCM 21          ADAT 10 <- PCM 22         ADAT 11 <- PCM 23         ADAT 12 <- PCM 24
ADAT 13 <- PCM 25         ADAT 14 <- PCM 26         ADAT 15 <- PCM 1          ADAT 16 <- PCM 2

96kHz:
PCM 1 <- Analogue 1       PCM 2 <- Analogue 2       PCM 3 <- Analogue 3       PCM 4 <- Analogue 4
PCM 5 <- Analogue 5       PCM 6 <- Analogue 6       PCM 7 <- Analogue 7       PCM 8 <- Analogue 8
PCM 9 <- PCM 1            PCM 10 <- PCM 2           PCM 11 <- S/PDIF 1        PCM 12 <- S/PDIF 2
PCM 13 <- ADAT 1          PCM 14 <- ADAT 2          PCM 15 <- ADAT 3          PCM 16 <- ADAT 4
PCM 17 <- None            PCM 18 <- None            Analogue 1 <- Mix A       Analogue 2 <- Mix B
Analogue 3 <- PCM 3       Analogue 4 <- PCM 4       Analogue 5 <- PCM 5       Analogue 6 <- PCM 6
Analogue 7 <- PCM 7       Analogue 8 <- PCM 8       Analogue 9 <- PCM 9       Analogue 10 <- PCM 10
Analogue 11 <- Mix A      Analogue 12 <- Mix B      Analogue 13 <- Mix A      Analogue 14 <- Mix B
Analogue 15 <- None       Analogue 16 <- None       S/PDIF 1 <- PCM 11        S/PDIF 2 <- PCM 12
ADAT 1 <- PCM 13          ADAT 2 <- PCM 14          ADAT 3 <- PCM 15          ADAT 4 <- PCM 16
ADAT 5 <- PCM 17          ADAT 6 <- PCM 18          ADAT 7 <- PCM 1           ADAT 8 <- PCM 2

192kHz:
PCM 1 <- Analogue 1       PCM 2 <- Analogue 2       PCM 3 <- Analogue 3       PCM 4 <- Analogue 4
PCM 5 <- Analogue 5       PCM 6 <- Analogue 6       PCM 7 <- Analogue 7       PCM 8 <- Analogue 8
PCM 9 <- PCM 1            PCM 10 <- PCM 2           Analogue 1 <- PCM 1       Analogue 2 <- PCM 2
Analogue 3 <- PCM 3       Analogue 4 <- PCM 4       Analogue 5 <- PCM 5       Analogue 6 <- PCM 6
Analogue 7 <- PCM 7       Analogue 8 <- PCM 8       Analogue 9 <- PCM 9       Analogue 10 <- PCM 10
Analogue 11 <- PCM 1      Analogue 12 <- PCM 2      Analogue 13 <- PCM 1      Analogue 14 <- PCM 2
Analogue 15 <- None       Analogue 16 <- None       S/PDIF 1 <- PCM 1         S/PDIF 2 <- PCM 2

Because these devices are so flexible, it would be much better to have a tool for users to easily set up their own profile to exactly match the configuration that they are using rather than have a generic profile that matches nobody's configuration but the person who created it.

@geoffreybennett
Copy link
Copy Markdown
Contributor

A proposal to have multiple direct profiles: PR #680 , see https://github.com/alsa-project/alsa-ucm-conf/pull/680/files#diff-4474c3b8f08283f87a7121c2f6dfec806f26eb405bd73ebc9d3256830753c8b5L97 .

I'm sorry, I don't understand what this is meant to do?

I tried to test it anyway:

$ git clone https://github.com/perexg/alsa-ucm-conf.git
$ git checkout origin/topic/direct-macro
[copy ucm and ucm2 directories to /usr/share/alsa]
$ systemctl --user restart pipewire pipewire-pulse wireplumber

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Gen [Scarlett 18i20 4th Gen], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0

$ alsaucm -c hw:0 dump text
ALSA lib ucm_cond.c:155:(if_eval_regex_match) [error.ucm] RegexMatch error (If.Condition.Regex)
ALSA lib main.c:1804:(snd_use_case_mgr_open) [error.ucm] failed to import hw:0 use case configuration -22
alsaucm: error failed to open sound card hw:0: Invalid argument

pavucontrol shows:

image

Maybe that's a step forward? It's not showing the "[ALSA UCM error]" that I was previously getting:
image

perexg added a commit to perexg/alsa-ucm-conf that referenced this pull request Jan 6, 2026
Use bcdDevice number (using sysfs) to detect the right
channel count. Information is taken from the pull request
comments bellow.

Link: alsa-project#660
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 6, 2026

I'm sorry, I don't understand what this is meant to do?

Please, retry, if you like. There was a typo in the configuration, so pipewire probably used legacy profiles. There should not be any error for the ucm dump text command. Thank you for your test and for the channel map.

It's also necessary to uncomment 96kHz and 192kHz section to make those direct profiles available -
https://github.com/alsa-project/alsa-ucm-conf/pull/680/files#diff-4474c3b8f08283f87a7121c2f6dfec806f26eb405bd73ebc9d3256830753c8b5L97 .

Because these devices are so flexible, it would be much better to have a tool for users to easily set up their own profile to exactly match the configuration that they are using rather than have a generic profile that matches nobody's configuration but the person who created it.

Right. But it would be better to have something to start with and expose all channels. And if we have UCM configuration tool in future to reduce or refine configurations for this complex hardware type, all sound cards can share one code instead maintain a specific tool for one hardware.

@geoffreybennett
Copy link
Copy Markdown
Contributor

I updated table in #660 (comment) and created PR #675 with bcdDevice number matching to set the correct channel count. Any feedback is appreciated.

If you think we really need a HiFi conf for all models, could we just have a simple one like this?

The question is why pipewire does not offer better identifiers in qpwgraph / pulseaudio sink/source mappings. UCM does the right job with the channel split IMHO.

I don't think that's the real problem? You mentioned ConflictingDevice so I tried removing that, and then I only see one HiFi configuration (and none of that "Direct1, Direct2, ..." stuff in the description). I have a vague idea of what ConflictingDevice is meant to do, but cannot figure out its relevance to the 18i20.

I have to admit I barely understand UCM, and my only experiences with it so far have been uniformly negative, even before 1.2.14 broke many users' 18i20 setups.

I can see UCM making sense for fixed-function cards, for the smallest Scarletts, and for the Vocaster One and Two. But for larger interfaces with general-purpose I/O, UCM just gets in the way.

A while back I created configurations for every Scarlett exposing every stereo output pair, and every input as mono and stereo which theoretically would be great for non-multichannel-aware applications, but the real-world usability was terrible.

My conclusion: for these larger interfaces, everyone's better off using Pro Audio, and creating virtual PipeWire/PulseAudio devices for any specific needs. The UCM2 format is, frankly, inscrutable: 548 lines of highly redundant, difficult-to-follow configuration with a less usable end-result. And, forgive me if I'm wrong, but I don't think there's even a way for users to sensibly override it with a better configuration? Since it's in /usr/share/alsa it's going to be overwritten on the next update.

image

@geoffreybennett
Copy link
Copy Markdown
Contributor

I'm sorry, I don't understand what this is meant to do?

Please, retry, if you like. There was a typo in the configuration, so pipewire probably used legacy profiles. There should not be any error for the ucm dump text command. Thank you for your test and for the channel map.

Okay, I retried and alsaucm dumptext does not fail anymore (tested on latest firmware 18i20 Gen 3 & 4; my Gen 2 is out of reach, and I don't have a Gen 1).

It's also necessary to uncomment 96kHz and 192kHz section to make those direct profiles available - https://github.com/alsa-project/alsa-ucm-conf/pull/680/files#diff-4474c3b8f08283f87a7121c2f6dfec806f26eb405bd73ebc9d3256830753c8b5L97 .

I don't understand what direct profiles are, or how to test them. I'm going on vacation soon, and won't be able to do much for the next few weeks.

Because these devices are so flexible, it would be much better to have a tool for users to easily set up their own profile to exactly match the configuration that they are using rather than have a generic profile that matches nobody's configuration but the person who created it.

Right. But it would be better to have something to start with and expose all channels.

I'm not clear on what you mean by "expose all channels"? The Pro Audio configuration already does this. Or you mean expose as individual virtual devices? That's a lot of virtual devices! For playback, it's reasonable to do stereo-only pairs of outputs, so that's 13 playback devices. Then for recording you want to support both mono and stereo recordings. That's 26+13 = 39 devices. As I said in my other message, I already created such UCM configurations, and the usability in applications is just atrocious because none of them expect to have 39 recording devices available. And still, the default firmware routing does not expose all physical channels individually.

The current 18i20 profile is already too tall to fit on my monitor, and it doesn't cover the very common use case of someone wanting to do a stereo recording, let alone a stereo recording from any pair of channels. But it does have an 8-channel virtual ADAT input (connected to the wrong inputs depending on model!) for some unknown reason.

image

And if we have UCM configuration tool in future to reduce or refine configurations for this complex hardware type, all sound cards can share one code instead maintain a specific tool for one hardware.

I don't understand what this would mean practically? By "specific tool for one hardware" you are referring to alsa-scarlett-gui? A UCM configuration tool would be a good idea, but I don't see how that would remove the need for it.

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 6, 2026

I don't understand what direct profiles are, or how to test them. I'm going on vacation soon, and won't be able to do much for the next few weeks.

UCM direct profile is identical to Pro profile created by pipewire. All channels, no remapping. The goal is to have 3 direct profiles for all channel count variants (different rates).

@brndd
Copy link
Copy Markdown
Contributor

brndd commented Jan 19, 2026

@geoffreybennett

And, forgive me if I'm wrong, but I don't think there's even a way for users to sensibly override it with a better configuration? Since it's in /usr/share/alsa it's going to be overwritten on the next update.

You can override the configuration by creating /etc/alsa/ucm2/ and matching the file structure under /usr/share/alsa/ucm2/.

@Kuroiban
Copy link
Copy Markdown

While I appreciate all the work done for this issue, I don't see any progression made on issue #588 . It was closed as an duplicate of issue issue #559 , that in it's self has a pull request into this draft. But all I see is talk about the channel count of gen 2 to gen 4. No talk about the issue I have with my gen 1 interface. While I can use a workaround mention in #588 that let's me use my interface in my DAW and many other programs, there is still a UMC error flag in shown in my KDE system settings with the device. Also I experience some problems with certain games based on Unreal Engine, that will crash on startup due to - as I assume - this error flag. I would love to see a fix to this problem, especially as the changes in the device config mentioned in the workaround seems to resolve all the the functioning problems with the device and only the error flag is tainting my experience.

@perexg
Copy link
Copy Markdown
Member

perexg commented Jan 29, 2026

@Kuroiban : Could you show your bcdDevice and channels numbers from cat /proc/asound/card2/stream0 file ? Replace ard2 with your number.

@Kuroiban
Copy link
Copy Markdown

@perexg: Sure. This is with the workaround applied, manually setting the capture channels to 18 from 20 in /usr/share/alsa/ucm2/USB-Audio/Focusrite/Scarlett-18i20.conf and Scarlett-18i20-HiFi.conf

Focusrite Scarlett 18i20 USB at usb-0000:0d:00.3-3, high speed : USB Audio

Playback:
Status: Stop
Interface 1
Altset 1
Format: S32_LE
Channels: 20
Endpoint: 0x01 (1 OUT) (ASYNC)
Rates: 44100, 48000
Data packet interval: 125 us
Bits: 24
Sync Endpoint: 0x81 (1 IN)
Sync EP Interface: 1
Sync EP Altset: 1
Implicit Feedback Mode: No
Interface 1
Altset 2
Format: S32_LE
Channels: 16
Endpoint: 0x01 (1 OUT) (ASYNC)
Rates: 44100, 48000, 88200, 96000
Data packet interval: 125 us
Bits: 24
Sync Endpoint: 0x81 (1 IN)
Sync EP Interface: 1
Sync EP Altset: 2
Implicit Feedback Mode: No

Capture:
Status: Stop
Interface 2
Altset 1
Format: S32_LE
Channels: 18
Endpoint: 0x82 (2 IN) (ASYNC)
Rates: 44100, 48000
Data packet interval: 125 us
Bits: 24
Interface 2
Altset 2
Format: S32_LE
Channels: 14
Endpoint: 0x82 (2 IN) (ASYNC)
Rates: 44100, 48000, 88200, 96000
Data packet interval: 125 us
Bits: 24
Channel map: FL FR FC LFE RL RR FLC FRC RC SL SR TC TFL TFC

@perexg perexg force-pushed the master branch 10 times, most recently from 90b4ed1 to 67998e1 Compare March 30, 2026 16:38
jglathe pushed a commit to jglathe/alsa-ucm-conf that referenced this pull request Apr 13, 2026
Link: alsa-project#660
Signed-off-by: dathegreat <d.a.thegreat123@gmail.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
jglathe pushed a commit to jglathe/alsa-ucm-conf that referenced this pull request Apr 13, 2026
Use bcdDevice number (using sysfs) to detect the right
channel count. Information is taken from the pull request
comments bellow.

Link: alsa-project#660
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ALSA UCM error for Scarlett 18i20 Gen2 with new profile introduced in 1.2.14

6 participants