open source

Open-source contribution: chdir for BusyBox

Coming soon to the Linux box near you:

Hopefully this doesn’t age like milk

So yeah, I managed to get a commit into one of the open-source projects that I use on a daily basis: BusyBox. I guess many others use it too, either knowingly or unknowingly. BusyBox is a software suite providing plenty of Unix utilities in a minimized single executable. For example, when you’re using dmesg command you don’t necessarily know if the implementation comes from util-linux or BusyBox. But if you’re using OpenWRT, Alpine or Yocto you’re most likely using the BusyBox version.

The Problem

Because the BusyBox binary is minimized, the utilities it provides are often missing lesser-used features. As mentioned in the previous Aioli devblog, start-stop-daemon is for example missing -d/--chdir option present in the full Debian counterpart. As mentioned in that text, I wrote a patch to add that feature. What I didn’t really mention is that I submitted the patch to the BusyBox mailing list. I was hoping that it would get applied, and eventually it did!

start-stop-daemon is a program that’s commonly used in the SysVinit scripts to control the lifecycle of the system services. It doesn’t only start and stop daemons, it can also reload them, check their status and… well that’s primarily that. What --chdir option does is that it changes the working directory of the start-stop-daemon process before it launches the program it’s been assigned to start. This effectively changes the working directory of the process that will actually be started.

The Solution

The patch for this feature was quite straightforward. Mostly it consisted of adding a variable to hold the new working directory, inserting the new -d option to the opt list for the option parser, and editing the usage message. Then, if the new option flag was set, it was just a matter of calling the xchdir() in libbb (BusyBox’s library) to change the directory to the given directory (or die).

The less popular sequel to “Skate or Die” and “Ski or Die”.

In addition to this, I looked at how the tests for BusyBox work and wrote tests for the new flag. And cleaned up the TODO. In the end, the commit delta ended up being less than 60 lines. From what I’ve understood of the commit stats, the start-stop-daemon got bloated by about 79 bytes as a result. So the next time you’re updating BusyBox and curse the fact that it doesn’t fit into your root file system that has 67 bytes of free space remaining, you know who to blame.

All in all, getting the patch merged was an interesting process. I could definitely contribute more to BusyBox if there are suitable issues. Something perhaps a bit less simple the next time. But whether there will be more commits or not, it’s wild to think that my code could be running in Linux boxes around the world. Although, I guess that would require the device vendors to update their devices to run the new (still unreleased) version of BusyBox, so I guess it’s not happening too soon.

Open-source contribution: RTL8821AU driver recipe

This is a story of how I became a useful member of society by doing my first open-source contribution.

It all began one fateful afternoon, when I purchased a TP-Link Wifi dongle, thinking that it would allow me to connect my old Raspberry Pi 2 wirelessly to the internet. It was running my own Poky-based distro, but what could really go wrong with random USB devices and Linux?

Well quite a plenty really. I plugged the device in, but I couldn’t connect to the highway of data. No delicious internet cookies for me. Not even a blinking led.

To begin troubleshooting the issue, I tried checking if the network interface was seen by kernel by running both ifconfig -a and ip link show. No wlan devices were found. Some googling suggested running lsusb. That showed the device, which at least proved that it wasn’t broken and was recognized by kernel. Some sort of network driver was clearly needed.

Bus 001 Device 004: ID 2357:011f TP-Link 802.11ac WLAN Adapter 
Bus 001 Device 003: ID 0424:ec00 Microchip Technology, Inc. (formerly SMSC) SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Microchip Technology, Inc. (formerly SMSC) SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Finding the correct driver turned out to be a bit tougher than expected. First I tried googling the name of the wifi dongle suffixed with “driver”. Bad Idea. This led to a lot of ancient forum posts that suggested all kinds of Realtek drivers for (almost) similarly named devices that were installed by enabling a variety of kernel configuration options. None of the drivers worked.

After some more of the furious googling I found out that the wifi dongle I bought required an out-of-tree kernel module instead. That meant I couldn’t just enable a kernel configuration to build the driver in my distro. Finding the correct driver was another trial and error type of affair. Someone suggested a driver for the 8812au chip. It did not work but helped me to find a correct trail.

Fortunately there’s a lot less diseases on this trail.

RTL8812AU driver repo contained a file supported-device-IDs that expectedly did not contain the device id output by lsusb. However, that gave me an idea (that I really should have gotten from the beginning): googling “driver 2357:011f”. Who would have guessed that searching for a driver with an exact device id instead of vague product names would yield the correct driver(s)? This search also helped me to find the name of the Realtek chip, 8821au, which I confused plenty of times with 8812au. I’m not sure if this info would have been available on the manual of the dongle because I did not read it.

After finding the driver & chip I connected some dots and realized that there actually is a kernel configuration driver named CONFIG_RTL8XXXU that I tried. Despite what the name suggests, it does not work with rtl8821au.

Once the correct driver was figured out it was time to add it to the Yocto build. Some more googling revealed that there is a meta layer called meta-rtlwifi for these Realtek out-of-tree modules. Unfortunately, it didn’t contain the RTL8821AU driver. Fortunately, I’ve been using git at work so I could fix that myself. You can see where this is heading.

So I took the RTL8812AU driver recipe as I suspected that it should mostly work, and updated the relevant parts, i.e. the repo to fetch the driver from. I was pleasantly surprised that the build worked just like that. Even more shocking was that the module worked as well. After that, it was just a matter of a pull request to get the driver added to the meta-layer alongside the other friendly drivers.

There were actually multiple drivers available for 8821au. At least morrownr, ulli-kroll and ivanborislav provide RTL8821AU drivers. In the end, I chose morrownr driver because their driver worked satisfactorily out of the box and their driver is also used for 8812au. I first gave a shot at ivanborislav driver but it filled my TTY with logs about power save mode. Most likely a configuration mistake from my side, but usually a thing that works without extra tinkering is the better choice.

It’s almost weird that there’s a meme for literally everything.

That’s how I got quite familiar with my wifi dongle, and made my first open-source contribution in the process. I also learned something. I’m not yet 100% sure what that is. Perhaps it’s that the device id is quite important when trying to find a suitable driver. And googling can give all kinds of interesting useful information. Until next time!