The Linux USB gadget API is built on a stack of two drivers : the “actual” USB driver for the physical USB interface of the Pi, and a sort of “middleware” driver (gadget driver) that implements the behavior of a USB device.
The USB driver will be the same for all gadget drivers, so let’s start with that.
Unlike the gadget drivers, this one ties to actual hardware. Therefore, we need to let Linux know that it’s here and what it is.
Take your Pi’s SD Card, plug it into your PC and access the boot partition (the only partition that should be accessible if you’re on a Windows PC). There, you will find a file named “config.txt”. Edit it and add these two lines at the end :
[pi0] dtoverlay=dwc2
Now, as you may know, I’m not the kind of guy to just tell you to do something and expect blind obedience. Otherwise, I’d be a religious leader. Let me explain what these lines do, it’ll make the whole shebang easier to comprehend, in the fullness of time.
Or if you’re in a hurry you can just proceed right now to your desired gadget’s page. Your loss.
The “config.txt” file is a boot configuration file that is normally edited through the “raspi-config” tool. You know, the tool you always use after flashing a new SD Card, if only to expand the Linux filesystem to take-up the entire space on that card. Well you can also edit this file manually when “raspi-config” hasn’t got you covered.
This file has its own documentation at raspberrypi.com but it’s a lot more information than you need right now. At this time, all you really need to know is that it’s a script in a simple ad-hoc language that’s executed by the boot firmware on your Pi’s SoC. It is meant to configure the hardware on your machine. If you’re old enough to have known MS-DOS, this is equivalent to the old “config.sys” file.
The [pi0] line is a filter. One great thing about Raspberry Pi is that all the different boards are vastly compatible with each other, to the extent that the same SD Card can boot on any model. However, there are hardware differences that you may want to mind. Most Raspberry Pi do not have a USB OTG port, so this filter ensures our configuration command will only be applied on a Pi Zero, whether it be a Zero, Zero W or Zero 2 W.
The dtoverlay command stands for “devicetree overlay”. Long story short, when Linux was born you had to compile all your drivers into the kernel so they would execute at the same level of trust (known as kernel mode or ring zero). That’s why old Linux geeks keep ranting about recompiling kernels all the time. But eventually we all grew tired of that and moved on to a more flexible approach : the DeviceTree (yes, just one word, that’s not a typo).
A devicetree is a data structure for describing hardware. Their words. Couldn’t put it better if I tried.
This makes it possible to compile drivers as modules separate from the kernel and then load those kernel modules when the machine boots, according to the contents of a devicetree structure. This approach accounts for optional hardware through devicetree overlays. Overlays are essentially partial devicetrees that can be grafted to the devicetree structure at boot.
You may have noticed that your SD Card’s boot partition happens to contain an “overlays” folder full of “.dtbo” files. DTBO stands for devicetree blob overlay, where “blob” refers to the compiled form of a devicetree. And you may also have noticed that one of those files is “dwc2.dtbo”.
But what does “dwc2” even mean ? It has exactly zero letter in common with USB or OTG.
DWC stands for DesignWare Core, which is a Synopsys product name. You see, in this day and age of rampant consumerism and late-stage capitalism, ain’t nobody got the time to develop their own USB interface. Instead, what tends to happen is that chip manufacturers turn to specialist companies like Synopsys for ready-made interface designs and all the supporting software and drivers. So did Broadcom when they designed the SoC on our beloved Raspberry Pi. This is exactly the same thing as licensing ARM for the design of the CPU cores in that same Raspberry Pi SoC.
If you are made of time (and curious), you can check out the product page for Synopsys USB 2.0 interfaces there.
The “overlays” folder also contains a “dwc-otg.dtbo” file, and you may be wondering why we’re not using that one instead. Well, as I understand it, its name is misleading and it does not support USB OTG ports. If I ever bother to learn more about that, I’ll amend this page.
So… that was a bit long. Let’s recap : we’ve just modified our Pi’s “config.txt” configuration file to overlay a USB device port configuration (dwc2) onto our Pi’s devicetree, so that Linux will be able to use it. Without that, the USB port on our Pi Zero could only act as a host port, using an OTG cable.
We’re now ready to try the different gadget drivers.