LXC and passing USB audio

aghadjip

Well-Known Member
Jan 22, 2019
31
7
48
43

Hey Folks,​

Long-ish thread, TLDR trying to pass through a USB audio device to an LXC container and am having a hard time with it. It might be a pulse audio issue but looking for advice.
As to the inevitable WHY, well, because. Yes i know this is easier in a VM. I use nomachine to connect to it and i would like to pass the mic and speaker through to the container.
Setup: Proxmox 7 on supermicro server board with 64 gigs of ram (manifold)
LXC: bullseye
USB being served from a virtualhere USB server. (jetson)
USB device Plantronics Calisto 3200
followed this guidehttps://medium.com/@konpat/usb-passthrough-to-an-lxc-proxmox-15482674f11d
and it "looks" like the device is being seen.

Code:
root@manifold:~# ./vhclientx86_64 -n

root@manifold:~# ./vhclientx86_64 -t list
VirtualHere Client IPC, below are the available devices:
(Value in brackets = address, * = Auto-Use)

Jetson USB (jetson:7575)
   --> Plantronics Calisto 3200 (jetson.12413)
   --> Slim Ext Blu-ray (jetson.1243) (In-use by: (XXXXX) at 10.XXXXX)
   --> VLI Product String (jetson.2142) (In-use by: (XXXXXX) at 10.XXXXX)
root@manifold:~# ./vhclientx86_64 -t USE,jetson.12413
OK
root@manifold:~# lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 047f:014c Plantronics, Inc. Plantronics Calisto 3200******
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 05e3:0610 Genesys Logic, Inc. Hub
Bus 001 Device 004: ID 0557:2419 ATEN International Co., Ltd
Bus 001 Device 002: ID 0557:7000 ATEN International Co., Ltd Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

root@manifold:~# ls -al /dev/bus/usb/003/002
crw-rw-r-- 1 root root 189, 257 Nov 29 19:04 /dev/bus/usb/003/002

So the device is seen by the server, yay! Now to pass it through to the LXC container.
added the below to my lxc conf file.

Code:
lxc.cgroup2.devices.allow: c 189:* rwm
lxc.mount.entry: /dev/bus/usb/003/002 dev/bus/usb/003/002 none bind,optional,create=file

XXXXXX XXXXXXXX-deb11 in ~ λ sudo lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 047f:014c Plantronics, Inc. Plantronics Calisto 3200
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 05e3:0610 Genesys Logic, Inc. Hub
Bus 001 Device 004: ID 0557:2419 ATEN International Co., Ltd
Bus 001 Device 002: ID 0557:7000 ATEN International Co., Ltd Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

XXXXXX XXXXXX-deb11 in ~ λ cat /proc/asound/cards
 0 [NVidia         ]: HDA-Intel - HDA NVidia
                      HDA NVidia at 0xc5080000 irq 153
 1 [P3200          ]: USB-Audio - Plantronics Calisto 3200
                      Plantronics Plantronics Calisto 3200 at usb-vhci_hcd.0-1, full speed

YAY it looks like the LXC sees the device! However, i can not get the LXC to actually USE the device.
Code:
XXXXX on XXXXX-deb11 in ~ λ sudo aplay --list-devices
aplay: device_list:274: no soundcards found...
XXXXX on XXXXXX-deb11 in ~ λ sudo lspci -v | grep -A7 -i "audio"
lspci: Unable to load libkmod resources: error -2
17:00.1 Audio device: NVIDIA Corporation GA104 High Definition Audio Controller (rev a1)
    Subsystem: NVIDIA Corporation Device 147a
    Flags: bus master, fast devsel, latency 0, IRQ 153, NUMA node 0
    Memory at c5080000 (32-bit, non-prefetchable) [size=16K]
    Capabilities: [60] Power Management version 3
    Capabilities: [68] MSI: Enable- Count=1/1 Maskable- 64bit+
    Capabilities: [78] Express Endpoint, MSI 00
    Capabilities: [100] Advanced Error Reporting

Only my passed through GPU seems to be recognized. Any recommendations?
 
Last edited:
Adding a bit more, i use this Plantronics calisto on debian 10 laptop and works well


Code:
aplay -l  
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC257 Analog [ALC257 Analog]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 3: HDMI 0 [HDMI 0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 7: HDMI 1 [HDMI 1]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 8: HDMI 2 [HDMI 2]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 9: HDMI 3 [HDMI 3]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 10: HDMI 4 [HDMI 4]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: P3200 [Plantronics Calisto 3200], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0


Code:
cat /proc/asound/cards
 0 [PCH            ]: HDA-Intel - HDA Intel PCH
                      HDA Intel PCH at 0xdd248000 irq 158
 1 [P3200          ]: USB-Audio - Plantronics Calisto 3200
                      Plantronics Plantronics Calisto 3200 at usb-0000:00:14.0-1, full speed
 2 [Webcam         ]: USB-Audio - C922 Pro Stream Webcam
                      C922 Pro Stream Webcam at usb-0000:00:14.0-4.3.1, high speed
 3 [Dock           ]: USB-Audio - WD19 Dock
                      Dell-WD15-Dock
 
Last edited:
i guess let me start by asking has anyone successfully passed through a USB device to a container? If so, can you post your setup? Doesnt have to be an audio device, ANY usb device
 
I passthrough a USB DVB-C tuner to a Ubuntu 20.04 LTS unpriviledged container:
arch: amd64 features: nesting=1 hostname: mythtv memory: 1280 mp0: /spool/mythtv,mp=/var/lib/mythtv,mountoptions=noatime,size=0T ostype: ubuntu rootfs: qpool-zfs:subvol-100-disk-0,mountoptions=noatime,size=4G swap: 1 unprivileged: 1 lxc.idmap: u 0 100000 65535 lxc.idmap: g 0 100000 44 lxc.idmap: g 44 44 1 lxc.idmap: g 45 100045 65490 lxc.cgroup2.devices.allow: c 212:* rwm lxc.mount.entry: /dev/dvb dev/dvb none bind,create=dir 0 0
Note that I mapped the video group from the host to the video group inside the container, which both happened to be 44.
 
  • Like
Reactions: aghadjip
Got it working by passing through the ALSA device...

Code:
root@pve:~# ls -la /dev/snd/by-id/
total 0
drwxr-xr-x 2 root root  60 May 27 21:17 .
drwxr-xr-x 4 root root 160 May 27 21:17 ..
lrwxrwxrwx 1 root root  12 May 27 21:17 usb-Topping_D10_Balanced-00 -> ../controlC1

root@pve:~# ls -la /dev/snd/
total 0
drwxr-xr-x  4 root root      160 May 27 21:17 .
drwxr-xr-x 23 root root     4720 May 24 07:43 ..
drwxr-xr-x  2 root root       60 May 27 21:17 by-id
drwxr-xr-x  2 root root       60 May 27 21:17 by-path
crw-rw----  1 root audio 116,  3 May 27 21:17 controlC1
crw-rw----  1 root audio 116,  2 May 27 21:17 pcmC1D0p
crw-rw----  1 root audio 116,  1 May 24 07:43 seq

Added the following lines to my privileged container...

Code:
lxc.cgroup2.devices.allow: c 116:* rwm
lxc.mount.entry: /dev/snd dev/snd none bind,optional,create=dir

Now it shows up in my container...

Code:
root@roon:~# aplay --list-devices
**** List of PLAYBACK Hardware Devices ****
card 1: Balanced [D10 Balanced], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0
 
  • Like
Reactions: hyu
Thanks for the posts here.
I managed to make it work for me as well, and within an unpriviledged container:
Code:
unprivileged: 1
lxc.idmap: u 0 100000 1000
lxc.idmap: g 0 100000 1000
lxc.idmap: u 1000 1000 1
lxc.idmap: g 1000 1000 1
lxc.idmap: u 1001 101000 64535
lxc.idmap: g 1001 101000 64535
lxc.cgroup2.devices.allow: c 116:* rwm
lxc.mount.entry: /dev/snd dev/snd none bind,optional,create=dir

I also had to chown /dev/snd devices to the user with UID:GID 1000 which is mapped above. I also added the user to the audio group just in case.

Code:
root@pve:~# ls -la /dev/snd
total 0
drwxr-xr-x  4 root       root      160 Apr  8 19:19 .
drwxr-xr-x 21 root       root     4960 Apr  8 19:19 ..
drwxr-xr-x  2 root       root       60 Apr  8 19:19 by-id
drwxr-xr-x  2 root       root       60 Apr  8 19:19 by-path
crw-rw----  1 shareduser audio 116,  3 Apr  8 19:19 controlC0
crw-rw----  1 shareduser audio 116,  2 Apr  8 19:19 pcmC0D0p
crw-rw----  1 shareduser audio 116,  1 Apr  8 19:18 seq
crw-rw----  1 shareduser audio 116, 33 Apr  8 19:19 timer
To see the sound devices with aplay -l, I had to make sure to run the command with the same user. sudo -u shareduser aplay -l
Compose for Airsonic Advanced which has Jukebox in the settings to play music from the unpriviledged docker container in the unpriviledged LXC.
YAML:
---
version: "2.1"
services:
  airsonic-advanced:
    image: lscr.io/linuxserver/airsonic-advanced:latest
    container_name: airsonic-advanced
    environment:
      - PUID=1000
      - PGID=1000 # + ... other env mappings
    volumes:
      - ./config:/config # + ... other volumes
    ports:
      - 4040:4040
    devices:
      - /dev/snd:/dev/snd #
    restart: unless-stopped
I also had an issue that each time the device disconnected and reconnected, it was going back to being owned by root.
I wrote this udev rule, and now it's being owned by the user I needed each time.

Code:
/etc/udev/rules.d/99-usb-audio.rules
Code:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="152a", ATTRS{idProduct}=="85dd", MODE="0666", GROUP="audio", OWNER="shareduser"
I've ran into more issues. When I disconnect the usb device and reconnect it, I can still play sound from the LXC and aplay -l still displays correctly, but on the docker It shows aplay: device_list:274: no soundcards found. Only restarting the docker container seems to fix this issue.

In an attempt to fix this, I tried creating a Docker volume that maps to the /dev/snd directory.
However even though aplay -l showed the sound device, airsonic advanced was throwing exceptions.
Code:
2023-05-10 23:53:29.164 ERROR --- o.a.p.s.JukeboxLegacySubsonicService     : Error in jukebox: java.lang.IllegalArgumentException: No line matching interface SourceDataLine supporting format PCM_SIGNED 44100.0 Hz, 16 bit, stereo, 4 bytes/frame, big-endian is supported.

I thought also of updating udev rules to restart the docker container when the audio device is reconnected, but in the unpriviledged LXC udev rules don't seem to work. In the Proxmox Host for some reason I wasn't able to find out why lxc-attach also wasn't working when executing the script from the udev rule.

The only option I have thought of is to have a script that checks every 10 seconds if the device is connected or disconnected and restarts the airsonic advanced container when it reconnects.
Bash:
#!/bin/bash

DEVICE_ID="152a:85dd" # replace with your USB device id
CONTAINER_NAME="airsonic" # replace with your container name
STATE_FILE="./airsonic-state.txt" # replace with the path to your state file

# check if USB device is connected
while true
do
  # read the current state of the device from the state file
  current_state=$(cat $STATE_FILE 2>/dev/null || echo "disconnected")
  if lsusb | grep -q $DEVICE_ID
  then
    # device is connected
    #echo "USB device is connected"
    if [ "$current_state" == "disconnected" ]
    then
      # state has changed, restart the container
      #echo "Device state has changed, restarting container"
      docker restart $CONTAINER_NAME
    else
      # state has not changed
      #echo "Device state has not changed"
      :
    fi
    # update the state file
    echo "connected" > $STATE_FILE
  else
    # device is disconnected
    #echo "USB device is disconnected"
    if [ "$current_state" == "connected" ]
    then
      # state has changed, do nothing
      #echo "Device state has changed, waiting for reconnection"
      :
    else
      # state has not changed
      #echo "Device state has not changed"
      :
    fi
    # update the state file
    echo "disconnected" > $STATE_FILE
  fi
  sleep 10
done
This requires a service as well to make it run on LXC startup

sudo nano /etc/systemd/system/airsonic_advanced_restart_script.service
Bash:
[Unit]
Description=Airsonic advanced restart script

[Service]
ExecStart=/srv/compose/airsonic-advanced/restart-airsonic.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target
A long, painful and imperfect solution. But I prefer all this over having to run a VM just for this single purpose.
 
Last edited:

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!