Raspberry Pi Zero – Programming over USB! (Part 1)

Update 19/05/2016 – The modules are now included in the most recent version of Raspbian and thanks to some digging around in kernel documentation, it is now possible to set the full thing up without a keyboard/mouse/screen! Just need a Windows/Mac/Linux computer!

Update 15/01/2016 – The modules have now been merged into the Raspberry Pi Foundation maintained kernels! So no more need for custom kernels, just need to grab the most recent alpha kernels. Doing this is now far simpler.

Full credit for the initial documentation for this goes to a number of Pi experts from the Raspberry Pi community, see here and here.

An acknowledgement also to Lady Ada of Adafruit who was working on documenting in parallel to myself on Christmas eve. She has taken a different approach which requires a UART serial cable. Her guide can be found here.

What is this?

The Raspberry Pi Zero is a very cool little computer. At £4, is pretty amazing for the price. But one thing many Pi users have wanted to be able to do for a long time is program their Raspberry Pi from another computer, using only a single USB cable!

The Raspberry Pi Zero is able to do this, hardware wise anyway, although a lack of software support was holding up it ever happening. Until now!

So what can it do?

Using the Linux USB Gadget modules, we can get the Pi Zero to emulate a whole host of USB devices including

Virtual Serial – So can get a serial connection into the Pi, similar to using the UART pins. You can use Putty (on Windows) or Screen (on Mac and Linux).

Virtual Ethernet – You can get your Pi Zero to appear as a USB Ethernet modem. With a little configuration, you can then get full SSH, VNC, FTP etc.

Mass storage device – You can get the Pi Zero to appear as a flash drive, allowing you to for example, copy files over and have the Pi run these files (useful for robotics for example)

Virtual MIDI – The Pi Zero could appear as a virtual MIDI instrument.

Virtual Audio – The Pi Zero could appear as a virtual headphone output or microphone input.

Virtual Human Interface Device (HID) – The Pi Zero could appear as a virtual HID, for example a keyboard or mouse. So when you plug it into your computer, it could start typing!

You can also combine a few of the above (up to 3 at a time) using the g_multi module, although Windows and Mac have difficulty handling it then.

Examples

Where is this useful? Lets take an example of some Raspberry Pi robots in a classroom. Although you could be using Wifi for each robot, remembering addresses, unreliability with wifi etc all make wifi a bit of a rubbish answer.
With this, the student simply plugs in the robot and perhaps drops their script onto the flash drive that appears. When they unplug it, the robot runs the script, dumping the results of the script back onto the mass storage device, ready to be read when it is plugged in next.

Another example, lets say you don’t have access to a screen to use with your Raspberry Pi Zero, in for example, a school. You could still let your students play with GPIO or Linux by simply using the serial module (with Putty or Screen), or the virtual ethernet module to allow them SSH access.

65 thoughts on “Raspberry Pi Zero – Programming over USB! (Part 1)”

Thanks to all for this Christmas present which will make our favourite nano-computer even more accessible to everyone =o)

Bravo to all who’ve worked on both the idea and the technical side for PiZero USB OTG use : DaveB, Andrew M, Simon W, LadyAda and of course the RPFoundation for bringing us the Hardware in the first place !

This is just fantastic work Andrew – huge potential , I’ve had a go at this, mind you with a limited ‘skillset’. Bearing in mind it’s still Christmas – would it be possible for you to do a walkthrough on setting it up for a Mac ?? Experiencing a few problems connecting – not sure what I’m doing wrong if at all ?? Apple is notoriously difficult to deal with in terms of 3rd party access / setups as it is so ‘locked down’ ;(

It seems as if the last tar.gz-file is the same as the first. I have a Raspberry Pi Model A (and not Zero) and I then need files that are hard-coded to gadget mode, because the OTG-ID-pin is connected to ground, i.e. always host.

There is very little extra code added, simply makes use of the Linux Gadget drivers and a small tweak to the device tree files for the Zero.
There is now a pull request sitting ready to be merged with the 4.4.x kernel branch with all the changes – https://github.com/raspberrypi/linux/pull/1239

I am interested about using the Raspberry Pi as a MIDI instrument with g_midi, but I am struggling to find any sort of documentation on how this could be done. Do you know of any tutorials/guides that could get me started using g_midi?

The modules and instructions worked perfectly. I am digging the g_ether for my headless configuration of the zero and with DHCP turned on, its perfect. Thanks again, I even have apache loaded on it so I have portable web server.

Great guide, I was able to get all the components in the guide to work last night. One thing though, when I tried to modprobe the g_hid driver, it says it is not foumd. Was it not included in the kernel? Would it be possible to compile the driver and modprobe it? Thanks!

Unfortunately I am not aware of anyone actually getting it working on A+ yet, or any of the modules for that matter. It looks like there is an issue with the OTG ID pin not being connected. It is still work in progress from what I can gather.

Hi, I’m trying to get my new A+ to talk over USB OTG, but can’t seem to get another host to see it as a device using the full size A port, I believe the micro USB port is unconnected apart from the power pins – anybody found this issue?

I’m unable to make it work. My computer is running Win 10.
I’ve followed the g_ether method 2, but it doesn’t show up on windows. On rpi boot, I see:
[ 4.516265] systemd[1]: systemd-modules-load.service: main process exited, code=exited, status=1/FAILURE
[ 4.536829] systemd[1]: Failed to start Load Kernel Modules.
[ 4.544593] systemd[1]: Unit systemd-modules-load.service entered failed state.
This is after enabling it on a fresh Raspbian, with no issues before enabling it.

i would like to use it as a serial injector in order to be able to distinguish multiples of the same device, keyboard/mouse in my case. can one of the usb ports act as a hid slave while the other is the host for the keyboard/mouse and if so, how would i power the zero? just plug an active hub on the host side? or does it get enough power from the slave port to power itself and the keyboard/mouse? is it possible with this device or is there any other solution or device which would let me add a serial number to a usb device?

The power USB port on the Pi Zero is just that, only for power. You also can’t attach a hub to the Pi Zero and use it in slave mode. If using it in USB slave mode, the only USB device connected to it can be a single computer.
If is only serial you want, may want to look at doing that over UART over the GPIO pins with a single USB UART adapter.

CONNECTION REFUSED
Unfortunately, as of November 2016 (Raspbian Jessie), the SSH server is NOT RUNNING ‘out of the box’. The setup works perfectly but the connection is refused. It responds to pings.
By connecting by some other means and running raspi-config you can easily fix this. I did this and at the same time setup wifi and now connect that way so haven’t been back to a USB connection but I would have thought it should work.

I have been struggling with getting on speaking terms with my PI mod A – that is, one USB, power and HDMI ports. Target of course to be able to PUTTY / SSH it from my pc so I can develop with Netbeans using the A as build host.

(Doing the same for the Pi 2 was an easy stake, just configure fixed IP address for eth0 and set up the ethernet interface on my pc accordingly.)

After lots of tweaking (without any progress at all), I found that the simplest solution was to use an USB-to-Ethernet gadget that I happened to have around.

So: My solution to ssh into the Pi mod A is as follows:
Build: Latest Rasbian build of November -16
Configuration:
– In /boot/config.txt: Add dtoverlay=dwc2 somewhere at the bottom to enable the dwc2 overlay
– in /etc/modules: Add dwc2 on a line of its own to make the Pi use it
– In /etc/network/interfaces:
Comment out /delete the line
iface eth0 inet manual

Add the following lines to set a static IP for eth0
# Don’t know if this is neccessary. Doesn’t seem to do any harm, anyway
allow-hotplug eth0
# Configure the eth0 as having static IP
iface eth0 inet static
# If you have a DHCP router in your network, you better stay with the 169.254.x.x address space. Select freely.
address 169.254.82.220
netmask 255.255.255.0
# I set the default gateway to the IP of the ethernet I/F of my pc
gateway 169.254.82.2
# Don’t know if these are really neccessary either.
broadcast 169.254.82.255
network 169.254.82.0

Reboot, and ping the address from yout PC, which you have connected with an ordinary tp cable to the USB-to-Ethernet gadget

One peculiarity: This solution worked without enabling dwc2 too, as long as I had the HDMI cable connected to the Pi. When I disconnected it, the Pi responded some ten times to ping, end then the connection died. Enabling dwc2 soplved that problem.

Hello
I have two questions
1. is this possible with the new Raspberry Pi Zero W?

2. If the following possible?
I would like to setting the pi zero as an Mass storage device. Then plugged in into an Windows or Linux pc. Now I would like to share the folder of the mass storage device over the WiFi with an server.
Now when the pc change the folder of the mass storage device (adding remove or change a file) I would like to sync this with the server. And the other direction should be possible to! If the server send me a new file I would like to add it into the folder of the mass storage device. But I don’t like to plug off and on the Pi zero to show the new changed or removed
files on my windows or Linux pc.
Is this possible to do?
The problem about the windows or Linux pc is that I can’t install any software on it. So it must be like plugged in and work.

I’m not entirely sure how to do this, but you could use kpartx (you would need to install it, but it’s *much* easier to use than mountfs & mount) to mount the image, and add a script that either unmounts and remounts the image, or checks for a button press to reload.

When you mount the image on the Pi, the changes *should* show up- I’m not sure, entirely, as I haven’t played with it much. Also, if you want to make your life a little easier, consider using Linux to format the mass storage image as NTFS. While this adds some complexity to mounting it, it makes it a lot easier to transfer files from Windows.

I slightly misread your post- so If I get this right, you want:
pi0PCFileServer
and when the FileServer updates, you want the PC to update the files on the Pi0 when it’s plugged in.
Do you know any programming/scripting languages? That would help a lot.
Git may work…

Here’s what I did differently:
***I used g_multi instead of g_mass_storage
Mass Storage:
[fallocate] to create an empty [.img], named [piusb.img]
Didn’t run [mkdosfs]
A different forum user recommended modifying [/etc/rc.local] to add a delay to mounting the img: [
sudo nano /etc/rc.local
]
add in the area before “_IP […”: [
/bin/sleep 5 #pre-wait time
/sbin/modprobe g_multi file=piusb.img stall=0 host_addr=169.254.64.64
/bin/sleep 5 #post-wait time
]

Writing a script that you can run over serial/ssh to mount the image & download files could be useful, as would writing a script that downloads files w/ the ethernet part of g_multi when it’s connected to a PC.

I’m still working on this stuff myself- if I remember to, I’ll post an update for you.

Thanks for such a clear blogpost – helped me no end in getting started with g_mass_storage! Would really appreciate any light you can shine on the slight issue I’m having though…

I’ve got a Pi Zero W that I’m using in OTG/gadget mode. I’ve activated dwc2 USB, partitioned and formatted the file that is to be used as filesystem and loaded g_mass_storage (all as per your guide above!).

It’s working fine in Windows – I can connect and see the contents, add/delete files, eject and reconnect seeing changes fine. I can mount it in Raspbian to check contents and can also attach it to other devices and interact with it fine.

However, I’ve got some devices that are very picky about what USB devices they will connect to (basically only flash drives). The problem is the OTG mass storage is being identified as “File-Stor Gadget (Rev: 0404)”, which is causing it to be rejected.

I can successfully use a USB flash drive in the target devices and have scraped the vendor/product ID from it to see if I can mimic them via g_mass_storage.