UPDATE: Jan 29th, 2024: It would seem that Asustor has read my mind and included this specific drvier in ADM Kernel Extensions, so this post is now obsolete, however, the journey was a ton of fun.
I’ve been running HomeAssistant for a long time at home to handle my light and thermostats as well as some simple automation that turns off light when I’m not at home. I’ve done so, as many do, on a Raspberry Pi 4 with the official HomeAssistant OS running on it. I also had an external ZigBee radio connected to the Raspberry, that handled communication with my lights and thermostats. It has been a pretty good solution, but after the third SD card died the infamous write fatigue death, I started looking for something better. Coincidentally, I was also looking for a NAS that could house a couple of HDD drives that I had in my desktop, to provide an always on back-up solution for my other systems.
I stumbled upon an Asustor Drivestor 2 and thought it fit the bill so I ordered one and when it arrived I plugged in my drives and I was off to the races. The operating system that Asustor has built for the drivestor (and other products), called ADM, also had a HomeAssistant app that could simply be installed on from an appstore like service. This was great I thought, everything was just working… Until i plugged in the aforementioned external ZigBee radio…
The radio I’m using is the CC2652RB development stick from Slaesh.sh, which seemed like the smallest, neatest solution at the time of purchase, and it certainly works very well for my use case. However, in Linux it uses a USB Serial bridge driver called cp210x, which can be found in the mainline Linux kernel. This driver was unfortunately nowhere to be found on the NAS itself though, so I started googling around to see if anyone else had faced the same issue.
I found a couple of blog and forum posts indicating that it was there at one point, but was removed in one of the later versions (for unknown reasons). To the rescue comes “some very helpful guy on the internet”™, who had hacked together the sources for the kernel and rebuilt it with enough luck, wizardry and smoke and mirrors that it started ticking. The link he posted to download the driver was unfortunately dead though which meant for us mere mortals that we were once again on our own.
I recently got a new job where I’m working very extensively with Linux drivers, how they’re developed and built, which got me thinking that a mere mortal like me maybe could become a wizard if only for a day. One thing I’ve learned at my new job is the importance of open source software licenses, and how they affect what companies can keep proprietary, but more importantly what parts of it has to be made public. The Linux kernel is licensed under GPL version 2, which requires that all code required to build the Linux kernel running on a product you own, has to be made available to you. What that means in practice is that the kernel code that was used to build the kernel on my drivestor (and all the drivers) was publicly available along with the tool chain to build it.
Asustor has a page where all of their GPL source is hosted so I downloaded all the sources
wget "https://downloadgb.asustor.com/developer/arm64-asustor-linux-gnu_20201223.tar.gz"
wget "https://sourceforge.net/projects/asgpl/files/ADM4.1.0/4.1.0.RLQ1_and_above/arm64rt_kernel_4_19_119/GPL_linux-4.9.119_ADM4.0_20221102.tar.bz2/download"
wget "https://sourceforge.net/projects/asgpl/files/ADM4.1.0/4.1.0.RLQ1_and_above/arm64rt_kernel_4_19_119/linux-4.9.119-arm64.config/download"
Unpacked it:
tar xaf arm64-asustor-linux-gnu_20201223.tar.gz
tar xaf GPL_linux-4.9.119_ADM4.0_20221102.tar.bz2
Moved the config into the linux-4.9.119
folder:
mv linux-4.9.119-arm64.config linux-4.9.119/.config
NOTE: If you can’t find the
.config
file, you can always try to ssh into the machine and dozcat /proc/config.gz > .config
. This.config
is identical to the one the running kernel was built with.
I then enabled the driver as a module in my config using make menuconfig
and searched for cp210x using /
. This change can also be made directly in the .config
file, but sometimes it’s easier to use menuconfig if you’re not sure what the module is actually called.
...
CONFIG_USB_SERIAL_CP210X=m
...
Then I tried to build the kernel module:
cd linux-4.9.119
PATH=$PWD/../aarch64-asustor-linux-gnu/bin:$PATH \
make \
-j32 \
ARCH=arm64 \
CROSS_COMPILE=aarch64-asustor-linux-gnu- \
drivers/usb/serial/cp210x.ko
This gave a single error:
/usr/bin/ld: scripts/dtc/dtc-parser.tab.o:(.bss+0x10): multiple definition of `yylloc'; scripts/dtc/dtc-lexer.lex.o:(.bss+0x0): first defined here
Which was fixed with this patch:
diff --git a/scripts/dtc/dtc-lexer.lex.c b/scripts/dtc/dtc-lexer.lex.c
index ba525c2..a2fe8db 100644
--- a/scripts/dtc/dtc-lexer.lex.c
+++ b/scripts/dtc/dtc-lexer.lex.c
@@ -637,7 +637,7 @@ char *yytext;
#include "srcpos.h"
#include "dtc-parser.tab.h"
-YYLTYPE yylloc;
+extern YYLTYPE yylloc;
extern bool treesource_error;
/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
After that, rerunning the make
command above produced the missing kernel module which I then copied to my NAS:
scp drivers/usb/serial/cp210x.ko nas:/tmp
I ssh’ed into my NAS and inserted it into the kernel
ssh nas
sudo mv /tmp/cp210x.ko /lib/modules/4.9.119/
sudo insmod /lib/modules/4.9.119/cp210x.ko
dmesg
then showed the following at the end:
[19789.266700] usbcore: registered new interface driver cp210x
[19789.272742] usbserial: USB Serial support registered for cp210x
Which got me smiling. I then took the ZigBee radio stick, and plugged it into the (back) USB port of my NAS and…
[19877.728808] xhci-hcd xhci-hcd.7.auto: Wait for xhci command complete left 1250 ms
[19877.854108] usb 5-1: new full-speed USB device number 2 using xhci-hcd
[19878.001986] cp210x 5-1:1.0: cp210x converter detected
[19878.008769] usb 5-1: cp210x converter now attached to ttyUSB0
It recognized the stick as if it had known it all its existence. I swiftly opened my HomeAssistant app on the NAS, went to “Devices and Services”, and there it was, under “Discovered” was a new service, “Zigbee Home Automation”. I clicked “Configure” and like magic I had freed my Raspberry Pi from destroying further SD cards, occupying a wall outlet in my server closet, taking up a network port on my router, and made my home lab setup much cleaner. It even kept the association to all of my devices, because the stick remembers what network it was part of.
This might seem like a tiny little thing that could have been remedied by returning the NAS and buying one that already had the kernel module built into its distribution, but I absolutely adore the adventure.