Working better with an online whiteboard

Jan 29, 2021 / 0 comments

LCD Writing Tablet

One of the challenges I find about being fully remote is that one of the ways I think while I explain things is I draw diagrams. I’m not artistic in any manner (my brothers got that skillset), but a set of boxes and lines and some text scribbled as I talk really helps. I do think even for myself, which is obviously as easy to replicate at home as in the office; I have plenty of paper and a whiteboard in my study. It’s not so easy when having a design discussion with someone remotely.

Doodling with a mouse doesn’t quite work; my art skills are bad enough without then factoring in the fact it’s not a pen-like device I’m using to do it. I’ve previously tried a proper graphics tablet, but there’s a disconnect between where you are writing and where the output appears. That makes doing things like labelling within a diagram, or going back to draw an update, quite difficult. Or it does if you’re me anyway.

The modern solution is probably a laptop with a stylus capable touchscreen, but I’ve shied away from such things because I don’t want fingerprints all over my screen and don’t want to pay extra for something I haven’t previously thought I’d use. An alternative is a tablet with a stylus capable screen, but those turn out to be premium models these days (remember when resistive was the cheap option because no one wanted to use the stylus?) and mine doesn’t support it. You can get capacitive styli (styluses?) but then when you lean on the tablet it all gets confused.

When I’m due a technology refresh of my laptop or tablet I’ll perhaps factor such things in, but what to do now, when I’m not entirely sure how much usage I’ll get out of such a device and thus can’t justify a major expense on it? Buy a random thing from the internet, of course!

It turns out there are a range of “LCD writing tablets” out there, which let you scribble on a screen and then erase it at the press of a button. An electronic etch-a-sketch, as it were. Most of them don’t count as “smart”, with power only needed for the erase, but there appears to have been a device called the “Boogie Board Sync” in the past which offered some ability to save things. Searching around I found the NEWYES 10” Bluetooth Archive Writing Tablet from BangGood. Which looked like it had enough smarts to be able to send the images over bluetooth and therefore might be hackable in some manner. At £45 it seemed a reasonable punt, so I ordered one.

It arrived within 2 weeks and I was surprised to find that when plugged in as a USB device it actually presented as a tablet. So much for a hackery requirement! It was detected by the kernel fine:

kernel dmesg output
usb 1-1.2: new full-speed USB device number 19 using xhci_hcd
usb 1-1.2: New USB device found, idVendor=6161, idProduct=4d15, bcdDevice=30.00
usb 1-1.2: New USB device strings: Mfr=5, Product=6, SerialNumber=0
usb 1-1.2: Product: LetSketch
usb 1-1.2: Manufacturer: LetSketch
hid-generic 0003:6161:4D15.0010: hiddev0,hidraw4: USB HID v1.11 Device [LetSketch LetSketch] on usb-0000:00:14.0-1.2/input0
input: LetSketch LetSketch as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.2/1-1.2:1.1/0003:6161:4D15.0011/input/input35
hid-generic 0003:6161:4D15.0011: input,hidraw5: USB HID v1.11 Device [LetSketch LetSketch] on usb-0000:00:14.0-1.2/input1
lsusb output
Bus 001 Device 016: ID 6161:4d15  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x6161 
  idProduct          0x4d15 
  bcdDevice           30.00
  iManufacturer           5 LetSketch
  iProduct                6 LetSketch
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x003b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              480mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      18
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               2
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      1 Boot Interface Subclass
      bInterfaceProtocol      2 Mouse
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      83
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval               2
Device Status:     0x0003
  Self Powered
  Remote Wakeup Enabled

Nice. X wasn’t happy though:

non-working Xorg log
(II) config/udev: Adding input device LetSketch LetSketch (/dev/input/event8)
(**) LetSketch LetSketch: Applying InputClass "libinput tablet catchall"
(II) Using input driver 'libinput' for 'LetSketch LetSketch'
(II) systemd-logind: got fd for /dev/input/event8 13:72 fd 34 paused 0
(**) LetSketch LetSketch: always reports core events
(**) Option "Device" "/dev/input/event8"
(**) Option "_source" "server/udev"
(II) event8  - LetSketch LetSketch: is tagged by udev as: Tablet
(EE) event8  - LetSketch LetSketch: libinput bug: missing tablet capabilities: resolution. Ignoring this device.
(II) event8  - LetSketch LetSketch: device is a tablet
(II) event8  - failed to create input device '/dev/input/event8'.
(EE) libinput: LetSketch LetSketch: Failed to create a device for /dev/input/event8
(EE) PreInit returned 2 for "LetSketch LetSketch"
(II) UnloadModule: "libinput"

I ended up digging into the libinput source to figure out what was going on here, and it turned out to be the fact there was no report of the physical size of the tablet, so no indication of what the resolution was. That’s solvable with an entry in the udev hwdb for evdev devices, so I sent a patch upstream and with that applied (or just dropped into /etc/udev/hwdb.d/61-evdev-local.hwdb and then running systemd-hwdb update and replugging the device) everything looks much happier:

working Xorg log
(II) config/udev: Adding input device LetSketch LetSketch (/dev/input/event8)
(**) LetSketch LetSketch: Applying InputClass "libinput tablet catchall"
(II) Using input driver 'libinput' for 'LetSketch LetSketch'
(II) systemd-logind: got fd for /dev/input/event8 13:72 fd 86 paused 0
(**) LetSketch LetSketch: always reports core events
(**) Option "Device" "/dev/input/event8"
(**) Option "_source" "server/udev"
(II) event8  - LetSketch LetSketch: is tagged by udev as: Tablet
(II) event8  - LetSketch LetSketch: tablet 'LetSketch LetSketch' unknown to libwacom
(II) event8  - LetSketch LetSketch: device is a tablet
(II) event8  - LetSketch LetSketch: device removed
(**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:08.1/0000:04:00.3/usb1/1-1/1-1.2/1-1.2:1.1/0003:6161:4D15.000A/input/input24/event8"
(II) XINPUT: Adding extended input device "LetSketch LetSketch" (type: TABLET, id 20)
(II) event8  - LetSketch LetSketch: is tagged by udev as: Tablet
(II) event8  - LetSketch LetSketch: tablet 'LetSketch LetSketch' unknown to libwacom
(II) event8  - LetSketch LetSketch: device is a tablet
(II) libinput: LetSketch LetSketch: needs a virtual subdevice
(**) LetSketch LetSketch Pen (0): Applying InputClass "libinput tablet catchall"
(II) Using input driver 'libinput' for 'LetSketch LetSketch Pen (0)'
(II) systemd-logind: returning pre-existing fd for /dev/input/event8 13:72
(**) LetSketch LetSketch Pen (0): always reports core events
(**) Option "Device" "/dev/input/event8"
(**) Option "_source" "_driver/libinput"
(II) libinput: LetSketch LetSketch Pen (0): is a virtual subdevice
(**) Option "config_info" "udev:/sys/devices/pci0000:00/0000:00:08.1/0000:04:00.3/usb1/1-1/1-1.2/1-1.2:1.1/0003:6161:4D15.000A/input/input24/event8"
(II) XINPUT: Adding extended input device "LetSketch LetSketch Pen (0)" (type: STYLUS, id 21)
(**) Option "AccelerationScheme" "none"
(**) LetSketch LetSketch Pen (0): (accel) selected scheme none/0
(**) LetSketch LetSketch Pen (0): (accel) acceleration factor: 2.000
(**) LetSketch LetSketch Pen (0): (accel) acceleration threshold: 4

The only additional piece I’ve done is tie the tablet to a single screen, so I can then full screen whichever “whiteboard” system I’m using on that screen and have it map to the tablet - haven’t worked out how to tie it to just the application window yet, but the fullscreen approach works fine, using my smaller laptop screen. To do that I use xinput list to figure out the ID of the tablet and then xinput map-to-output 23 eDP-1 to map it to the eDP-1 output (the internal laptop screen), assuming the ID that comes out of the list is 23.

But is it any good? Well, the quality of the screen isn’t fantastic - no fine art or anything here - but the tablet part seems fine (complete with some pressure sensitivity) and the fact I can see what I’ve drawn where I’m trying to draw something new makes it a lot more useful for me. I’ve had a play with just screen sharing the GIMP and doodling in that, but equally work has an O365 subscription and the Microsoft Whiteboard turns out to be pretty good without anyone I’m sharing with needing to install anything.

Of course my artistic skills are still dreadful, but I have actually managed to use it for drawing out a couple of things while discussing them, so I’m considering that a win.

Saved Tablet image

Free Software Activities for 2020

Jan 9, 2021 / 0 comments

As a reader of Planet Debian I see a bunch of updates at the start of each month about what people are up to in terms of their Free Software activities. I’m not generally active enough in the Free Software world to justify a monthly report, but I did a report of my Free Software Activities for 2019 and thought I’d do another for 2020. I ended up not doing as much as last year; I put a lot of that down to fatigue about the state of the world and generally not wanting to spend time on the computer at the end of the working day.


2020 was unsurprisingly not a great year for conference attendance. I was fortunate enough to make it to FOSDEM and CopyleftConf 2020 - I didn’t speak at either, but had plenty of interesting hallway track conversations as well as seeing some good talks. I hadn’t been planning to attend DebConf20 due to time constraints, but its move to an entirely online conference meant I was able to attend a few talks at least. I have to say I don’t like virtual conferences as much as the real thing; it’s not as easy to have the casual chats at them, and it’s also harder to carve out the exclusive time when you’re at home. That said I spoke at NIDevConf this year, which was also fully virtual. It’s not a Free Software focussed conference, but there’s a lot of crossover in terms of technologies and I spoke on my experiences with Go, some of which are influenced by my packaging experiences within Debian.


Most of my contributions to Free software happen within Debian.

As part of the Data Protection Team I responded to various inbound queries to that team. Some of this involved chasing up other project teams who had been slow to respond - folks, if you’re running a service that stores personal data about people then you need to be responsive to requests about it.

The Debian Keyring was possibly my largest single point of contribution. We’re in a roughly 3 month rotation of who handles the keyring updates, and I handled 2020.02.02, 2020.03.24, 2020.06.24, 2020.09.24 + 2020.12.24

For Debian New Members I’m mostly inactive as an application manager - we generally seem to have enough available recently. If that changes I’ll look at stepping in to help, but I don’t see that happening. I continue to be involved in Front Desk, having various conversations throughout the year with the rest of the team, but there’s no doubt Mattia and Pierre-Elliott are the real doers at present.

In terms of package uploads I continued to work on gcc-xtensa-lx106, largely doing uploads to deal with updates to the GCC version or packaging (5, 6 + 7). sigrok had a few minor updates, libsigkrok 0.5.2-2, libsigrokdecode 0.5.3-2 as well as a new upstream release of Pulseview 0.4.2-1 and a fix to cope with change to QT 0.4.2-2. Due to the sigrok-firmware requirement on sdcc I also continued to help out there, updating to 4.0.0+dfsg-1 and doing some fixups in 4.0.0+dfsg-2.

Despite still not writing an VHDL these days I continue to try and make sure ghdl is ok, because I found it a useful tool in the past. In 2020 that meant a new upstream release, 0.37+dfsg-1 along with a couple of more minor updates (0.37+dfsg-2 + 0.37+dfsg-3.

libcli had a new upstream release, 1.10.4-1, and I did a long overdue update to sendip to the latest upstream release, 2.6-1 having been poked about an outstanding bug by the Reproducible Builds folk.

OpenOCD is coming up to 4 years since its last stable release, but I did a snapshot upload to Debian experimental (0.10.0+g20200530-1) and a subsequent one to unstable (0.10.0+g20200819-1). There are also moves to produce a 0.11.0 release and I uploaded 0.11.0~rc1-1 as a result. libjaylink got a bump as a result (0.2.0-1) after some discussion with upstream.


On the subject of OpenOCD I’ve tried to be a bit more involved upstream. I’m not familiar enough with the intricacies of JTAG/SWD/the various architectures supported to contribute to the core, but I pushed the config for my HIE JTAG adapter upstream and try and review patches that don’t require in depth hardware knowledge.


I’ve been contributing to the Linux kernel for a number of years now, mostly just minor bits here and there for issues I hit. This year I spent a lot of time getting support for the MikoTik RB3011 router upstreamed. That included the basic DTS addition, fixing up QCA8K to support SGMII CPU connections, adding proper 802.1q VLAN support to QCA8K and cleaning up an existing QCOM ADM driver that’s required for the NAND. There were a number of associated bugfixes/minor changes found along the way too. It can be a little frustrating at times going round the review loop with submitting things upstream, but I do find it quite satisfying when it all comes together and I have no interest in weird vendor trees that just bitrot over time.

Software in the Public Interest

I haven’t sat on the board of SPI since 2015 but I was still acting as the primary maintainer of the membership website (with Martin Michlmayr as the other active contributor) and hosting it on my own machine. I managed to finally extricate myself from this role in August. I remain a contributing member.

Personal projects

2020 finally saw another release (0.6.0, followed swiftly by 0.6.1 to allow the upload of 0.6.1-1 to Debian) of onak. This release finally adds various improvements to deal with the hostility shown to the OpenPGP keyserver network in recent years, including full signature verification as an option.

I fixed an oversight in my Digoo/1-wire temperature decoder and a bug that turned up on ARM but not MIPS in my mqtt-arp code. I should probably package it for Debian (even if I don’t upload it), as I’m running it on my RB3011 now.

Rooting the Tesco Hudl

Dec 23, 2020 / 0 comments

Tesco Hudl

I have an original Tesco Hudl - a Rockchip RK3188 based Android tablet. It’s somewhat long in the tooth and mine is running Android 4.2.2 (Jelly Bean). As a first step in trying to get it updated a bit I decided to root it and have a poke about. There are plenty of guides for this, but they mostly involve downloading Android apps that look dodgy or don’t exist any more. Thankfully the bootloader is unlocked, so I did it the hard (manual) way from a Debian 10 (Buster) box. I doubt this is useful to many folk, but I thought I’d write it up. As you’d expect follow this at your own risk; there is the potential to brick the Hudl.

First, enable developer mode on the Hudl (so we can adb in). Open the Settings app, scroll down to the bottom and click “About Tablet”, scroll down to the bottom and tap “Build number” 7 times, at which point it will tell you “You are now a developer!”. Go back to the main settings menu and just above “About Tablet” there will now be a “Developer options” entry. Click it, then make sure the box beside “USB debugging” is ticked.

Now you need to install the appropriate tools on your Debian box. That should be:

$ sudo apt install adb rkflashtool

We also need to download a suitable su tool. I lazily went for the prebuilt SuperSU Root:

$ mkdir hudl-root
$ cd hudl-root
$ wget
$ unzip

2.82 is the latest version but has problems on Jelly Bean; the device will end up not properly booting.

Hook the Hudl up to your machine with a suitable USB cable and you’ll now be able to get a shell on it:

$ adb shell
* daemon not running; starting now at tcp:5037
* daemon started successfully
shell@android:/ $

Ctrl-D will quit the shell and return you back to the local prompt. Next step is to reboot into the Rockchip bootloader, and use that to download the system partition (just over 1G in size)

$ adb reboot bootloader
$ sudo rkflashtool r system > system.img
rkflashtool: info: rkflashtool v5.2
rkflashtool: info: Detected RK3188...
rkflashtool: info: interface claimed
rkflashtool: info: working with partition: system
rkflashtool: info: found offset: 0x00142000
rkflashtool: info: found size: 0x00200000
rkflashtool: info: reading flash memory at offset 0x00341fe0... Done!

We now have a system.img file which represents the system partition of the device. We can mount that and copy over the su binary and SuperSU apk.

$ sudo mount -o loop system.img /mnt
$ sudo cp common/Superuser.apk /mnt/app/
$ sudo cp armv7/su /mnt/xbin/
$ sudo chmod +sx /mnt/xbin/su
$ sudo umount /mnt

Finally we can write this image back to the device, reboot and once the reboot has completed use adb to connect and su to root. SuperSU might pop up a dialog on the tablet asking you to ok the action (and possibly indicate it needs to do a fixup of the installation):

$ sudo rkflashtool w system < system.img
$ sudo rkflashtool b
$ adb shell
shell@android:/ $ su -
root@android:/ #

DeskPi Pro + 8GB Pi 4

Dec 16, 2020 / 0 comments

DeskPi Pro Raspberry Pi case

Despite having worked on a number of ARM platforms I’ve never actually had an ARM based development box at home. I have a Raspberry Pi B Classic (the original 256MB rev 0002 variant) a coworker gave me some years ago, but it’s not what you’d choose for a build machine and generally gets used as a self contained TFTP/console server for hooking up to devices under test. Mostly I’ve been able to do kernel development with the cross compilers already built as part of Debian, and either use pre-built images or Debian directly when I need userland pieces. At a previous job I had a Marvell MACCHIATObin available to me, which works out as a nice platform - quad core A72 @ 2GHz with 16GB RAM, proper SATA and a PCIe slot. However they’re still a bit pricey for a casual home machine. I really like the look of the HoneyComb LX2 - 16 A72 cores, up to 64GB RAM - but it’s even more expensive.

So when I saw the existence of the 8GB Raspberry Pi 4 I was interested. Firstly, the Pi 4 is a proper 64 bit device (my existing Pi B is ARMv6 which means it needs to run Raspbian instead of native Debian armhf), capable of running an upstream kernel and unmodified Debian userspace. Secondly the Pi 4 has a USB 3 controller sitting on a PCIe bus rather than just the limited SoC USB 2 controller. It’s not SATA, but it’s still a fairly decent method of attaching some storage that’s faster/more reliable than an SD card. Finally 8GB RAM is starting to get to a decent amount - for a headless build box 4GB is probably generally enough, but I wanted some headroom.

The Pi comes as a bare board, so I needed a case. Ideally I wanted something self contained that could take the Pi, provide a USB/SATA adaptor and take the drive too. I came across the pre-order for the DeskPi Pro, decided it was the sort of thing I was after, and ordered one towards the end of September. It finally arrived at the start of December, at which point I got round to ordering a Pi 4 from CPC.

Total cost ~ £120 for the case + Pi.

The Bad

First, let’s get the bad parts out of the way.

Broken USB port (right)

I managed to break a USB port on the Desk Pi. It has a pair of forward facing ports, I plugged my wireless keyboard dongle into it and when trying to remove it the solid spacer bit in the socket broke off. I’ve never had this happen to me before and I’ve been using USB devices for 20 years, so I’m putting the blame on a shoddy socket.

The first drive I tried was an old Crucial M500 mSATA device. I have an adaptor that makes it look like a normal 2.5” drive so I used that. Unfortunately it resulted in a boot loop; the Pi would boot its initial firmware, try to talk to the drive and then reboot before even loading Linux. The DeskPi Pro comes with an m2 adaptor and I had a spare m2 drive, so I tried that and it all worked fine. This might just be power issues, but it was an unfortunate experience especially after the USB port had broken off.

(Given I ended up using an M.2 drive another case option would have been the Argon ONE M.2, which is a bit more compact.)

The Annoying

DeskPi Pro without rear bezel

The case is a little snug; I was worried I was going to damage things as I slid it in. Additionally the construction process is a little involved. There’s a good set of instructions, but there are a lot of pieces and screws involved. This includes a couple of FFC cables to join things up. I think this is because they’ve attempted to make a compact case rather than allowing a little extra room, and it does have the advantage that once assembled it feels robust without anything loose in it.

DeskPi Pro with rear bezel and USB3 dongle

I hate the need for an external USB3 dongle to bridge from the Pi to the USB/SATA adaptor. All the cases I’ve seen with an internal drive bay have to do this, because the USB3 isn’t brought out internally by the Pi, but it just looks ugly to me. It’s hidden at the back, but meh.

Fan control is via a USB/serial device, which is fine, but it attaches to the USB C power port which defaults to being a USB peripheral. Raspbian based kernels support device tree overlays which allows easy reconfiguration to host mode, but for a Debian based system I ended up rolling my own dtb file. I changed

#include "bcm283x-rpi-usb-peripheral.dtsi"


#include "bcm283x-rpi-usb-host.dtsi"

in arch/arm/boot/dts/bcm2711-rpi-4-b.dts and then I did:

cpp -nostdinc -I include -I arch -undef -x assembler-with-cpp \
    arch/arm/boot/dts/bcm2711-rpi-4-b.dts > rpi4.preprocessed
dtc -I dts -O dtb rpi4.preprocessed -o bcm2711-rpi-4-b.dtb

and the resulting bcm2711-rpi-4-b.dtb file replaced the one in /boot/firmware. This isn’t a necessary step if you don’t want to use the cooling fan in the case, or the front USB ports, and it’s not really anyone’s fault, but it was an annoying extra step to have to figure out.

The DeskPi came with a microSD card that was supposed to have RaspiOS already on it. It didn’t, it was blank. In my case that was fine, because I wanted to use Debian, but it was a minor niggle.

The Good

I used Gunnar’s pre-built Pi Debian image and it Just Worked; I dd’d it to the microSD as instructed and the Pi 4 came up with working wifi, video and USB enabling me to get it configured for my network. I did an apt upgrade and got updated to the Buster 10.7 release, as well as the latest 5.9 backport kernel, and everything came back without effort after a reboot. It’s lovely to be able to run Debian on this device without having to futz around with self-compiled kernels.

The DeskPi makes a lot of effort to route things externally. The SD slot is brought out to the front, making it easy to fiddle with the card contents without having to open the case to replace it. All the important ports are brought out to the back either through orientation of the Pi, or extenders in the case. That means the built in Pi USB ports, the HDMI sockets (conveniently converted to full size internally), an audio jack and a USB-C power port. The aforementioned USB3 dongle for the bridge to the drive is the only external thing that’s annoying.

Thermally things seem good too. I haven’t done a full torture test yet, but with the fan off the system is sitting at about 40°C while fairly idle. Some loops in bash that push load up to above 2 get the temperature up to 46°C or so, and turning the fan on brings it down to 40°C again. It’s audible, but quieter than my laptop and not annoying.

I liked the way the case came with everything I needed other than the Pi 4 and a suitable disk drive. There was an included PSU (a proper USB-C PD device, UK plug), the heatsink/fan is there, the USB/SATA converter is there and even an SD card is provided (though that’s just because I had a pre-order).

Speaking of the SD, I only needed it for initial setup. Recent Pi 4 bootloaders are capable of booting directly from USB mass storage devices. So I upgraded using the RPi EEPROM Recovery image (which just needs extracted to the SD FAT partition, no need for anything complicated - boot with it and the screen goes all green and you know it’s ok), then created a FAT partition at the start of the drive for the kernel / bootloader config and a regular EXT4 partition for root. Copies everything over, updated paths, took out the SD and it all just works happily.


My main complaint is the broken USB port, which feels like the result of a cheap connector. For a front facing port expected to see more use than the rear ports I think there’s a reasonable expectation of robustness. However I’m an early adopter and maybe future runs will be better.

Other than that I’m pretty happy. The case is exactly the sort of thing I wanted; I was looking for something that would turn the Pi into a box that can sit on my desk on the network and that I don’t have to worry about knocking wires out of or lots of cables hooking bits up. Everything being included made it very convenient to get up and running. I still haven’t poked the Pi that hard, but first impressions are looking good for it being a trouble free ARM64 dev box in the corner, until I can justify a HoneyComb.

Mainline Linux on the MikroTik RB3011

Sep 21, 2020 / 0 comments

I upgraded my home internet connection to fibre (FTTP) last October. I’m still on an 80M/20M service, so it’s no faster than my old VDSL FTTC connection was, and as a result for a long time I continued to use my HomeHub 5A running OpenWRT. However the FTTP ONT meant I was using up an additional ethernet port on the router, and I was already short, so I ended up with a GigE switch in use as well. Also my wifi is handled by a UniFi, which takes its power via Power-over-Ethernet. That mean I had a router, a switch and a PoE injector all in close proximity. I wanted to reduce the number of devices, and ideally upgrade to something that could scale once I decide to upgrade my FTTP service speed.

Looking around I found the MikroTik RB3011UiAS-RM, which is a rack mountable device with 10 GigE ports (plus an SFP slot) and a dual core Qualcomm IPQ8064 ARM powering it. There’s 1G RAM and 128MB NAND flash, as well as a USB3 port. It also has PoE support. On paper it seemed like an ideal device. I wasn’t particularly interested in running RouterOS on it (the provided software), but that’s based on Linux and there was some work going on within OpenWRT to add support, so it seemed like a worthwhile platform to experiment with (what, you expected this to be about me buying an off the shelf device and using it with only the supplied software?). As an added bonus a friend said he had one he wasn’t using, and was happy to sell it to me for a bargain price.

RB3011 router in use

I did try out RouterOS to start with, but I didn’t find it particularly compelling. I’m comfortable configuring firewalling and routing at a Linux command line, and I run some additional services on the router like my MQTT broker, and mqtt-arp, my wifi device presence monitor. I could move things around such that they ran on the house server, but I consider them core services and as a result am happier with them on the router.

The first step was to get something booting on the router. Luckily it has an RJ45 serial console port on the back, and a reasonably featured bootloader that can manage to boot via tftp over the network. It wants an ELF binary rather than a plain kernel, but Sergey Sergeev had done the hard work of getting u-boot working for the IPQ8064, which mean I could just build normal u-boot images to try out.

Linux upstream already had basic support for a lot of the pieces I was interested in. There’s a slight fudge around AUTO_ZRELADDR because the network coprocessors want a chunk of memory at the start of RAM, but there’s ongoing discussions about how to handle this cleanly that I’m hopeful will eventually mean I can drop that hack. Serial, ethernet, the QCA8337 switches (2 sets of 5 ports, tied to different GigE devices on the processor) and the internal NOR all had drivers, so it was a matter of crafting an appropriate DTB to get them working. That left niggles.

First, the second switch is hooked up via SGMII. It turned out the IPQ806x stmmac driver didn’t initialise the clocks in this mode correctly, and neither did the qca8k switch driver. So I need to fix up both of those (Sergey had handled the stmmac driver, so I just had to clean up and submit his patch). Next it turned out the driver for talking to the Qualcomm firmware (SCM) had been updated in a way that broke the old method needed on the IPQ8064. Some git archaeology figured that one out and provided a solution. Ansuel Smith helpfully provided the DWC3 PHY driver for the USB port. That got me to the point I could put a Debian armhf image onto a USB stick and mount that as root, which made debugging much easier.

At this point I started to play with configuring up the device to actually act as a router. I make use of a number of VLANs on my home network, so I wanted to make sure I could support those. Turned out the stmmac driver wasn’t happy reconfiguring its MTU because the IPQ8064 driver doesn’t configure the FIFO sizes. I found what seem to be the correct values and plumbed them in. Then the qca8k driver only supported port bridging. I wanted the ability to have a trunk port to connect to the upstairs switch, while also having ports that only had a single VLAN for local devices. And I wanted the switch to handle this rather than requiring the CPU to bridge the traffic. Thankfully it’s easy to find a copy of the QCA8337 datasheet and the kernel Distributed Switch Architecture is pretty flexible, so I was able to implement the necessary support.

I stuck with Debian on the USB stick for actually putting the device into production. It makes it easier to fix things up if necessary, and the USB stick allows for a full Debian install which would be tricky on the 128M of internal NAND. That means I can use things like nftables for my firewalling, and use the standard Debian packages for things like collectd and mosquitto. Plus for debug I can fire up things like tcpdump or tshark. Which ended up being useful because when I put the device into production I started having weird IPv6 issues that turned out to be a lack of proper Ethernet multicast filter support in the IPQ806x ethernet device. The driver would try and setup the multicast filter for the IPv6 NDP related packets, but it wouldn’t actually work. The fix was to fall back to just receiving all multicast packets - this is what the vendor driver does.

Most of this work will be present once the 5.9 kernel is released - the basics are already in 5.8. Currently not queued up that I can think of are the following:

  • stmmac IPQ806x FIFO sizes. I sent out an RFC patch for these, but didn’t get any replies. I probably just need to submit this.
  • NAND. This is missing support for the QCOM ADM DMA engine. I’ve sent out the patch I found to enable this, and have had some feedback, so I’m hopeful it will get in at some point.
  • LCD. AFAICT LCD is an ST7735 device, which has kernel support, but I haven’t spent serious effort getting the SPI configuration to work.
  • Touchscreen. Again, this seems to be a zt2046q or similar, which has a kernel driver, but the basic attempts I’ve tried don’t get any response.
  • Proper SFP functionality. The IPQ806x has a PCS module, but the stmmac driver doesn’t have an easy way to plumb this in. I have ideas about how to get it working properly (and it can be hacked up with a fixed link config) but it’s not been a high priority.
  • Device tree additions. Some of the later bits I’ve enabled aren’t yet in the mainline RB3011 DTB. I’ll submit a patch for that at some point.

Overall I consider the device a success, and it’s been entertaining getting it working properly. I’m running a mostly mainline kernel, it’s handling my house traffic without breaking a sweat, and the fact it’s running Debian makes it nice and easy to throw more things on it as I desire. However it turned out the RB3011 isn’t as perfect device as I’d hoped. The PoE support is passive, and the UniFi wants 802.1af. So I was going to end up with 2 devices. As it happened I picked up a cheap D-Link DGS-1210-10P switch, which provides the PoE support as well as some additional switch ports. Plus it runs Linux, so more on that later…

subscribe via RSS