Welcome to this year’s yearly Kodi post. The fact that I don’t write about Kodi very often should be a sign that it’s actually fairly stable, and indeed beside for the random fight with X11 over whether DPMS should or should not be enabled, my HTPC setup works fairly well, even though it’s getting used less often — the main content I have on it is stuff that we own in DVDs — either because we ripped it ourselves or… found it to make it easier on us.
In part due to my poking around my other TV-related project, and in part because my phone seems to have issues at keeping its IPv6 stable – which means I can’t control Kodi with the Kore app until I turn wifi off and on again – I decided to address the biggest missing features of Intel’s NUC: the lack of HDMI CEC support — and as far as I know that’s a missing feature even on their most recent NUCs.
With CEC, HDMI-connected devices can provide a level of control, including signaling a request to turn on or off, to change the input selection, and so on. It also allows a TV remote control to send most button presses to a connected device. This allows, for instance, to have control over Kodi’s menus with a single remote control, rather than having to set up a second remote just for that, which is what I was originally planning on doing, using a vintage SVHS remote control.
As I said, Intel doesn’t support CEC on their NUC, to this day. Instead they suggest you to buy an adapter from companies such as Pulse Eight, which thankfully still also sell the harness for my six years old model. The adapter is a microcontroller that is connected to an Intel-provided header, from which it receives the CEC signals coming from the HDMI port on one side, and exposes an USB device through the motherboard header, from which the libCEC – that Pulse Eight themselves developed – can decode it and provide information to the other software.
The Pulse-Eight installation instructions gloss over the most interesting part: which pins does it need on the Custom Solutions Header, and more interesting how do you get to them. It turns out that I had to disassemble most of the NUC to get to the connector, and only found the right pins thanks to Kingj who reviewed this kit five years ago. The thing that his review seemed to ignore, though, is that the connectors are just about as tall as the same there is to use that theader — and the cable rubs onto the WiFi antenna (which I actually never use, so I was actually tempted to remove, until I remember they do Bluetooth, too). And the suggested position to stick the small board onto the Ethernet connector bumps into the heat foam that’s meant to protect the mSATA drive. But beside those two issues, it fit all together, and with a bit of worry and fear to break stuff, and possibly one of the black pip retainers broken, I did manage to get the whole thing installed just fine.
Troubleshooting Pulse-Eight CEC Adapter Issues
After installing and booting up the NUC, I found myself nearly crying from the frustration when I booted up and saw the adapter turn up on lsusb
as Atmel at90usb162 DFU bootloader. This appears to be a common bane of multiple people, and at least on Windows people suggested that a firmware update would help — the firmware update being only available as an option on Windows (and possibly Wine?), but not released on Linux. Turns out that this is a red herring.
The DFU bootloader is the Device Firmware Update — this is the mode you need a microcontroller (MCU) to be in to load it with a new program. Usually there’s two ways to enter this operation: a physical one and a logical one (sending a specific command via USB, for instance), and while I didn’t expect them to be stateful, they appear to be. At first I was afraid I grounded something I shouldn’t have (which would have put into firmware download mode), or that the device left the factory without being programmed (which would have indeed been fixed by running the firmware update).
Instead, it turns out it might just be stateful, and was left in programming mode when it left the factory — and you can fix that with a single command on Linux: dfu-tool attach
. The command is provided by fwupd (LVFS), and worked like a charm on my board for it to show up as the /dev/ttyACM0
it needed to be.
The next problem was figuring out why Kodi was not acting on any of the remote button presses. According to a lot of blogs, and forum posts, and wikis, this might have had to do with remote.xml
. It didn’t, at least for me. The problem is that Kodi recognizes the presence of the CEC device by looking at the USB devices connected, but it doesn’t check if it has permissions to open the device, until it tries to. And the device (/dev/ttyACM0
, which is usually the easiest no-drivers-needed way to connect an USB-to-UART bridge), is usually owned by the dialout
group, which my Kodi user was not part of.
Why dialout
and what the heck does it mean? Given it is 2020 as I write this, it might be worth giving a bit of a history lesson, without being condescending to those who might not have heard the term before. This group is usually “in charge” of serial port devices, such as ttyS0
and ttyACM0
and ttyUSB0
— the reason for that is that back in the old days of phone-line connectivity (which for some are current days still), the main use for serial ports was to connect modems (or in some cases faxes) — and that meant that whoever could access the serial ports would be able to “dial out” — that is, make a phone call. Since phone calls could be (and possibly still are) very expensive, accessing those ports couldn’t be made too easy. This is now a totally legacy naming, but… well, it’s hard to change these things, particularly in UNIX-land.
I solved this by adding Kodi to the group. The NUC doesn’t have any other serial port, so it’s not an issue to do that. The alternative would be to have an udev rule that explicitly sets the device as owned by the user running Kodi, similar to the rules in glucometerutils.
So now the device works, Kodi can receive the commands just fine, and I don’t have to bother to get the Kore app out just to select the next episode of whatever we’re watching at any one time. The only thing that remains annoying to me is that I can’t access the CEC device from any other process. I was wondering if I could implement most of what I wanted in the project I described previously (namely, controlling TV inputs) through CEC (answer: probably), but that’s a moot point because serial devices can only be accessed by a single process at a time (the same is true of most other devices — this is the reason why Windows has device drivers, and why you end up with so many “daemons” in Linux and other *nix: you need something that “multiplexes” the account across different processes).
If this was ten years ago, you’d have me design a CEC Daemon, and proof-of-concept integrate it in Kodi. Time being what it is, I’m unlikely to be working on this any time soon. But if someone feels like it’s a worthy task, I’ll be happy to chat, discuss designs, or review code to implement it.