Share TV tuner with LXC container

Hi everyone,

I’m getting very frustrated trying to share my TV tuner with an Ubuntu 18.04 LXC container where I installed tvheadend. I don’t seem to be able to get the configuration right so that the TV tuner shows up in LXC, even after reading and following a variety of guides, both in the Turris documentation, this forum and elsewhere. Something is definitely wrong and I can’t figure out what. Any help is appreciated. Here is the configuration I have so far:

root@turris:~# lsusb
Bus 005 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 002: ID 15f4:0131 HanfTek
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 002: ID 1058:107c Western Digital Technologies, Inc.
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub

root@turris:~# ls -l /dev/bus/usb/004
crw-rw-r--    1 root     root      189, 384 Feb 23 10:34 001
crw-rw-r--    1 root     root      189, 385 Feb 23 10:34 002

root@turris:~# ls -l /dev/dvb
drwxr-xr-x    2 root     root           140 Feb 22 19:33 adapter0
root@turris:~# ls -l /dev/dvb/adapter0
crw-rw----    1 root     44        212,   4 Feb 23 10:34 demux0
crw-rw----    1 root     44        212,   5 Feb 23 10:34 dvr0
crw-rw----    1 root     44        212,   3 Feb 23 10:34 frontend0
crw-rw----    1 root     44        212,  19 Feb 23 10:34 frontend1
crw-rw----    1 root     44        212,   7 Feb 23 10:34 net0

From this, I came up with this LXC configuration:

#TV Tuner
lxc.group.devices.allow = c 189:* rwm
lxc.mount.entry = /dev/bus/usb/004 dev/bus/usb/004 none bind,optional,create=dir 0 0

lxc.group.devices.allow = c 212:* rwm
lxc.mount.entry = /dev/dvb dev/dvb none bind,optional,create=dir 0 0

Some things to note:
– I’ve seen configs with both create=file and create=dir, which is confusing
– I’ve seen configs with both the USB primary ID and the secondary ID: /dev/bus/usb/004 vs /dev/bus/usb/004/002
– The Turris documentation advises lxc.group.devices.allow = c 188:* rwm for Omnia, which is confusing because on my device it’s 189, not 188.
– None of the instructions I’ve seen have the 0 0 after the dir instruction, yet if I don’t add them, the directories are not created in the LXC container. I’ve copied those from a working OpenMediaVault LXC container which does manage to read attached USB hard drives.
– Even though the directories are now present in the LXC container, the w_scan2 utility finds no adapter (yes, tvheadend is stopped). Tvheadend does not find any adapter either when the service is started.

I see most likely copy/paste error… There is AFAIK not lxc.group.devices.allow configuration parameter, you want to use lxc.cgroup.devices.allow.

So missing “c” character in cgroup.

I wrote some USB passthru how-to here - Turris Documentation. But not for TV USB stick but for Zigbee one. But the key principle is same.

cheers.

The exact cgroup major number is not any magical constant. There is not any single “number for Omnia”, but the number depends on your particular hardware.

For example, bellow you can see different HW having different major and minor cgroup numbers.

root@turris:~# ls -lah /dev/ttyACM0 
crw-rw-r--    1 root     20        166,   0 Feb 23 18:15 /dev/ttyACM0
root@turris:~# ls -lah /dev/ttyS0 
crw-rw-r--    1 root     root        4,  64 Feb 21 20:17 /dev/ttyS0
root@turris:~# ls -lah /dev/ttyS1
crw-rw-r--    1 root     root        4,  65 Feb 21 20:17 /dev/ttyS1
root@turris:~#

Thanks for your response. I changed it, but doesn’t appear to fix the issue, unfortunately.

Also, it should probably be corrected in this guide too if lxc.group.devices.allow is not correct:
https://doc.turris.cz/doc/en/public/tvheadend_lxc

I’ve also found the same directive, with group instead of cgroup in several responses on this forum related to tuners and other USB devices attached in LXC.

Any other suggestions please? I’m really beginning to get frustrated with this. Not sure what I’m missing.

@Pepe I see you in the edit-history of https://doc.turris.cz/doc/en/public/tvheadend_lxc . Could you pls. doublecheck it and confirm my theory that parameter name lxc.group.devices.allow is typo error and it should be replaced with lxc.cgroup.devices.allow?

Perhaps there is smth. I’m not aware of or I’m simply wrong…

Any other suggestions please?

Have you stopped and started the container after cgroup config change?
lsusb -t in container is still not showing the device?

I figured it out. I was sure that what I was missing was something basic: tvheadend was also installed in TurrisOS and was configured to start automatically. This means it was taking over the tuner so it was unavailable to the container. I stopped the tvheadend service in TurrisOS using LuCI and also disabled autostart for it. I also stopped the tvheadend service in the container and then the w_scan2 utility was able detect and use the tuner. There are some weird things I encountered along the way that is probably best to share:

– First of all, one of the reasons why I tried to run tvheadend inside an LXC container was because I couldn’t get tvheadend in TurrisOS to find any channels. The tuner – in my case Astrometa DVB T/T2/C aka HanfTek aka Rafael Micro R828D – has two chipsets inside Realtek RTL2832P and Panasonic MN88473 handling different network types. I was interested in the MN88473 in particular because it handles the DVB-C that I need. This chipset requires binary firmware to be placed in /lib/firmware, which I obtained from the OpenELEC GitHub repository.

Anyway, tvheadend running on TurrisOS properly detected the tuner frontends, both Realtek and Panasonic; dmesg showed the firmware was loaded properly, but scanning didn’t work. Furthermore, scanning with the w_scan command line utility also didn’t find anything. I put the same tuner in a computer with Linux Mint, used the same firmware from OpenELEC and used Kaffeine to scan channels. It worked. This indicated to me there is something wrong with the setup in TurrisOS and/or tvheadend on TurrisOS. Since Mint is based on Ubuntu and since I read reports on this forum about tvheadend success with Ubuntu containers, I decided to give the container approach a try.

The other reason was security. I want to expose this publicly and it’s better if it runs in a container rather than on the main router OS. Since now I managed to get it to work in tvheadend in an Ubuntu container and actually scan and find channels, it’s further indication that there’s something wrong with the tvheadend setup in TurrisOS or in the way the userspace communicates with the driver. One final note on this, when you test with w_scan you have to first stop the tvheadend service.

– The LXC configuration that worked for me was this:

#TV Tuner
lxc.cgroup.devices.allow = c 189:* rwm
lxc.mount.entry = /dev/bus/usb/004 dev/bus/usb/004 none bind,optional,create=dir 0 0

lxc.cgroup.devices.allow = c 212:* rwm
lxc.mount.entry = /dev/dvb dev/dvb none bind,optional,create=dir 0 0

Please note that there are various instructions on this forum and in the wiki that use lxc.group.devices.allow instead of lxc.cgroup.devices.allow. Also, there are also instructions that did not have the 0 0 after create=dir. Without adding this, the directories were not created for me. I needed to add the 0 0.

– After I stopped tvheadend under TurrisOS, w_scan2 in the container was able to see the tuners and find something on scan. However, tvheadend in container was still not able to see the tuners. Then I remembered reading someone saying on this forum that they had to run tvheadend as root for the scan to work.

By default tvheadend runs as user hts with group video. The devices under /dev/dvb/adapter0 are owned by root and group video. The group has rw permissions, so technically running tvheadend as hts with group video should work out of the box, but for some reason it didn’t.

I modified the tvheadend config in /etc/default/tvheadend and changed the user from hts to root and restarted the service. Now, this causes a different problem, because the service reads the user-specific config for the web interface from .hts/tvheadend in the user’s home directory and of course there is no such directory for root if you went through the setup wizard when tvheadend was running as hts. So I couldn’t log into the tvheadend web interface anymore. At this point I decided to stop the service, edit the /etc/default/tvheadend config again and change the service user from root back to hts. Once I did that and started the service again it suddenly started identifying the TV tuners. Why? I have no idea, but it worked and appears to continue to work even across container restart.

I hope this whole experience helps someone. My case applied to:
Turris OS version 3.11.14
Kernel version 4.4.199-a890a5a94ebb621f8f1720c24d12fef1-0
LXC Container Ubuntu Bionic

First, I must say good job and thanks for posting detailed report about setup!

Is the root:video ownership there also after reboot of whole turris?
The htsroot toggle seems suspicious to me.

If after reboot there would be something wrong with the permissions, please note, that you can extend the cgroups statement to hardcode the UID and GID as in the example below:

lxc.mount.entry = <src> <dest> none bind,optional,create=dir,rw,uid=123456,gid=654321 0 0

So one could define that the mount entry will be owned by the UID of root and GID of video (instead of 654321, obviously) in UR case.

But indeed, if it’s working for you, don’t change it :slight_smile:

On TurrisOS the ownership is root:root, but in the Ubuntu container it’s root:video.

root@turris:~# ls -l /dev/dvb/adapter0/
crw-r--r--    1 root     root      212,   4 Feb 24 13:30 demux0
crw-r--r--    1 root     root      212,   5 Feb 24 13:30 dvr0
crw-r--r--    1 root     root      212,   3 Feb 24 13:30 frontend0
crw-r--r--    1 root     root      212,  19 Feb 24 13:30 frontend1
crw-r--r--    1 root     root      212,   7 Feb 24 13:30 net0

root@tvh-ubuntu:~# ls -l /dev/dvb/adapter0/
total 0
crw-rw---- 1 root video 212,  4 Feb 24 15:18 demux0
crw-rw---- 1 root video 212,  5 Feb 24 15:18 dvr0
crw-rw---- 1 root video 212,  3 Feb 24 15:18 frontend0
crw-rw---- 1 root video 212, 19 Feb 24 15:18 frontend1
crw-rw---- 1 root video 212,  7 Feb 24 15:18 net0

It is preserved across router reboots, as well as container restarts. Of course, on TurrisOS tvheadend runs as root.

The article is part of community documentation. I mean the whole doc.turris.cz is community documentation, so anyone can edit it, improve it and even create articles for others.

Yes, there was an typo, which I had even in my old LXC container, which I am not using anymore. Added even missing zeros.

This can be improved and I agree. Created an issue in our Gitlab repository and will take a look.

1 Like