Linux / DVB: Playing with a HD-901T2 (“Astrometa”) DVB-T2 USB stick

This is the successful version of a previous post, using a DVB USB stick that works, for a change.

Fix this, or it will wobble

Literally. The USB plug of this device is poorly designed, so the metal frame doesn’t attach well to female connector. As a result, every little vibration makes the USB stick disconnect and possibly reconnect to the computer. If that happens in the middle of watching (or recording) something, bad luck. See “USB disaster” below for what it looks like in the logs.

The solution is simple: Chop a USB cable, and connect the side that goes to the computer (Type A Male, typically) directly to the board. Not elegant, but reliable (with some hot glue properly used).

The trick is to spot which wire should go where. A simple multimeter can be used to figure that out, or, if you like living on the edge, rely on the coloring of the wires, which is standard. Nothing stops a cable manufacturer from swapping wires, but they rarely do. What you really want to verify is that the red wire is +5V, and the black is GND. Having the white and green wires swapped will make the board fail to work (it will be detected as low-speed device, and hence fail to enumerate) but with no permanent damage.

This is what it looked like on my board, minus hot glue that I applied afterwards (click to enlarge):

USB stick board after soldering cable to boardand a closeup:

USB stick board after soldering cable to board, closeup

Plugging in the card:

$ dmesg
[ ... ]
[ 2466.203556] usb 1-2: dvb_usb_v2: found a 'Astrometa DVB-T2' in warm state
[ 2466.287494] usb 1-2: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
[ 2466.287522] DVB: registering new adapter (Astrometa DVB-T2)
[ 2466.305556] i2c i2c-9: Added multiplexed i2c bus 10
[ 2466.305567] rtl2832 9-0010: Realtek RTL2832 successfully attached
[ 2466.310149] mn88473: module is from the staging directory, the quality is unknown, you have been warned.
[ 2466.313533] mn88473 9-0018: Panasonic MN88473 successfully attached
[ 2466.313551] usb 1-2: DVB: registering adapter 0 frontend 0 (Realtek RTL2832 (DVB-T))...
[ 2466.313718] usb 1-2: DVB: registering adapter 0 frontend 1 (Panasonic MN88473)...
[ 2466.322520] r820t 10-003a: creating new instance
[ 2466.335747] r820t 10-003a: Rafael Micro r820t successfully identified
[ 2466.335780] r820t 10-003a: attaching existing instance
[ 2466.343872] r820t 10-003a: Rafael Micro r820t successfully identified
[ 2466.351883] media: Linux media interface: v0.10
[ 2466.365085] Linux video capture interface: v2.00
[ 2466.388370] rtl2832_sdr rtl2832_sdr.1.auto: Registered as swradio0
[ 2466.388382] rtl2832_sdr rtl2832_sdr.1.auto: Realtek RTL2832 SDR attached
[ 2466.388386] rtl2832_sdr rtl2832_sdr.1.auto: SDR API is still slightly experimental and functionality changes may follow
[ 2466.395405] Registered IR keymap rc-empty
[ 2466.395640] input: Astrometa DVB-T2 as /devices/pci0000:00/0000:00:14.0/usb1/1-2/rc/rc0/input11
[ 2466.395932] rc0: Astrometa DVB-T2 as /devices/pci0000:00/0000:00:14.0/usb1/1-2/rc/rc0
[ 2466.401023] IR NEC protocol handler initialized
[ 2466.402794] IR RC5(x/sz) protocol handler initialized
[ 2466.405693] IR RC6 protocol handler initialized
[ 2466.408419] IR JVC protocol handler initialized
[ 2466.414092] IR Sharp protocol handler initialized
[ 2466.414716] IR MCE Keyboard/mouse protocol handler initialized
[ 2466.418597] input: MCE IR Keyboard/Mouse (dvb_usb_rtl28xxu) as /devices/virtual/input/input12
[ 2466.418906] usb 1-2: dvb_usb_v2: schedule remote query interval to 200 msecs
[ 2466.418972] lirc_dev: IR Remote Control driver registered, major 244
[ 2466.422821] rc rc0: lirc_dev: driver ir-lirc-codec (dvb_usb_rtl28xxu) registered at minor = 0
[ 2466.422827] IR LIRC bridge handler initialized
[ 2466.424978] IR XMP protocol handler initialized
[ 2466.426269] IR Sony protocol handler initialized
[ 2466.426274] IR SANYO protocol handler initialized
[ 2466.429076] usb 1-2: dvb_usb_v2: 'Astrometa DVB-T2' successfully initialized and connected
[ 2466.429300] usbcore: registered new interface driver dvb_usb_rtl28xxu

Seems pretty good. Judging by the device ID (15f4:0131 per lsusb), it’s exactly the device mentioned in Antti’s blog.

$ dvb-fe-tool
Device Realtek RTL2832 (DVB-T) (/dev/dvb/adapter0/frontend0) capabilities:
     CAN_FEC_1_2
     CAN_FEC_2_3
     CAN_FEC_3_4
     CAN_FEC_5_6
     CAN_FEC_7_8
     CAN_FEC_AUTO
     CAN_GUARD_INTERVAL_AUTO
     CAN_HIERARCHY_AUTO
     CAN_INVERSION_AUTO
     CAN_MUTE_TS
     CAN_QAM_16
     CAN_QAM_64
     CAN_QAM_AUTO
     CAN_QPSK
     CAN_RECOVER
     CAN_TRANSMISSION_MODE_AUTO
DVB API Version 5.10, Current v5 delivery system: DVBT
Supported delivery system:
    [DVBT]

Scanning went fine too:

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00)
Scanning frequency #2 538000000
Lock   (0x1f)
Service Ch 1, provider Idan +: digital television
Service Ch 2, provider Idan +: digital television
Service Ch 10, provider Idan +: digital television
Service Ch 33, provider Idan +: digital television
Service Ch 99, provider Idan +: digital television
Service Ch 23, provider Idan +: digital television
Service Idan+test_2, provider Idan+: digital television
WARNING  Channel Idan+test_2 (service ID 7) not found on PMT. Skipping it.
Service Aleph, provider Idan +: digital radio
Service Bet, provider Idan +: digital radio
Service Gimmel, provider Idan +: digital radio
Service Dalet, provider Idan +: digital radio
Service Moreshet, provider Idan +: digital radio
Service 88FM, provider Idan +: digital radio
Service Musica, provider Idan +: digital radio
Service Reka, provider Idan +: digital radio
Service Galatz, provider Idan +: digital radio
Service Galgalatz, provider Idan +: digital radio
Service Radios, provider Idan +: digital radio
Service Kol Barama, provider Idan +: digital radio
Service Lev HaMdina, provider Idan +: digital radio
Service CLASSICAL bu, provider Idan +: digital radio

And some info:

$ dvb-fe-tool -g
FREQUENCY = 538000000
MODULATION = QAM/16
BANDWIDTH_HZ = 8000000
INVERSION = OFF
CODE_RATE_HP = 2/3
CODE_RATE_LP = 1/2
GUARD_INTERVAL = 1/4
TRANSMISSION_MODE = 8K
HIERARCHY = NONE
DELIVERY_SYSTEM = DVBT
$ dvb-fe-tool -m
       (0x00) Signal= 92.55% C/N= 32.98dB postBER= 0
       (0x00) Signal= 92.55% C/N= 32.98dB postBER= 0
       (0x00) Signal= 92.55% C/N= 32.98dB postBER= 0
       (0x00) Signal= 92.55% C/N= 32.98dB postBER= 0
       (0x00) Signal= 92.55% C/N= 32.98dB postBER= 0

Hmmm… Why isn’t it locked? And the data doesn’t change as I move the antenna around.

On the other hand,

$ dvbv5-zap -c dvb_channel.conf -r 'Ch 10'
using demux '/dev/dvb/adapter0/demux0'
reading channels from file 'dvb_channel.conf'
service has pid type 06:  2642 2641 2640
tuning to 538000000 Hz
video pid 2625
  dvb_set_pesfilter 2625
audio pid 2626
  dvb_set_pesfilter 2626
       (0x00)
Lock   (0x1f)
Lock   (0x1f)
DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
Lock   (0x1f) Signal= 92.55% C/N= 38.67dB postBER= 0

Much better. I have a lock, and both the signal level and C/N change as I move the antenna. Actually, disconnecting the antenna and short-circuiting the input jack yields

Lock   (0x1f) Signal= 92.94% C/N= 28.19dB postBER= 1.01x10^-3

so with a momentary non-zero BER as shown above, so it looks like it’s legit.

So I have zero BER? I should see TV perfectly, then?

$ mplayer -cache 800 /dev/dvb/adapter0/dvr0
MPlayer 1.2.1 (Debian), built with gcc-5.3.1 (C) 2000-2016 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing /dev/dvb/adapter0/dvr0.
Cache fill: 16.00% (131072 bytes)   

libavformat version 56.40.101 (external)
Cache empty, consider increasing -cache and/or -cache-min. [performance issue]
TS file format detected.
Cache empty, consider increasing -cache and/or -cache-min. [performance issue]
Cache empty, consider increasing -cache and/or -cache-min. [performance issue]
Cache empty, consider increasing -cache and/or -cache-min. [performance issue]
Cache empty, consider increasing -cache and/or -cache-min. [performance issue]

Oh no. What’s really weird is that going

$ cat /dev/dvb/adapter0/dvr0 > this

and in parallel

$ ffplay this

Actually does play TV more or less live (see this post for more on ffplay in this context). But

$ mplayer this
MPlayer 1.2.1 (Debian), built with gcc-5.3.1 (C) 2000-2016 MPlayer Team
mplayer: could not connect to socket
mplayer: No such file or directory
Failed to open LIRC support. You will not be able to use your remote control.

Playing this.
libavformat version 56.40.101 (external)
TS file format detected.
VIDEO MPEG2(pid=2625) AUDIO MPA(pid=2626) NO SUBS (yet)!  PROGRAM N. 0
MPEG: FATAL: EOF while searching for sequence header.
Video: Cannot read properties.
Load subtitles in ./

No sequence header? The clip is a minute long! Googling around, I found this tip, saying maybe there’s no PAT/PMT in the stream, and suggested adding “-demuxer lavf” flags to mplayer. That turned out to be corect:

$ mplayer -demuxer lavf this

Plays the clip, but

$ mplayer -demuxer lavf -cache 800 /dev/dvb/adapter0/dvr0

still complains about the cache being empty, like before. Only difference: When I hit CTRL-C, it plays the channel for a split second and closes. So I gave up this direction for now.

In hindsight, I don’t think I every tried to copy with my previous dongle. Maybe it worked, after all, even though there was a crucial difference: I never managed to get Tvheadend to display a picture either with the previous dongle. And with this one Tvheadend works like a charm.

I will never know, as I messed it up in the end.

USB disaster

See “Fix this, or it will wobble” at the top of this post on how to fix this issue.

It can start with a few like these:

Mar 10 10:44:21 tv kernel: [ 6133.433107] rtl2832 9-0010: i2c reg read failed -32

But after some time (an hour or so of playback)  ends with a full scale spontaneous disconnection of the USB device (without me touching anything, needless to say):

Mar 11 13:48:01 tv kernel: [ 1793.806742] usb 1-4: USB disconnect, device number 7
Mar 11 13:48:02 tv tvheadend[3325]: linuxdvb: Realtek RTL2832 (DVB-T) : DVB-T #0 - FE_READ_STATUS error No such device
Mar 11 13:48:02 tv kernel: [ 1794.805814] usb 1-4: dvb_usb_v2: rc.query() failed=-110
Mar 11 13:48:02 tv kernel: [ 1794.805885] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:02 tv acpid: input device has been disconnected, fd 7
Mar 11 13:48:02 tv acpid: input device has been disconnected, fd 6
Mar 11 13:48:02 tv kernel: [ 1794.933688] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:02 tv kernel: [ 1794.933706] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:02 tv kernel: [ 1794.933713] r820t 10-003a: r820t_write: i2c wr failed=-19 reg=0c len=1: f0
Mar 11 13:48:02 tv kernel: [ 1794.933720] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:02 tv kernel: [ 1794.937964] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:03 tv kernel: [ 1795.729720] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:03 tv kernel: [ 1795.772054] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:03 tv kernel: [ 1795.772069] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:03 tv kernel: [ 1795.772077] r820t 10-003a: r820t_read: i2c rd failed=-19 reg=00 len=4: f0 e1 2b ff
Mar 11 13:48:03 tv kernel: [ 1795.774643] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:03 tv kernel: [ 1795.933712] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:04 tv kernel: [ 1796.772180] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:04 tv kernel: [ 1796.772190] r820t 10-003a: r820t_read: i2c rd failed=-19 reg=00 len=4: f0 e1 2b ff
Mar 11 13:48:04 tv kernel: [ 1796.774426] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:04 tv kernel: [ 1796.933718] rtl2832 9-0010: i2c reg read failed -19
Mar 11 13:48:05 tv kernel: [ 1797.772322] rtl2832 9-0010: i2c reg read failed -19

sometimes along with a kernel warning regarding the USB hub work thread:

Mar 11 11:25:37 tv kernel: [  480.125459] INFO: task kworker/2:1:91 blocked for more than 120 seconds.
Mar 11 11:25:37 tv kernel: [  480.125485]       Tainted: G         C OE   4.4.0-53-generic #74-Ubuntu
Mar 11 11:25:37 tv kernel: [  480.125495] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
Mar 11 11:25:37 tv kernel: [  480.125506] kworker/2:1     D ffff880270613788     0    91      2 0x00000000
Mar 11 11:25:37 tv kernel: [  480.125547] Workqueue: usb_hub_wq hub_event
Mar 11 11:25:37 tv kernel: [  480.125561]  ffff880270613788 ffff880071e34a98 ffff880270f28c80 ffff8802705f8c80
Mar 11 11:25:37 tv kernel: [  480.125581]  ffff880270614000 ffff880272614108 ffff880071e34a98 ffff880071e34000
Mar 11 11:25:37 tv kernel: [  480.125599]  ffff880071e34aa0 ffff8802706137a0 ffffffff81831f75 ffff8802751a0800
Mar 11 11:25:37 tv kernel: [  480.125619] Call Trace:
Mar 11 11:25:37 tv kernel: [  480.125645]  [<ffffffff81831f75>] schedule+0x35/0x80
Mar 11 11:25:37 tv kernel: [  480.125695]  [<ffffffffc08adaf1>] dvb_unregister_frontend+0xd1/0x130 [dvb_core]
Mar 11 11:25:37 tv kernel: [  480.125718]  [<ffffffff810c3ec0>] ? wake_atomic_t_function+0x60/0x60
Mar 11 11:25:37 tv kernel: [  480.125745]  [<ffffffffc096f41d>] dvb_usbv2_exit+0x13d/0x3c0 [dvb_usb_v2]
Mar 11 11:25:37 tv kernel: [  480.125769]  [<ffffffffc096f714>] dvb_usbv2_disconnect+0x74/0xf0 [dvb_usb_v2]

After this, “lsusb” gets stuck with no output. Something really bad happened on the USB interface.

This renders the DVB stick useless. Luckily, there’s a simple solution. If you have a soldering iron, that is.

Linux kernel: /proc/iomem-like output to kernel log during boot

In order to have something similar to /proc/iomem printed out to the console (and dmesg), this piece of code can be implanted somewhere in the kernel code (in my case it was arch/arm/mach-zynq/common.c). It may be required to add #include headers, depending on the file it’s added to.

The original code that produces /proc/iomem is at kernel/resource.c.

static struct resource *adhoc_next_resource(struct resource *p, bool sibling_only)
{
  /* Caller wants to traverse through siblings only */
  if (sibling_only)
    return p->sibling;

  if (p->child)
    return p->child;
  while (!p->sibling && p->parent)
    p = p->parent;
  return p->sibling;
}

static void print_iomem(void)
{
  struct resource *r = &iomem_resource;
  int width = r->end < 0x10000 ? 4 : 8;
  pr_info("iomem mapping:\n");
  while (r) {
    pr_info("%0*llx-%0*llx : %s\n",
             width, (unsigned long long) r->start,
	     width, (unsigned long long) r->end,
	     r->name ? r->name : "");
    r = adhoc_next_resource(r, false);
  }
}

And then call print_iomem(). The output differs only from /proc/iomem in that it lacks the indentations representing the nesting of memory regions.

This was useful for me to get a snapshot during an early stage of Linux’ boot.

Linux: How to read through all files (checking a backup)

After finishing a backup to a USB stick, I like to verify that all is in place by reading through all files. Using the “tar” utility with verbose file output seemed to be a good idea. But…

Don’t

$ tar -cv . > /dev/null

For whatever reason, the files aren’t really read. Only the names of the files are printed.

It’s a bit of a mystery to me how the optimization was possible, but the time it took to complete this was way too short (using a USB stick flash)

Do

$ tar -cv . | cat > /dev/null

This, on the other hand, forces reading through the files

Linux Device Tree: What those status = “okay” are about

There are a lot of “okay” assignments in the kernel’s device tree. For example, arch/arm/boot/dts/zynq-zed.dts starts with

/dts-v1/;
#include "zynq-7000.dtsi"

and later on there’s, among others,

&sdhci0 {
	status = "okay";
};

&uart1 {
	status = "okay";
};

&usb0 {
	status = "okay";
	dr_mode = "host";
	usb-phy = <&usb_phy0>;
};

Let’s look on the last one, relating to the usb0 label. In zynq-7000.dtsi, there’s

		usb0: usb@e0002000 {
			compatible = "xlnx,zynq-usb-2.20a", "chipidea,usb2";
			status = "disabled";
			clocks = <&clkc 28>;
			interrupt-parent = <&intc>;
			interrupts = <0 21 4>;
			reg = <0xe0002000 0x1000>;
			phy_type = "ulpi";
		};

So the “okay” assignment in zynq-zed.dts overrides the one in zynq-7000.dtsi, “disabled”.

As explained on this page, if the “status” property is present, it must be “ok” or “okay”, or the device entry node is ignored (or should be). This allows the .dtsi file to include all possible hardware entries, and keep them “disabled”, and let the .dts file including it hand-pick those required, only by changing the “status”.

And indeed, in drivers/of/base.c it says

/**
 *  of_device_is_available - check if a device is available for use
 *
 *  @device: Node to check for availability
 *
 *  Returns true if the status property is absent or set to "okay" or "ok",
 *  false otherwise
 */
bool of_device_is_available(const struct device_node *device)
{
	unsigned long flags;
	bool res;

	raw_spin_lock_irqsave(&devtree_lock, flags);
	res = __of_device_is_available(device);
	raw_spin_unlock_irqrestore(&devtree_lock, flags);
	return res;

}
EXPORT_SYMBOL(of_device_is_available);

and

/**
 *  __of_device_is_available - check if a device is available for use
 *
 *  @device: Node to check for availability, with locks already held
 *
 *  Returns true if the status property is absent or set to "okay" or "ok",
 *  false otherwise
 */
static bool __of_device_is_available(const struct device_node *device)
{
	const char *status;
	int statlen;

	if (!device)
		return false;

	status = __of_get_property(device, "status", &statlen);
	if (status == NULL)
		return true;

	if (statlen > 0) {
		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
			return true;
	}

	return false;
}

This feature was added to the kernel back in 2008 in commit 834d97d452208279edf11c57eca150360d2dd1d6, but it seems it took some time before it was actually adopted.

Note that when there’s no “status” entry, it’s treated as “okay”. This retains backward compatibility with DTS files that don’t care much about this feature.

bash: Jots on exiting the script

Trapping

Call a function (byebye in this case) just before exiting a script:

trap byebye exit

Or a command:

trap 'echo "Farewell cruel world!"' exit

It’s possible to catch various signals with “trap” as well.

Quit on error

In short: Have a

set -e

at the beginning of the script. It’s a global on-off feature, so it can be cancelled temporarily with something like

set +e
[ ... something we don't care if it fails ... ]
set -e

From bash’ man page, under the “-e” flag:

Exit immediately if a pipeline (which may consist of a single simple command), a subshell command enclosed in parentheses, or one of the commands executed as part of a command list enclosed by braces (see SHELL GRAMMAR above) exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or ││ list except the command following the final && or ││, any command in a pipeline but the last, or if the command’s return value is being inverted with !. A trap on ERR, if set, is executed before the shell exits. This option applies to the shell environment and each subshell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell.

From own testing:

  • Does quit if a function returns a non-zero value (as it says above)
  • If “set -e” appears in a file containing functions, it’s applies to the script invoking the function file (-e is global)
  • If an error occurs during a trap handler with set -e active, the trap script stops at that point (i.e. trap scripts are not exempt from set -e).

overlayroot (and permission issues) on Linux Mint 18.1

Introduction

Wanting my media center computer to maintain consistent behavior and be tolerant to sudden power outages, I looked for a way to have the root filesystem read-only. This can cause problems with programs that expect to write to all kind of files allover, and media related software has this tendency to break when things divert from exactly as expected. So overlayroot is an elegant solution, as the system behaves completely as usual, only the changes are stored in RAM, and vanish on the next boot.

Only risk: Working hard on some changes, just to discover that the system was in overlay mode, and all went poof.

My system is a Linux Mint 18.1 (”Serena”) which is a derivative of Ubuntu 16.04 (”Xenial”). It runs a 4.4.0-53-generic kernel.

Starting off

Following this excellent post:

$ sudo apt-get install overlayroot

Note that the installation generates a new initramfs in /boot with the update-initramfs command-line utility, but comparing with the old one I couldn’t find anything related to overlayroot.

Overlayroot isn’t active by default. It’s possible to edit /etc/overlayroot.conf, but since I’m planning to switch back and forth with GRUB, I might as well enable it with the Linux kernel command rather than disabling it with the same.

In order to create a GRUB2 menu entry, copy /etc/grub.d/10_linux into /etc/grub.d/15_linux_overlay, and change:

os="$1"

into

os="RAM OVERLAY $1"

but even more important, add the following line somewhere at the beginning of the file:

GRUB_CMDLINE_LINUX_DEFAULT="overlayroot=\"tmpfs:swap=0,recurse=0\" $GRUB_CMDLINE_LINUX_DEFAULT"

and run update-grub. Let’s break it down:

  • overlayroot=tmpfs:  obviously means use tmpfs for overlaying the root
  • swap=0: Disable swap. This is the default, but why rely on that
  • recurse=0: Don’t overlay any of root’s subdirectories, if mounted separately. /boot/, in my case. No reason to overlay it, as I’ve set it to mount read-only anyhow

By the way, there are empty “custom” entries in /etc/grub.d/, but since I want them exactly like the original, only with a couple of changes, copying those long scripts is more accurate.

To make this the default boot, change the GRUB_DEFAULT variable in /etc/default/grub to point to the desired index, or move 15_linux_overlay to say, 09_linux_overlay. And run update-grub, or course.

Sometimes it’s required to have SHIFT pressed when the computer boots to get the GRUB menu up, and alternative kernels appear under “Advanced options”  (it wasn’t this case, but just to have this written down). And if I’m at it, on an older system, update-grub doesn’t make any difference, but

# grub-mkconfig > /boot/grub/grub.cfg

does.

But then it didn’t work

When booting Linux with overlayroot enabled, the Avahi daemon failed to start. And indeed, trying to kick it off manually (as root):

# avahi-daemon -s
avahi-daemon: error while loading shared libraries: libavahi-common.so.3: cannot stat shared object: Permission denied

Sounds weird. Let’s look at the strace of the same command:

execve("/usr/sbin/avahi-daemon", ["avahi-daemon", "-s"], [/* 30 vars */]) = 0
brk(NULL)                               = 0x20a8000

[ ... yada yada ... ]

open("/usr/lib/x86_64-linux-gnu/libavahi-common.so.3", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@/\0\0\0\0\0\0"..., 832) = 832
fstat(3, 0x7fff3f2caaa0)                = -1 EACCES (Permission denied)
close(3)                                = 0
writev(2, [{"avahi-daemon", 12}, {": ", 2}, {"error while loading shared libra"..., 36}, {": ", 2}, {"libavahi-common.so.3", 20}, {": ", 2}, {"cannot stat shared object", 25}, {": ", 2}, {"Permission denied", 17}, {"\n", 1}], 10) = 119
exit_group(127)                         = ?
+++ exited with 127 +++

WHATWHATWHAT? It’s fine to read from the file, but fstat() is denied?

And there was a similar problem with ping:

$ ping 1.1.1.1
ping: error while loading shared libraries: libcap.so.2: cannot stat shared object: Permission denied

Hint: If I moved /bin/ping to /bin/ping2, and ran ping2 instead, it ran normally.

Let’s talk about permissions

I know four types of permissions systems:

Since I issued the command as root, POSIX permissions won’t stop me. SELinux isn’t installed at all on Linux Mint 18.1, so maybe ACL?

$ cd /usr/lib/x86_64-linux-gnu
$ ls -l libavahi-common.so.*
lrwxrwxrwx 1 root root    24 Feb  3 13:00 libavahi-common.so.3 -> libavahi-common.so.3.5.3
-rw-r--r-- 1 root root 47952 Nov 24  2015 libavahi-common.so.3.5.3

$ getfacl libavahi-common.so.3
# file: libavahi-common.so.3
# owner: root
# group: root
user::rw-
group::r--
other::r--

$ getfacl libavahi-common.so.3.5.3
# file: libavahi-common.so.3.5.3
# owner: root
# group: root
user::rw-
group::r--
other::r--

Nope, nothing fishy about these files.

And this brings me back to the major hint from above: Changing the name of the executable made a difference. What functionality is sensitive to the executable’s path? Apparmor.

This gave me a major déjà vu from SELinux: That thing that’s supposed to make your system secure, but also causes mysterious failures until you’ve had enough of it, and go

$ sudo update-rc.d apparmor remove

Reboot, and then all was fine again. I have a feeling that many others will use this same command.

What it looks like

With overlayroot up and running, I get

$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
udev                         3.9G     0  3.9G   0% /dev
tmpfs                        784M  9.5M  774M   2% /run
/dev/mapper/vg_ssd2-lv_root  118G  6.5G  106G   6% /media/root-ro
tmpfs-root                   3.9G  3.0M  3.9G   1% /media/root-rw
overlayroot                  3.9G  3.0M  3.9G   1% /
tmpfs                        3.9G  772K  3.9G   1% /dev/shm
tmpfs                        5.0M  4.0K  5.0M   1% /run/lock
tmpfs                        3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/sda1                    239M   99M  123M  45% /boot
cgmfs                        100K     0  100K   0% /run/cgmanager/fs
tmpfs                        784M   16K  784M   1% /run/user/1000

and

$ mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
udev on /dev type devtmpfs (rw,nosuid,relatime,size=3987932k,nr_inodes=996983,mode=755)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=801940k,mode=755)
/dev/mapper/vg_ssd2-lv_root on /media/root-ro type ext4 (ro,relatime,data=ordered)
tmpfs-root on /media/root-rw type tmpfs (rw,relatime)
overlayroot on / type overlay (rw,relatime,lowerdir=/media/root-ro,upperdir=/media/root-rw/overlay,workdir=/media/root-rw/overlay-workdir/_)
securityfs on /sys/kernel/security type securityfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
[...etc...]

So clearly, my SSD was mounted read-only, and used as “lowerdir”. The overlay directory is at /media/root-rw/overlay/, and the working directory (where files are prepared before going to the overlay, in order to ensure atomicity) is /media/root-rw/overlay-workdir/.

Preventing confusion

Trying to avoid confusion on whether the system is volatile or not, I added this script to the “Startup Applications” on my Cinnamon desktop (Menu > Preferences > Startup Applications):

#!/bin/bash

# Set a dedicated background for volatile (overlay) sessions

if grep -q overlayroot /proc/cmdline ; then
  /usr/bin/gsettings set org.cinnamon.desktop.background picture-uri \
    'file:///usr/local/share/wallpaper.jpg'

I put the script in /usr/local/bin/overlay-wallpaper, and the wallpaper as /usr/local/share/wallpaper.jpg. Since this script runs only when the system is volatile, this setting is gone when the system reboots. More about setting up Gnome attributes in this post.

FWIW, adding this script as a startup application resulted in a file named “.config/autostart/Special wallpaper for overlay session.desktop” which reads:

[Desktop Entry]
Type=Application
Exec=/usr/local/bin/overlay-wallpaper
X-GNOME-Autostart-enabled=true
NoDisplay=false
Hidden=false
Name[en_US]=Overlay wallpaper
Comment[en_US]=Special wallpaper for overlay session
X-GNOME-Autostart-Delay=0

Notes

  • overlayroot is a great way to tell what files are changed while the system is running. Just
    $ ls -RC on /media/root-rw/overlay/

    tells the whole story.

  • The size of tmpfs (and hence the overlay) is half the physical RAM by default. On my machine, that’s almost 4 GB, which is probably more than ever necessary. But if tmpfs becomes full, the computer will deadlock, as stated in the kernel’s documentation. Meaning: A simple program that decides to write a huge file can freeze the system completely. If that’s a problem, use some disk partition as the lowerdir, and wipe it clean (make2fs) on each boot before mounting.
  • If you want to save something permanently, it’s possible to remount the underlying root directory in read-write mode,
    $ sudo mount -o remount,rw /media/root-ro

    Note that this doesn’t disable the overlay — changes are not saved. To have something written permanently, change or create files under /media/root-ro/.
    This may or may not have an immediate effect on the currently seen root directory, depending on whether it has an entry in the overlay directory. So it’s useful mostly for minor fixes or to save something specific.

  • Every change in the file causes a copy into the overlay directory, including changes in permissions etc. If the file is deleted, a “whiteout” file is created in the respective position in the overlay, marking that it’s absent. Something like this (after deleting eli.tar.gz from my Desktop):
    $ cd /media/root-rw/overlay/home/eli/Desktop/
    $ ls -l
    total 0
    c--------- 1 root root 0, 0 Feb 21 13:48 eli.tar.gz
  • Judging by the vast amount of patches under fs/overlayfs/ in the kernel tree since v4.4 (to say, v4.10), the whole thing seems a bit shaky. On the other hand, who cares, if it messes up just pull the plug and reboot. And frankly, it works great.

Wallpaper / desktop background + other stuff on Linux Mint 18.1 / Cinnamon

Desktop wallpaper setting

Get the current one:

$ gsettings get org.cinnamon.desktop.background picture-uri
'file:///usr/share/backgrounds/linuxmint/default_background.jpg'

And set it to another:

$ gsettings set org.cinnamon.desktop.background picture-uri 'file:///usr/share/backgrounds/linuxmint/edesigner_linuxmint.png'

Notes:

  • The “file://” prefix is mandatory.
  • There also an org.gnome.desktop.background attribute. Apparently, org.cinnamon.desktop.background overrides the former.
  • For an effect on the screen, the “set” command must be run on the active console (i.e. it doesn’t work from an remote ssh session)
  • If the URI property is faulty, the actual desktop background reverts to the default, but the faulty value is shown as is with the “get” command. This is somewhat confusing. In particular, omitting the file:// prefix makes a faulty value.

A bit more with gsettings

List all keys and values related to the desktop background:

$ gsettings list-recursively org.cinnamon.desktop.background
org.cinnamon.desktop.background picture-uri 'file:///usr/share/backgrounds/linuxmint/edesigner_linuxmint.png'
org.cinnamon.desktop.background color-shading-type 'solid'
org.cinnamon.desktop.background primary-color '#000000'
org.cinnamon.desktop.background picture-options 'zoom'
org.cinnamon.desktop.background picture-opacity 100
org.cinnamon.desktop.background secondary-color '#000000'

Or org.cinnamon, for that matter

$ gsettings list-recursively org.cinnamon

And there’s also “reset” for resetting a value to its default, and “monitor”, which prints a line each time the value of a key is changing.

The “org.cinnamon.desktop.background” strings is called a “schema”. These can be listed with:

$ gsettings list-schemas

Or the list of relocatable schemas (don’t ask me what “relocatable” means):

$ gsettings list-relocatable-schemas

These schemas can be found in /usr/share/glib-2.0/schemas/. For example, the schema for the desktop background properties can be found as /usr/share/glib-2.0/schemas/org.cinnamon.desktop.background.gschema.xml.

However  the XML files are not in effect directly. Rather, it’s the compiled file, /usr/share/glib-2.0/schemas/gschemas, generated with glib-compile-schemas.

dconf

gsetting is dconf-based, and accesses ~/.config/dconf/user binary database for obtaining non-default values. To dump all values in this database, install the dconf command-line tool:

$ sudo apt-get install dconf-cli

and then

$ dconf dump /

Or shall I be more specific?

$ dconf dump /org/cinnamon/desktop/background/
[/]
picture-uri='file:///usr/share/backgrounds/linuxmint/default_background.jpg'

Note that running “gsettings reset” on a key removes it from the dconf database:

$ gsettings reset org.cinnamon.desktop.background picture-uri
$ dconf dump /org/cinnamon/desktop/background/
$

(no output)

Messing up with other Window Manager

One way to completely mess up is running /etc/X11/Xsession through an ssh -X session with another computer. This will cause an attempt to start a full desktop session on the ssh client’s  X server, where an existing desktop already exists. A whole lot of attributes will be changed, for example the wallpaper, font settings and the windows’ title bars become rock-bottom basic and ugly. Apparently, these settings are made directly on the X server, so restarting Cinnamon doesn’t help. It’s the X server that needs restarting.

So the good news is that a messup of this sort doesn’t affect the permanent setting. A simple reboot fixes this. The bad news are, of course, that a reboot is necessary. Or maybe restarting the X server will be enough. Didn’t check this option.

Why I would run /etc/X11/Xsession is a different story. If I do, it’s best not to forget the DISPLAY= assignment…

Linux / DVB: Playing with command-line utilities

General

Yet another collection of jots as I try out stuff. In this post, I’m playing with a Sin Hon DVB dongle, trying but failing to receive terrestrial TV with it. The OS is Linux Mint 18.1. I had also Kodi and Tvheadend installed on the system, but they aren’t discussed here.

There’s no coherent say here. The dongle I used  was mostly likely defective, and I got myself another model, that worked better. This post repeats some of the stages below, with the new dongle.

Install

# apt-get install dvb-tools dtv-scan-tables
# apt-get install w-scan

Note so self: Turn off tvheadend service before trying command-line utilities, as the former holds the resources, quite naturally.

Immediately after plugging in the DVB stick

Getting some general info:

$ dvb-fe-tool
Device Silicon Labs Si2168 (/dev/dvb/adapter0/frontend0) capabilities:
     CAN_2G_MODULATION
     CAN_FEC_1_2
     CAN_FEC_2_3
     CAN_FEC_3_4
     CAN_FEC_5_6
     CAN_FEC_7_8
     CAN_FEC_AUTO
     CAN_GUARD_INTERVAL_AUTO
     CAN_HIERARCHY_AUTO
     CAN_INVERSION_AUTO
     CAN_MULTISTREAM
     CAN_MUTE_TS
     CAN_QAM_16
     CAN_QAM_32
     CAN_QAM_64
     CAN_QAM_128
     CAN_QAM_256
     CAN_QAM_AUTO
     CAN_QPSK
     CAN_TRANSMISSION_MODE_AUTO
DVB API Version 5.10, Current v5 delivery system: DVBT
Supported delivery systems:
    [DVBT]
     DVBT2
     DVBC/ANNEX_A

What’s the status?

$ dvb-fe-tool -g
FREQUENCY = 0
MODULATION = QAM/AUTO
BANDWIDTH_HZ = 0
INVERSION = OFF
CODE_RATE_HP = AUTO
CODE_RATE_LP = AUTO
GUARD_INTERVAL = AUTO
TRANSMISSION_MODE = AUTO
HIERARCHY = AUTO
DELIVERY_SYSTEM = DVBT

Weird fact: dvb-fe-tool shows status output when executed immediately after tvheadend has set up the DVB stick, but not after dvbv5-scan

$ dvb-fe-tool -m
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable

Scanning for channels

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= -89.00dBm
Scanning frequency #2 538000000
Lock   (0x1f) Signal= -89.00dBm C/N= 18.75dB UCB= 0 postBER= 1.00
Service Ch 1, provider Idan +: digital television
Service Ch 2, provider Idan +: digital television
Service Ch 10, provider Idan +: digital television
Service Ch 33, provider Idan +: digital television
Service Ch 99, provider Idan +: digital television
Service Ch 23, provider Idan +: digital television
Service Idan+test_2, provider Idan+: digital television
WARNING  Channel Idan+test_2 (service ID 7) not found on PMT. Skipping it.
Service Aleph, provider Idan +: digital radio
Service Bet, provider Idan +: digital radio
Service Gimmel, provider Idan +: digital radio
Service Dalet, provider Idan +: digital radio
Service Moreshet, provider Idan +: digital radio
Service 88FM, provider Idan +: digital radio
Service Musica, provider Idan +: digital radio
Service Reka, provider Idan +: digital radio
Service Galatz, provider Idan +: digital radio
Service Galgalatz, provider Idan +: digital radio
Service Radios, provider Idan +: digital radio
Service Kol Barama, provider Idan +: digital radio
Service Lev HaMdina, provider Idan +: digital radio
Service CLASSICAL bu, provider Idan +: digital radio

A dvb_channel.conf file was created, listed at the end of this post.

Don’t get too encouraged by the channel list: It’s detected even if the signal is extremely poor. Or if something is horribly wrong. Don’t know. I never managed to get this working.

Pay more attention to the postBER=1 (or if it says something like UCB= 2686 postBER= 625x10^-3). Even more discouraging is the fact that the signal levels are the same where it locked and where it didn’t. In other words, almost all signal that arrives to the tuner is noise.

After scanning, the frequency is set, but it’s not tuned in yet:

$ dvb-fe-tool -g
FREQUENCY = 538000000
MODULATION = QAM/16
BANDWIDTH_HZ = 8000000
INVERSION = OFF
CODE_RATE_HP = 2/3
CODE_RATE_LP = AUTO
GUARD_INTERVAL = 1/4
TRANSMISSION_MODE = 8K
HIERARCHY = NONE
DELIVERY_SYSTEM = DVBT
$ dvb-fe-tool -m
ERROR    FE_READ_STATUS: Resource temporarily unavailable
ERROR    FE_READ_STATUS: Resource temporarily unavailable

The regional configuration file, /usr/share/dvb/dvb-t/il-All, is part of the dtv-scan-tables:

$ cat /usr/share/dvb/dvb-t/il-All 
# Israel, Israel Broadcasting Authority's transmitters
# Generated from list in http://www.iba.org.il/reception/
[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 514000000
	BANDWIDTH_HZ = 8000000
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = NONE
	MODULATION = QAM/16
	TRANSMISSION_MODE = 8K
	GUARD_INTERVAL = 1/4
	HIERARCHY = NONE
	INVERSION = AUTO

[CHANNEL]
	DELIVERY_SYSTEM = DVBT
	FREQUENCY = 538000000
	BANDWIDTH_HZ = 8000000
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = NONE
	MODULATION = QAM/16
	TRANSMISSION_MODE = 8K
	GUARD_INTERVAL = 1/4
	HIERARCHY = NONE
	INVERSION = AUTO

This file represents the two frequencies at which DVB-T is broadcast in Israel (same stream, different frequencies in different regions of Israel).

Watching TV

One day, when I find a proper dongle, this will work. For now, I get this:

$ dvbv5-zap -c dvb_channel.conf -r 'Ch 10'
using demux '/dev/dvb/adapter0/demux0'
reading channels from file 'dvb_channel.conf'
service has pid type 06:  2642 2641 2640
tuning to 538000000 Hz
video pid 2625
  dvb_set_pesfilter 2625
audio pid 2626
  dvb_set_pesfilter 2626
       (0x00)
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00
DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
Lock   (0x1f) C/N= 25.25dB UCB= 0 postBER= 1.00

Some explanations:

  • The ‘Ch 10′ string is the identifier found in dvb_channel.conf for Israeli Channel 10 (see full listing at the end of this post)
  • The (0x00) part says that the demodulator isn’t locked (odds are that the firmware was loaded as a result of running dvbv5-zap, so it took a short while)
  • The (0x1f) part says that all demodulator locks were obtained, and the “Lock” before says it.
  • The PostBER = 1.00 clearly indicates I have a problem, and is there reason I can’t watch anything. And by the way, BER can never exceed 0.5, because if you get more than half the bits wrong, read the NOT of all bits, and the BER will go down. So BER=1 actually means no errors. But not being a schmuck about it, it’s clear that the demodulator wants to say something’s not good.
  • UCB = 0, number of uncorrected data transport blocks so far. Zero isn’t really encouraging, as it’s most likely a result of no data blocks detected at all.

To actually see the channel, go e.g.

$ mplayer -cache 800 /dev/dvb/adapter0/dvr0

Need I say that I got nothing? Mplayer ran nicely, tried to fish some info, but never got as far as opening an image window.

By the way, the BER info capability of the si2168 chip I used was due to a feature that is due for addition in kernel 4.11 (I patched mine manually). So without that, it looks like this:

$ dvbv5-zap -c dvb_channel.conf -r 'Ch 10'
using demux '/dev/dvb/adapter0/demux0'
reading channels from file 'dvb_channel.conf'
service has pid type 06:  2642 2641 2640
tuning to 538000000 Hz
video pid 2625
  dvb_set_pesfilter 2625
audio pid 2626
  dvb_set_pesfilter 2626
       (0x00)
Lock   (0x1f) C/N= 25.50dB
Lock   (0x1f) C/N= 25.50dB
DVR interface '/dev/dvb/adapter0/dvr0' can now be opened
Lock   (0x1f) C/N= 25.50dB

Using w_scan

This is what I got in Haifa with my Sin Hon TDH601 (“HD809″). Note that I didn’t offer any hints on my location, but it managed anyhow.

$ w_scan
w_scan
w_scan version 20141122 (compiled for DVB API 5.10)
WARNING: could not guess your country. Falling back to 'DE'
guessing country 'DE', use -c <country> to override
using settings for GERMANY
DVB aerial
DVB-T Europe
scan type TERRESTRIAL, channellist 4
output format vdr-2.0
WARNING: could not guess your codepage. Falling back to 'UTF-8'
output charset 'UTF-8', use -C <charset> to override
Info: using DVB adapter auto detection.
	/dev/dvb/adapter0/frontend0 -> TERRESTRIAL "Silicon Labs Si2168": very good :-))

Using TERRESTRIAL frontend (adapter /dev/dvb/adapter0/frontend0)
-_-_-_-_ Getting frontend capabilities-_-_-_-_
Using DVB API 5.10
frontend 'Silicon Labs Si2168' supports
DVB-T2
INVERSION_AUTO
QAM_AUTO
TRANSMISSION_MODE_AUTO
GUARD_INTERVAL_AUTO
HIERARCHY_AUTO
FEC_AUTO
FREQ (42.00MHz ... 870.00MHz)
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
Scanning DVB-T...
Scanning 7MHz frequencies...
177500: (time: 00:01.719)
184500: (time: 00:03.747)
191500: (time: 00:05.803)
198500: (time: 00:07.811)
205500: (time: 00:09.819)
212500: (time: 00:11.827)
219500: (time: 00:13.831)
226500: (time: 00:15.835)
Scanning 8MHz frequencies...
474000: (time: 00:17.843)
482000: (time: 00:19.847)
490000: (time: 00:21.855)
498000: (time: 00:23.907)
506000: (time: 00:25.911)
514000: (time: 00:27.959)
522000: (time: 00:29.967)
530000: (time: 00:31.970)
538000: (time: 00:34.022)         signal ok:	QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:0)
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:0) : updating transport_stream_id: -> (0:0:2)
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:0:2) : updating network_id -> (0:4369:2)
        new transponder: (QPSK     f =      0 kHz I0B999C0D0T2G32Y0 (65314:4369:1)) 0x4000
        QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (0:4369:2) : updating original_network_id -> (65314:4369:2)
        updating transponder:
           (QAM_AUTO f = 538000 kHz I999B8C999D999T999G999Y999 (65314:4369:2)) 0x0000
        to (QAM_16   f = 538000 kHz I999B8C23D0T8G4Y0 (65314:4369:2)) 0x405A
        new transponder: (QAM_16   f =      0 kHz I999B8C23D0T8G4Y0 (8959:4369:3)) 0x405A
546000: (time: 00:35.198)
554000: (time: 00:37.250)
562000: (time: 00:39.254)
570000: (time: 00:41.306)
578000: (time: 00:43.358)
586000: (time: 00:45.414)
594000: (time: 00:47.462)
602000: (time: 00:49.514)
610000: (time: 00:51.522)
618000: (time: 00:53.574)
626000: (time: 00:55.578)
634000: (time: 00:57.586)
642000: (time: 00:59.638)
650000: (time: 01:01.641)
658000: (time: 01:03.697)
666000: (time: 01:05.701)
674000: (time: 01:07.705)
682000: (time: 01:09.753)
690000: (time: 01:11.801)
698000: (time: 01:13.857)
706000: (time: 01:15.909)
714000: (time: 01:17.913)
722000: (time: 01:19.917)
730000: (time: 01:21.969)
738000: (time: 01:24.025)
746000: (time: 01:26.073)
754000: (time: 01:28.081)
762000: (time: 01:30.085)
770000: (time: 01:32.092)
778000: (time: 01:34.096)
786000: (time: 01:36.104)
794000: (time: 01:38.108)
802000: (time: 01:40.112)
810000: (time: 01:42.164)
818000: (time: 01:44.216)
826000: (time: 01:46.220)
834000: (time: 01:48.276)
842000: (time: 01:50.328)
850000: (time: 01:52.332)
858000: (time: 01:54.384)
Scanning DVB-T2...
Scanning 7MHz frequencies...
177500: (time: 01:56.388)
184500: (time: 01:58.396)
191500: (time: 02:00.400)
198500: (time: 02:02.403)
205500: (time: 02:04.407)
212500: (time: 02:06.455)
219500: (time: 02:08.511)
226500: (time: 02:10.519)
Scanning 8MHz frequencies...
474000: (time: 02:12.571)
482000: (time: 02:14.579)
490000: (time: 02:16.583)
498000: (time: 02:18.587)
506000: (time: 02:20.591)
514000: (time: 02:22.643)
522000: (time: 02:24.695)
530000: (time: 02:26.699)
538000: skipped (already known transponder)
546000: (time: 02:28.751)
554000: (time: 02:30.755)
562000: (time: 02:32.762)
570000: (time: 02:34.766)
578000: (time: 02:36.774)
586000: (time: 02:38.778)
594000: (time: 02:40.782)
602000: (time: 02:42.786)
610000: (time: 02:44.790)
618000: (time: 02:46.842)
626000: (time: 02:48.846)
634000: (time: 02:50.850)
642000: (time: 02:52.858)
650000: (time: 02:54.862)
658000: (time: 02:56.866)
666000: (time: 02:58.874)
674000: (time: 03:00.878)
682000: (time: 03:02.881)
690000: (time: 03:04.889)
698000: (time: 03:06.893)
706000: (time: 03:08.897)
714000: (time: 03:10.901)
722000: (time: 03:12.909)
730000: (time: 03:14.917)
738000: (time: 03:16.921)
746000: (time: 03:18.929)
754000: (time: 03:20.933)
762000: (time: 03:22.937)
770000: (time: 03:24.941)
778000: (time: 03:26.945)
786000: (time: 03:28.949)
794000: (time: 03:30.957)
802000: (time: 03:32.961)
810000: (time: 03:34.964)
818000: (time: 03:36.968)
826000: (time: 03:38.976)
834000: (time: 03:41.028)
842000: (time: 03:43.080)
850000: (time: 03:45.132)
858000: (time: 03:47.184)
tune to: QAM_16   f = 538000 kHz I999B8C23D0T8G4Y0 (65314:4369:2) (time: 03:49.188)
	service = Ch 1 (Idan +)
	service = Ch 2 (Idan +)
	service = Ch 10 (Idan +)
	service = Ch 33 (Idan +)
	service = Ch 99 (Idan +)
	service = Ch 23 (Idan +)
	service = Idan+test_2 (Idan+)
	service = Aleph (Idan +)
	service = Bet (Idan +)
	service = Gimmel (Idan +)
	service = Dalet (Idan +)
	service = Moreshet (Idan +)
	service = 88FM (Idan +)
	service = Musica (Idan +)
	service = Reka (Idan +)
	service = Galatz (Idan +)
	service = Galgalatz (Idan +)
	service = Radios (Idan +)
	service = Kol Barama (Idan +)
	service = Lev HaMdina (Idan +)
	service = CLASSICAL bu (Idan +)
retrying with center_frequency = 514000000
tune to: QAM_16   f = 514000 kHz I999B8C23D0T8G4Y0 (8959:4369:3) (time: 04:02.968)
----------no signal----------
tune to: QAM_AUTO f = 514000 kHz I999B8C999D0T999G999Y0 (8959:4369:3) (time: 04:08.995)  (no signal)
----------no signal----------
(time: 04:15.019) dumping lists (20 services)
..
Ch 1;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2561=27:2562@17:0;1025:0:1:65314:2:0
Ch 2;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2593=27:2594@17,2595:0;2608,2609,2610:0:2:65314:2:0
Ch 10;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2625=27:2626@17,2627:0;2640,2641,2642:0:3:65314:2:0
Ch 33;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2657=27:2658@17:0:0:4:65314:2:0
Ch 99;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:2689=27:2690@17:0;2704:0:5:65314:2:0
Ch 23;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:3585=27:3586@17:0:0:6:65314:2:0
Aleph;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2817@17:0:0:21:65314:2:0
Bet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2833@17:0:0:22:65314:2:0
Gimmel;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2849@17:0:0:23:65314:2:0
Dalet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2865@17:0:0:24:65314:2:0
Moreshet;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2881@17:0:0:25:65314:2:0
88FM;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2897@17:0:0:26:65314:2:0
Musica;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2913@17:0:0:27:65314:2:0
Reka;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2929@17:0:0:28:65314:2:0
Galatz;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2945@17:0:0:29:65314:2:0
Galgalatz;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:2961@17:0:0:30:65314:2:0
Radios;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3057@17:0:0:36:65314:2:0
Kol Barama;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3137@17:0:0:41:65314:2:0
Lev HaMdina;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3153@17:0:0:42:65314:2:0
CLASSICAL bu;Idan +:538000:B8C23D0G4M16T8Y0:T:27500:0:3201@17:0:0:45:65314:2:0
Done, scan time: 04:15.019

The dvb_channel.conf file

As promised above, this is the dvb_channel.conf that was obtained with dvbv5-scan:

[Ch 1]
	SERVICE_ID = 1
	VIDEO_PID = 2561
	AUDIO_PID = 2562
	PID_06 = 1025
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 2]
	SERVICE_ID = 2
	VIDEO_PID = 2593
	AUDIO_PID = 2594 2595
	PID_06 = 2610 2609 2608
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 10]
	SERVICE_ID = 3
	VIDEO_PID = 2625
	AUDIO_PID = 2626 2627
	PID_06 = 2642 2641 2640
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 33]
	SERVICE_ID = 4
	VIDEO_PID = 2657
	AUDIO_PID = 2658
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 99]
	SERVICE_ID = 5
	VIDEO_PID = 2689
	AUDIO_PID = 2690
	PID_06 = 2704
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Ch 23]
	SERVICE_ID = 6
	VIDEO_PID = 3585
	AUDIO_PID = 3586
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Aleph]
	SERVICE_ID = 21
	AUDIO_PID = 2817
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Bet]
	SERVICE_ID = 22
	AUDIO_PID = 2833
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Gimmel]
	SERVICE_ID = 23
	AUDIO_PID = 2849
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Dalet]
	SERVICE_ID = 24
	AUDIO_PID = 2865
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Moreshet]
	SERVICE_ID = 25
	AUDIO_PID = 2881
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[88FM]
	SERVICE_ID = 26
	AUDIO_PID = 2897
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Musica]
	SERVICE_ID = 27
	AUDIO_PID = 2913
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Reka]
	SERVICE_ID = 28
	AUDIO_PID = 2929
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Galatz]
	SERVICE_ID = 29
	AUDIO_PID = 2945
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Galgalatz]
	SERVICE_ID = 30
	AUDIO_PID = 2961
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Radios]
	SERVICE_ID = 36
	AUDIO_PID = 3057
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Kol Barama]
	SERVICE_ID = 41
	AUDIO_PID = 3137
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[Lev HaMdina]
	SERVICE_ID = 42
	AUDIO_PID = 3153
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

[CLASSICAL bu]
	SERVICE_ID = 45
	AUDIO_PID = 3201
	FREQUENCY = 538000000
	MODULATION = QAM/16
	BANDWIDTH_HZ = 8000000
	INVERSION = AUTO
	CODE_RATE_HP = 2/3
	CODE_RATE_LP = AUTO
	GUARD_INTERVAL = 1/4
	TRANSMISSION_MODE = 8K
	HIERARCHY = NONE
	DELIVERY_SYSTEM = DVBT

This was obtained on February 8th, 2017. It’s probably going to change over time.

Linux and DVB: Failing with a Sin Hon TDH 601 / HD809 USB dongle

General

These are my jots as I attempted to use an DVB USB dongle to receive digital TV in Haifa, Israel. Spoiler: I never managed to get my dongle working properly. Maybe because it was faulty to begin with, and maybe because I missed something. It seems more like the former.

It says “HD809″ and has Vendor/Product IDs 3344/24a0 (see below). 0x3344 = Leaguer Microelectronics (Shenzhen, China), 24a0 is unknown.

Here’s what it looks like:

Sin Hon TDH601 DVB-T2 dongle

Probably a Sin Hon TDH601. According to the manufacturer, it should run with Android 4.1 with OTG on the USB plug, which according to this page means any kernel after 3.0.31. And my phone should detect the dongle, which it doesn’t. As a matter of fact, looking into Android’s kernel v4.4 (which is pretty much a plain Linux kernel) there is nothing matching the “24a0″ string under drivers/. So no.

A look inside:

Sin Hon TDH601 DVB-T2 dongle under the hood

and

Sin Hon TDH601 DVB-T2 dongle under the hood(click to enlarge)

Can you see the little short-circuit on LME2510C two pins to the upper left? And the two of Si2168′s, at the right? I don’t know if they should be there, but I know I messed up completely trying to separate them.

Back to Linux and drivers: Found the device mentioned, leading to this patch, which outlines the devices: LME2510C USB interface (a.k.a. LM04 or QQBOX, not QBOX, with drivers for Windows), Si2168-B40 demodulator, Si2157-A30 tuner. The Windows driver for non-C LME2510 appears to be the same one.

Apparently, LME2510C is a USB front-end for a tuner and a demodulator, each controller by I2C. Calling the driver by the front end surely causes some confusion. It may be useful to know, that the same pair of tuner and demodulator is used in the PCTV tripleStick (292e), so except for the LME2510C USB front end, all that applies to the 292e probably goes for the Sin Hon dongle.

Antti Palosaari’s Linux repo obtained with

$ git clone git://git.linuxtv.org/anttip/media_tree.git/

where the lme2510c_tdh601branch contains the commit from June 2016, adding the drivers/media/usb/dvb-usb-v2/lme2510.c file (not to be confused with rc-lme2510.c, which contains key maps for a remote control it seems). It requires dvb-usb-lme2510c-0.fw as a firmware file.

Not to be confused with drivers/media/usb/dvb-usb-v2/lmedm04.c, which relates to the same USB interface, but with different devices behind it.

Found 0x3344/0x1122 supported in the 3.12 kernel of Zedboard (LME’s remote control?)

Incorporation in Linux Mint 18.1

Grabbed the Linux Kernel git:

$ git clone git://kernel.ubuntu.com/ubuntu/ubuntu-xenial.git

and checked out the Ubuntu-4.4.0-53.74 tag

Copied configuration file:

$ cp /boot/config-4.4.0-53-generic .config

And on the machine itself:

$ sudo apt-get install libssl-dev
$ make modules_prepare

libssl-dev is required for one of the kernel scripts (sign-file). And running this on my own computer failed with

  CC      kernel/bounds.s
gcc: unrecognized option '-no-pie'
cc1: error: unrecognized command line option "-fstack-protector-strong"
make[1]: *** [kernel/bounds.s] Error 1
make: *** [prepare0] Error 2

(so much for a vintage distribution and compiler)

Tried to compile the directory in question:

$ make M=drivers/media/usb/dvb-usb-v2

That went through nice, however there was a complaint about missing Module.symvers, and hence the module didn’t get into the kernel with insmod.

So after patching the kernel with commit f92f72c1138e33e3a2976724e8b4bc6775b53ee8 from Antti Palosaari’s repo (creating a text patch and applying it with git am on Ubuntu’s kernel) I compiled the kernel and modules completely on the target machine

$ make -j 6 bzImage modules

And that took some time, of course. It seems like this is the only way to obtain Module.symvers.

Eventually, I went down the entire way from the lme2510c_tdh601branch in the media-tree git repo to some common point with the kernel I used (4.4.0-53-generic) and cherry-picked whatever was in the middle. This required some manual adjustments. In particular, this enabled the UCB and BER statistics collection.

Finally, the module was put in place:

# cp drivers/media/usb/dvb-usb-v2/lme2510c.ko /lib/modules/4.4.0-53-generic/kernel/drivers/media/usb/dvb-usb-v2/
# depmod -a

and plugging in the dongle was enough:

[12200.242253] usb 1-2: new high-speed USB device number 6 using xhci_hcd
[12200.371223] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x81 has invalid maxpacket 64
[12200.371235] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x1 has invalid maxpacket 64
[12200.371241] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x2 has invalid maxpacket 64
[12200.371248] usb 1-2: config 1 interface 0 altsetting 1 bulk endpoint 0x8A has invalid maxpacket 64
[12200.371681] usb 1-2: New USB device found, idVendor=3344, idProduct=24a0
[12200.371691] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=3
[12200.371697] usb 1-2: SerialNumber: 䥈児
[12201.486687] usb 1-2: dvb_usb_v2: found a 'Sin Hon TDH601' in cold state
[12201.489636] usb 1-2: dvb_usb_v2: downloading firmware from file 'dvb-usb-lme2510c-0.fw'
[12201.516925] usbcore: registered new interface driver lme2510c
[12201.549778] usb 1-2: USB disconnect, device number 6
[12201.549992] usb 1-2: dvb_usb_v2: 'Sin Hon TDH601' successfully deinitialized and disconnected
[12201.826659] usb 1-2: new high-speed USB device number 7 using xhci_hcd
[12201.955630] usb 1-2: New USB device found, idVendor=3344, idProduct=24a0
[12201.955642] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[12201.955648] usb 1-2: Product: 䝇䝇
[12201.955656] usb 1-2: Manufacturer: Leaguerme
[12201.955661] usb 1-2: SerialNumber: LMEUSBSN0001
[12201.957020] usb 1-2: dvb_usb_v2: found a 'Sin Hon TDH601' in warm state
[12201.957302] usb 1-2: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
[12201.957324] DVB: registering new adapter (Sin Hon TDH601)
[12201.972436] i2c i2c-9: Added multiplexed i2c bus 10
[12201.972444] si2168 9-0064: Silicon Labs Si2168 successfully attached
[12201.979987] si2157 10-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached
[12201.980015] usb 1-2: DVB: registering adapter 0 frontend 0 (Silicon Labs Si2168)...
[12201.980442] usb 1-2: dvb_usb_v2: 'Sin Hon TDH601' successfully initialized and connected

with lsmod’s relevant part going

Module                  Size  Used by
si2157                 16384  1
si2168                 20480  1
i2c_mux                16384  1 si2168
lme2510c               16384  0
dvb_usb_v2             36864  1 lme2510c
dvb_core              122880  1 dvb_usb_v2
rc_core                28672  1 dvb_usb_v2

The relevant device files reside in /dev/dvb/adapter0. I made them R/W accessible to all manually to begin with.

And then, when attempting to scan, I got the following in dmesg:

[13200.818391] si2168 9-0064: found a 'Silicon Labs Si2168-B40'
[13200.818461] si2168 9-0064: Direct firmware load for dvb-demod-si2168-b40-01.fw failed with error -2
[13200.818493] si2168 9-0064: Direct firmware load for dvb-demod-si2168-02.fw failed with error -2
[13200.818499] si2168 9-0064: firmware file 'dvb-demod-si2168-02.fw' not found
[13200.823201] si2157 10-0060: found a 'Silicon Labs Si2157-A30'
[13200.873313] si2157 10-0060: firmware version: 3.0.5

So I grabbed the two files from the dvb-firmware Github repo.

The firmware for the driver itself (dvb-usb-lme2510c-0.fw) was downloaded from Palosaari’s site.

Firmware for the si2168 (dvb-demod-si2168-b40-01.fw) was downloaded from here (version 4.0.25). Doesn’t seem like there’s a major difference between the revisions (in the sense that none worked for me. I tried several).

dvb-demod-si2168-02.fw is the fallback firmware for all si2168 demodulators. There’s no point using it when a specific firmware file is available.

The si2157 tuner doesn’t require any firmware file.

All firmware files were copied to /lib/firmware on the target machine.

Missing firmware symptoms

When both dvb-demod-si2168-02.fw and dvb-demod-si2168-b40-01.fw are missing or have not been loaded properly:

[ 1089.192756] si2168 9-0064: Direct firmware load for dvb-demod-si2168-b40-01.fw failed with error -2
[ 1089.193730] si2168 9-0064: please install firmware file 'dvb-demod-si2168-b40-01.fw'
[ 1089.193753] si2168 9-0064: downloading firmware from file 'dvb-demod-si2168-02.fw'
[ 1089.509845] si2168 9-0064: firmware version: B 4.0.4

And this results with something like this:

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= 0.00dBm
Scanning frequency #2 538000000
       (0x00) Signal= 0.00dBm

But with dvb-demod-si2168-02.fw loaded (and dvb-demod-si2168-b40-01.fw not present):

$ dvbv5-scan /usr/share/dvb/dvb-t/il-All
Cannot calc frequency shift. Either bandwidth/symbol-rate is unavailable (yet).
Scanning frequency #1 514000000
       (0x00) Signal= -85.00dBm
Scanning frequency #2 538000000
Lock   (0x1f) Signal= -85.00dBm C/N= 20.25dB UCB= 0 postBER= 1.00
Service Ch 1, provider Idan +: digital television
Service Ch 2, provider Idan +: digital television
[... etc ...]

The important lesson is that channels are detected without dvb-demod-si2168-b40-01.fw, only no data can be obtained (the BER is horribly high). Explained why above.

Final status

I destroyed the hardware completely when trying to fix what seemed to be a short circuit between two pins of the LME2510C chip. Unfortunately, I messed things up (fine-pitch soldering is a skill, too bad I don’t possess it), and the device isn’t detected on the USB bus properly. Or more precisely, one gets

[12135.429658] usb 1-4: new full-speed USB device number 13 using xhci_hcd
[12135.541697] usb 1-4: device descriptor read/64, error -71
[12135.757589] usb 1-4: device descriptor read/64, error -71
[12135.973634] usb 1-4: new full-speed USB device number 14 using xhci_hcd
[12136.085569] usb 1-4: device descriptor read/64, error -71
[12136.301560] usb 1-4: device descriptor read/64, error -71
[12136.517668] usb 1-4: new full-speed USB device number 15 using xhci_hcd
[12136.517909] usb 1-4: Device not responding to setup address.
[12136.721700] usb 1-4: Device not responding to setup address.
[12136.925512] usb 1-4: device not accepting address 15, error -71
[12137.037492] usb 1-4: new full-speed USB device number 16 using xhci_hcd
[12137.037709] usb 1-4: Device not responding to setup address.
[12137.241728] usb 1-4: Device not responding to setup address.
[12137.445494] usb 1-4: device not accepting address 16, error -71
[12137.445653] usb usb1-port4: unable to enumerate USB device

Raw session

A proper plug-in syslog (device is OK, and drivers and firmware in place):

[ 1175.580411] usb 1-4: new high-speed USB device number 7 using xhci_hcd
[ 1175.708790] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x81 has invalid maxpacket 64
[ 1175.708803] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x1 has invalid maxpacket 64
[ 1175.708810] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x2 has invalid maxpacket 64
[ 1175.708817] usb 1-4: config 1 interface 0 altsetting 1 bulk endpoint 0x8A has invalid maxpacket 64
[ 1175.709033] usb 1-4: New USB device found, idVendor=3344, idProduct=24a0
[ 1175.709041] usb 1-4: New USB device strings: Mfr=0, Product=0, SerialNumber=3
[ 1175.709048] usb 1-4: SerialNumber: 䥈児
[ 1175.711681] usb 1-4: dvb_usb_v2: found a 'Sin Hon TDH601' in cold state
[ 1175.711789] usb 1-4: dvb_usb_v2: downloading firmware from file 'dvb-usb-lme2510c-0.fw'
[ 1175.775782] usb 1-4: USB disconnect, device number 7
[ 1175.775955] usb 1-4: dvb_usb_v2: 'Sin Hon TDH601' successfully deinitialized and disconnected
[ 1176.052434] usb 1-4: new high-speed USB device number 8 using xhci_hcd
[ 1176.181496] usb 1-4: New USB device found, idVendor=3344, idProduct=24a0
[ 1176.181510] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 1176.181519] usb 1-4: Product: 䝇䝇
[ 1176.181527] usb 1-4: Manufacturer: Leaguerme
[ 1176.181534] usb 1-4: SerialNumber: LMEUSBSN0001
[ 1176.183341] usb 1-4: dvb_usb_v2: found a 'Sin Hon TDH601' in warm state
[ 1176.183804] usb 1-4: dvb_usb_v2: will pass the complete MPEG2 transport stream to the software demuxer
[ 1176.183833] DVB: registering new adapter (Sin Hon TDH601)
[ 1176.192171] i2c i2c-9: Added multiplexed i2c bus 10
[ 1176.192182] si2168 9-0064: Silicon Labs Si2168-B40 successfully identified
[ 1176.192188] si2168 9-0064: firmware version: B 4.0.2
[ 1176.197203] si2157 10-0060: Silicon Labs Si2147/2148/2157/2158 successfully attached
[ 1176.197228] usb 1-4: DVB: registering adapter 0 frontend 0 (Silicon Labs Si2168)...
[ 1176.197483] usb 1-4: dvb_usb_v2: 'Sin Hon TDH601' successfully initialized and connected

And when running e.g. dvbv5-zap:

[ 1320.568204] si2168 9-0064: downloading firmware from file 'dvb-demod-si2168-b40-01.fw'
[ 1321.527006] si2168 9-0064: firmware version: B 4.0.25
[ 1321.538051] si2157 10-0060: found a 'Silicon Labs Si2157-A30'
[ 1321.588369] si2157 10-0060: firmware version: 3.0.5

And lsusb:

# lsusb -v

Bus 001 Device 003: ID 3344:24a0
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x3344
  idProduct          0x24a0
  bcdDevice            0.00
  iManufacturer           0
  iProduct                0
  iSerial                 3 ???
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           76
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xc0
      Self Powered
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           0
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       1
      bNumEndpoints           7
      bInterfaceClass       255 Vendor Specific Class
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x86  EP 6 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x87  EP 7 IN
        bmAttributes            1
          Transfer Type            Isochronous
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x03fc  1x 1020 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x0a  EP 10 OUT
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               0
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x8a  EP 10 IN
        bmAttributes            2
          Transfer Type            Bulk
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               0
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  bNumConfigurations      1
Device Status:     0x0000
  (Bus Powered)

The lsusb was made on another computer, but that shouldn’t matter.

Linux Mint 18.1 + i915: Updating the Intel Graphics stack

Running Linux Mint 18.1 (kernel 4.4.0-53) on a Gigabyte Brix BACE-3160 (with an i915 graphics controller) , I had all kind of minor graphics artifacts (in particular a sluggish mouse pointer and Kodi felt heavy). So obviously, I went for updating the graphics stack.

Intel supplies an tool for doing this automagically on a selected list of distributions. In particular, the Graphics Update Tool 2.0.2 is intended for Ubuntu 16.04. Which is fine, since Mint 18.1 is derived from this distribution exactly.

So I downloaded it, and installed it:

$ sudo dpkg -i intel-graphics-update-tool_2.0.2_amd64.deb

That didn’t work all that nice, because there were missing dependencies. Easily fixed with

$ sudo apt-get -f install

And then launch the tool itself:

$ sudo intel-graphics-update-tool

And this is where the tool refused, because the distribution doesn’t match. So I tricked it by replacing the file it checks (a thanks goes to strace). First, save the real one:

$ sudo mv /etc/lsb-release /etc/lsb-release-mint

and then edit /etc/lsb-release to mimic Ubuntu. That is, saying this:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04 LTS"

And then run the tool again. Now everything went through fine. And for the record, it really helped with those graphics issues.

By the way, among the things it did was to add an apt-get repository. Namely, adding the file /etc/apt/sources.list.d/intellinuxgraphics.list with the following:

deb https://download.01.org/gfx/ubuntu/16.04/main xenial main #Intel Graphics drivers

For the record, this is /etc/lsb-release for Linux Mint 18.1:

DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=18.1
DISTRIB_CODENAME=serena
DISTRIB_DESCRIPTION="Linux Mint 18.1 Serena"

In case someone needs to fake Linux Mint…

Note that the effective initrd.img file (probably in /boot) must be updated (I’m not 100% about it, but it seems like the update tool did it): Odds are that the kernel modules related to graphics are loaded from the initrd.img, and not /lib/modules, as part of displaying the graphical splash screen (Plymouth) until Gnome is up and running. Unless you’ve disabled it, like myself.