Raspberry Pi 4b as an Ubuntu 21.10 USB gadget tethered to an iPad Pro
Over the Christmas period, I had foolishly decided that I’d like to do some tinkering with C64 development. The plan was, as we were away, to see if I could use virtual machines, via UTM on my 11” iPad Pro.
For whatever reason – I suspect because it’s the original 11” Pro – I couldn’t get any virtual machines to work. At this point I remembered an article I’d seen about using a tethered Raspberry Pi for exactly the same thing.
Having bought a Raspberry Pi 4b some time ago, with the full intention of playing retro games on it – which lasted all of a week – it made sense to repurpose it and see if I could get it up and running as a USB gadget to use for messing around.
There are a number of tutorials online, all based on Ben Hardhill’s original, detailing how to do this with Raspian/Raspberry Pi OS. This worked great, however Virtual Code was really, really, laggy using VNC, and I also couldn’t get VICE to work.1
At work the devs are going to start using Next.js in the near term and I’ve been meaning to try playing with React since about 2015. With that in mind I thought I’d switch to building the Pi out for that purpose.
All good, but then I decided I wanted to do it with Ubuntu instead of Raspberry Pi OS, because why do the easy thing when you can over engineer something for no good reason?
A Google search led to a single forum thread detailing how to do it for Ubuntu 20.10. There isn’t an actual step by step so I wanted to detail that here.
1. Initial steps
Obviously the first thing to do is burn the Ubuntu 21.10 server image to an SD card with Raspberry Pi Imager.
Once done, don’t eject the SD card – you need to edit the following three files on your computer, before inserting into the Pi:
network-config
cmdline.txt
config.txt
1.1. network-config
As a safety net, add your WiFi details to the config file by uncommenting and editing the WiFi lines. If your network name contains spaces, remember to use quotes:
wifis:
wlan0:
dhcp4: true
dhcp6: false
optional: true
access-points:
"Network Name":
password: "Network Password"
You can optionally add an address line here as well, to specify an IP:
addresses: [XXX.XXX.XXX.XXX/XX]
Note this is in CIDR notation which will blow your mind. Happily there are calculators for this.
Once you’ve done this, add the usb0
interface under ethernets
:
ethernets:
eth0:
dhcp4: true
optional: true
usb0:
dhcp4: false
optional: true
addresses: [10.55.0.1/29]
1.2 cmdline.txt
A simple edit to add modules-load=dwc2,g_ether
between rootwait
and fixrtc
.2
It should look something like this when you’ve finished:
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=LABEL=writable rootfstype=ext4 elevator=deadline rootwait modules-load=dwc2,g_ether fixrtc quiet splash
1.3 config.txt
Another simple edit, adding dtoverlay=dwc2,dr_mode=peripheral
to the end of this file. On Ubuntu 21.10 dtoverlay=dwc2
already exists at the end of the file, however my limited knowledge means I don’t know if it requires one or both, so I just slapped the aforementioned after this so it reads:
# Config settings specific to arm64
arm_64bit=1
dtoverlay=dwc2
dtoverlay=dwc2,dr_mode=peripheral
The original forum thread questions if the dr_mode=peripheral
is necessary, however I can’t be arsed to haven’t tried removing it.
You can eject the SD card now, and insert it into the Pi. The next few steps I did on the iPad, with the Pi plugged in, connected via WiFi – you’ll need to know the address of the Pi if you didn’t specify it in network-config
.
If you look peek into settings on the iPad as the Pi boots up, you will see an “RNDIS/Ethernet Gadget” appear in the “Ethernet” section that appears under “Wi-Fi”. Tapping on that and you’ll eventually see a self-assigned IP and subnet mask appear – we’ll change this in subsequent steps.
2. Update and upgrade
The usual chat here, update and upgrade the install
sudo apt update && apt upgrade
Once done, reboot the Pi:
sudo reboot
3. Install and configure dnsmasq
Install dnsmasq via apt:
sudo apt install dnsmasq
At the end of the install it will attempt to run, but will fail as systemd-resolved
is already running on port 53 – this will be resolved in the next step.
Create /etc/dnsmasq.d/usb
:
sudo nano /etc/dnsmasq.d/usb
and add the following:
interface=usb0
dhcp-range=10.55.0.2,10.55.0.6,255.255.255.248,1h
dhcp-option=3
leasefile-ro
port=0
According to the forum thread, the port=0
line is the bit that disables the DNS server part of dnsmasq, to avoid the clash with systemd-resolved
.
Now uncomment the last line of /etc/default/dnsmasq
:
# If the resolvconf package is installed, dnsmasq will tell resolvconf
# to use dnsmasq under 127.0.0.1 as the system's default resolver.
# Uncommenting this line inhibits this behaviour.
DNSMASQ_EXCEPT="lo"
Finishing up
Reboot the Pi and navigate to Settings > Ethernet > RNDIS/Ethernet Gadget. You’ll now see that it has an IP address of 10.55.0.X, with a subnet mask of 255.255.255.48. You should now be able to SSH into your Pi via the 10.55.0.1 address we specified in step 1.1.
Unfortunately it appears that the Pi will only retain those settings on initial boot and any subsequent reboots where it can retain the IP lease. After that – e.g. leaving it overnight – the Pi will consistently show up on the iPad with a self assigned IP in the 169.x.x.x range. To remedy this, I’ve had to manually set the IP and subnet mask to something between 10.55.0.2-10.55.0.6 and 255.255.255.48 respectively.
Addendum
During the course of burning SD cards with various images, I came across the fact that the new Macbook Pro’s SD card slots are… sub-optimal. Repeatedly there were errors in verifying images being burnt to the cards, to the point where I thought it was the Raspberry Pi Imager software. Switching to an external SD card reader every image burnt and verified successfully.
Apparently I’m not the only one experiencing issues. This is obviously not a great look for a premium machine.
However, later I discovered that Jeff Geerling – his blog is brilliant btw – has a whole series of articles on which SD card to chose for your Raspberry Pi, the TL:DR is the Samsung EVO Pro Plus.
Both of the Samsung SD cards I bought worked with the provided adaptors in the Macbook Pro, with no errors.
- This is after trying both the package install and building it from scratch – the package version refused to see the required ROMs, and the built version just launched a black screen. ↵
- Not entirely sure that it has to be between these two or at the end. The guide I linked to at the start suggests after
rootwait
. ↵