Skip to content

Instantly share code, notes, and snippets.

@shiona
Last active March 26, 2024 12:48
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shiona/def87540b87466fff315c4ac805c6766 to your computer and use it in GitHub Desktop.
Save shiona/def87540b87466fff315c4ac805c6766 to your computer and use it in GitHub Desktop.
Focusrite saffire 6 USB config for linux
pcm.frontroute {
type route
slave.pcm "dmix:USB"
ttable.0.0 1
ttable.1.1 1
}
pcm.frontusb {
type plug
slave.pcm "frontroute"
hint {
show on
description "USB front channels"
}
}
pcm.rearroute {
type route
slave.pcm "dmix:USB"
ttable.0.2 1
ttable.1.3 1
}
pcm.rearusb {
type plug
slave.pcm "rearroute"
hint {
show on
description "USB rear channels"
}
}
pcm.micaroute {
type route
slave.pcm "dsnoop:USB"
ttable.0.0 1
}
pcm.mica {
type plug
slave.pcm "micaroute"
hint {
show on
description "Focusrite Saffire Input 1"
}
}
pcm.micbroute {
type route
slave.pcm "dsnoop:USB"
ttable.0.1 1
}
pcm.micb {
type plug
slave.pcm "micbroute"
hint {
show on
description "Focusrite Saffire Input 2"
}
}
pcm.!default {
type plug
slave {
pcm "hw:1,0"
}
}
ctl.!default {
type hw
card 1
}
# Add to the end of the file. DO NOT REPLACE THE WHOLE FILE.
# File location on my system: /etc/pulse/default.pa
# the "alsa_output.usb-Focusrite_Audio_Engineering_Saffire_6USB-00.analog-surround-40"
# might be different for other users.
# Replace with the corresponding name output of the command
# pacmd list-sinks | grep 'name:'
load-module module-remap-sink sink_name=speakers remix=no master=alsa_output.usb-Focusrite_Audio_Engineering_Saffire_6USB-00.analog-surround-40 channels=2 master_channel_map=front-left,front-right channel_map=front-left,front-right
load-module module-remap-sink sink_name=headphones remix=no master=alsa_output.usb-Focusrite_Audio_Engineering_Saffire_6USB-00.analog-surround-40 channels=2 master_channel_map=rear-left,rear-right channel_map=front-left,front-right
---
sound/usb/pcm.c | 44 ++++++++++++++++++++++++++++++++++++--------
sound/usb/quirks-table.h | 24 ++++++++++++++++++++++++
2 files changed, 60 insertions(+), 8 deletions(-)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 44d178e..19e319d 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -483,7 +483,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
struct usb_host_interface *alts;
struct usb_interface_descriptor *altsd;
struct usb_interface *iface;
- int err;
+ int err, need_init, i;
iface = usb_ifnum_to_if(dev, fmt->iface);
if (WARN_ON(!iface))
@@ -498,12 +498,26 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
/* close the old interface */
if (subs->interface >= 0 && subs->interface != fmt->iface) {
- err = usb_set_interface(subs->dev, subs->interface, 0);
- if (err < 0) {
- dev_err(&dev->dev,
- "%d:%d: return to setting 0 failed (%d)\n",
- fmt->iface, fmt->altsetting, err);
- return -EIO;
+
+ need_init = iface->cur_altsetting != alts;
+
+ if (need_init) {
+ err = usb_set_interface(dev, fmt->iface, fmt->altsetting);
+ if (err < 0) {
+ dev_err(&dev->dev,
+ "%d:%d: usb_set_interface failed (%d)\n",
+ fmt->iface, fmt->altsetting, err);
+ return -EIO;
+ }
+ dev_dbg(&dev->dev, "setting usb interface %d:%d\n",
+ fmt->iface, fmt->altsetting);
+ }
+
+ for (i = 0; i < alts->desc.bNumEndpoints; ++i) {
+ if (alts->endpoint[i].desc.bEndpointAddress == fmt->endpoint)
+ alts->endpoint[i].enabled = 1;
+ else if (need_init)
+ alts->endpoint[i].enabled = 0;
}
subs->interface = -1;
subs->altset_idx = 0;
@@ -1241,12 +1255,26 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
{
struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
struct snd_usb_substream *subs = &as->substream[direction];
+ struct usb_interface *iface;
+ struct usb_host_interface *cur_alts;
+ int i, ep_active = 0;
stop_endpoints(subs, true);
if (subs->interface >= 0 &&
!snd_usb_lock_shutdown(subs->stream->chip)) {
- usb_set_interface(subs->dev, subs->interface, 0);
+ iface = usb_ifnum_to_if(subs->dev, subs->interface);
+ cur_alts = iface->cur_altsetting;
+ for (i = 0; i < cur_alts->desc.bNumEndpoints; ++i) {
+ if (cur_alts->endpoint[i].desc.bEndpointAddress == subs->ep_num)
+ cur_alts->endpoint[i].enabled = 0;
+
+ ep_active += cur_alts->endpoint[i].enabled;
+ }
+
+ if (!ep_active)
+ usb_set_interface(subs->dev, subs->interface, 0);
+
subs->interface = -1;
snd_usb_unlock_shutdown(subs->stream->chip);
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c60a776..2670498 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2701,6 +2701,30 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
.endpoint = 0x01,
.ep_attr = USB_ENDPOINT_XFER_ISOC,
+ .maxpacksize = 0x024c,
+ .rates = SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000,
+ .rate_min = 44100,
+ .rate_max = 48000,
+ .nr_rates = 2,
+ .rate_table = (unsigned int[]) {
+ 44100, 48000
+ }
+ }
+ },
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+ .data = &(const struct audioformat) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 2,
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
+ .endpoint = 0x82,
+ .ep_attr = USB_ENDPOINT_XFER_ISOC,
+ .maxpacksize = 0x0126,
.rates = SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000,
.rate_min = 44100,
--
2.10.2
@shostakub
Copy link

shostakub commented Sep 11, 2017

Hi Shiona,

I'm not a programmer but musician who need to make work fine his Focusrite Saffire 6 USB on Linux (Ubuntu Studio 16.04). Linux recognise the interface (I can see it in QjackCtl configuration and also Patchage) but it cannot make it work anyway. I found your code and I suppose this is what I need but I don't know how. Could you mind to write the steps to follow?

Thanks in advance

@vdmann
Copy link

vdmann commented Apr 4, 2018

Hi shostakub,

The Focusrite Saffire 6 USB DAC should work right out the box on Ubuntu 17.10 with Linux kernel 4.13.0-38-generic. To check if Ubuntu recognizes your DAC use:

lsusb comand with output or similar to:

Bus 002 Device 010: ID 1235:8008 Focusrite-Novation Saffire 6

or aplay -l with output or similar to:

card 2: S6USB20 [Saffire 6USB2.0], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

Should also see some processes being made with pulseaudio server monitoring with top

@shostakub
Copy link

shostakub commented Apr 9, 2018

Hi vdmann,

Thanks for the reply. I'm using Ubuntu 16.04 with Linux kernel 4.13.0-38-generic and, as you said, Ubuntu recognizes the sound card:
Bus 001 Device 005: ID 1235:0010 Focusrite-Novation Saffire 6
and also:
card 2: USB [Saffire 6 USB], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0

Now, I'm trying to make it work in Cadence but finally it has appeared!

All the best

@realvirtuality
Copy link

Hello,

I’m struggling to use my Saffire 6 USB 1.1 with Ubuntu 18.04 (and I’m quite new to Linux).
The sound card shows up in the Settings outputs (and aplay -l, can hear sound through speakers), but not in the inputs (nor arecord -l, can’t record with Audacity).

Before I ask a linux-wizard friend of mine to help me implement your instructions, can you confirm they should solve my problem?
Thanks in advance!

@iwconfig
Copy link

iwconfig commented Sep 27, 2019

Hello, if you're on Debian you can read this: https://kernel-team.pages.debian.net/kernel-handbook/ch-common-tasks.html

You can customize it however you like, but I only wanted to apply the patch and use the default configuration, so I followed step 4.2 through 4.2.2. When you're done with 4.2.2 just install the new .deb files with dpkg. It works, input from my sound card is showing up and listed using arecord -l. Though I have yet not managed to get any actual input sound from it. At least it is recognized now with my patched kernel.

Edit: I guess this applies to Ubuntu users as well, but I could be wrong.

@LucasArvid
Copy link

Hi there,
I'm relatively new to linux and are completely lost on the process of applying this kernel patch.
I'm currently using Pop!_os so following iwconfig's debian direction isn't really possible (as far as i know).
I would highly appreciate some instruction or someone pointing me in the right direction.
Thanks in advance!

@iwconfig
Copy link

I'm currently using Pop!_os so following iwconfig's debian direction isn't really possible (as far as i know).
I would highly appreciate some instruction or someone pointing me in the right direction.

Well actually you should be able to follow the same instructions with Pop!_OS since it is based on Ubuntu which in turn is based on Debian.

Since it is based on Ubuntu you should probably follow their guide but how you do it on Debian vs Ubuntu is essentially the same. This applies to Pop!_OS as well. It seems Pop!_OS is not that much diverged from the Ubuntu base with the release version (even the code name i think?) being the same. Pop!_OS utilize Ubuntus main repositories also.

Following the Ubuntu guide you might run into dependency issues however, as there might be modified (OS specific) variations of packages following some other package naming scheme. If there is any package apt cannot find, use apt-cache seach to search for it. Search for parts of the package name as it can differ somewhat in pre/suffixes ir even name. Search strings are looked for in package descriptions also. You can even take a look in the Pop!_OS specific repository at https://apt.pop-os.org/staging/master/pool/ which is where the possible diverged packages (and names) probably is located. Other than that, make sure packages names correspond to the ones available for the Ubuntu version Pop!_OS is based on.

To check release info for which version of Ubuntu your Pop!_OS is based on, run any or all of the following in terminal:

cat /etc/*{release,version}
lsb_release -a
cat /etc/issue
cat /etc/motd

Check for some indication of Ubuntu like for example UBUNTU_CODENAME=cosmic. I think the /etc/os-release file or lsb_release -cs will suffice, but you can also tell by checking the apt repository sources placed in the /etc/apt/sources.list file

cat /etc/apt/sources.list

An example of what to check for:

                                                                                                  $.~._/\/°	
                                                                                      _.,;'-._;~}*`'½"¯°´
deb http://us.archive.ubuntu.com/ubuntu/ cosmic main restricted universe multiverse   .>Y<V>A<I>Y<V>.
                                         ¯¯¯¯¯¯\_______________                      (-_¯su((`)c}h>´~
                                                               )                     ° \ar % / ,°
deb http://apt.pop-os.org/proprietary cosmic main             (                       {´/,t*~,(
                                      ¯¯¯¯¯¯\           _____/ \______________________}{
                                             \           \ The Ubuntu release code name \
                                              \__________/¯¯¯¯¯¯¯¯¯°¯¯¯¯¯¯¯¯¯¯¯¯¯°¯¯¯¯¯¯¯¯

Official ubuntu guide: https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel
Another ubuntu guide: https://www.maketecheasier.com/build-custom-kernel-ubuntu/

Happy custom kerneling and best of luck.

(Sorry, i had too much fun with the ascii art :)
              ¯¯¯¯¯¯¯¯¯¯¯¯

@LucasArvid
Copy link

Thanks alot for the detailed response iwconfig, i'll give it a shot when i get back from work!
Hahah, dont worry about the ascii art, i was properly impressed!

Once again, thanks alot. Didnt really expect to get such detailed information.

@odinho
Copy link

odinho commented Feb 7, 2021

This quirk fix has been added to the Linux 5.9 kernel! Which means Linux 5.10 which is a LTS release has it, and should hopefully be part of most distro releases coming out this year. Notably Ubuntu 21.04 will have it, and Ubuntu 20.04 LTS will actually get this kernel backported and so should at that time hopefully magically just work.

The patch is smaller than the one above here, but hoping that's all that's needed ^_^

@iwconfig
Copy link

iwconfig commented Feb 7, 2021

Awesome, thanks for the heads up. That is wonderful news! 👍

Here's the commit for anyone interested: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=470757f5b3a46bd85741bb0d8c1fd3f21048a2af

@jcozain
Copy link

jcozain commented Oct 24, 2021

thanks for posting this. i am using ubuntu studio 21.04 and i found this interface used for very cheap. it gets recognized on plugin but only works in pulse audio. jack wont start neither ardour using alsa directly. is there anything i need to modyfy for alsa to work? i tried every sampling rate / buffer size combo available.

@shiona
Copy link
Author

shiona commented Nov 22, 2021

I'm sorry, I'm no longer using this interface and am unable to comment on how/if should work with current systems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment