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

Part 2 to this post can be found here.

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.


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.

How to I set it up on my Raspberry Pi?

I have thrown together a guide over on Github Gists, including links to the downloadable precompiled kernels.

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

  1. It’s like opening the last door on an Advent calendar !

    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 !

    Joyeux Noël et bonnes fêtes!

  2. 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’ ;(

  3. 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.

  4. 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?


  5. Cool stuff ! Like David I’m interested in the HID thing. What prevented you from including the g_hid driver in the kernel? Any advice how we could do that ourselves would be appreciated.

  6. 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.

  7. Thanks for helping me go networking on my pi zero.

    What is the correct set up on pi zero and host linux, what needs to be append to the end of /etc/network/interfaces using address on the pi?

    This seems to work fine for me, but should I be using
    a netmask of and
    pi zero /etc/network/interfaces

    allow-hotplug usb0
    iface usb0 inet static

    My debian linux /etc/network/interfaces

    allow-hotplug usb0
    iface usb0 inet static
    up iptables -A POSTROUTING -t nat -j MASQUERADE -s
    up sysctl -w net.ipv4.ip_forward=1
    up route add -host usb0
    down iptables -D POSTROUTING -t nat -j MASQUERADE -s

    Got some info from

  8. 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!

    1. Only on the data port. You can only use the power port for power unfortunately, its data lines aren’t connected to anything.

      1. Hi,
        sorry for my ignorance, but are this data lines hardware or software? If it were software there would be the possibility of programming it as the data port

  9. Has anyone managed to get the g_mass_storage module working with the pi a+ model? Is it even possible? Any help or knowledge would be highly appreciated. Thanks!

    1. 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.

  10. I’m having difficulty setting up usb0 to have a static IP address to connect to. I’m only using the g_ether module.

    I’m using the Raspberry Pi Zero as a LAMP server, with PHP.

    For the laptop, I am using Arch with XFCE. Is there a way I can set a unique address to the Raspberry Pi?

    1. Don’t worry – solved my own issue!

      In XFCE / distros that use nm-connection-editor, you need to make a new Ethernet Interface. Call it whatever you want, and under the “IPv4” tab, for the Method, select “Link-Local Only”.

      It probably automatically created the interface for me, but I must’ve deleted it when I was tinkering with my own network.

      Great guide, by the way! This’ll be extremely useful when developing my PHP scripts!

  11. Followed the g_ether instructions and all ok, the Zero is powered and sat at the prompt after connecting from the USB on the laptop.

    I can’t seem to SSH though – assuming it’s the port number (default 22 not working) – likely I’m missing the obvious (new to a lot of this). Should I be using a different port number?

    Many thanks for a great tutorial!

    1. Just figured out, how to make it work on minibian:

      1) using 1 GB microsd
      2) apt-get update
      3) apt-get install raspi-config
      4) run raspi-config and resize partition
      5) reboot
      6) apt-get install rpi-update
      7) BRANCH=next rpi-update
      8) reboot
      9) add “dtoverlay=dwc2” in /boot/config.txt
      10) add “dwc2” in /etc/modules
      11) add “g_serial” in /etc/modules
      12) reboot
      13) systemctl enable getty@ttyGS0.service
      14) systemctl start getty@ttyGS0.service
      15) edit /etc/securetty and add ttyGS0 at the end
      15) reboot

      Now I can connect my pi zero via microusb cable to PC, Windows 8.1 detected and created ELMO GMAS (COM5) and I can connect via Putty.

  12. Hello,

    i have updated to the new raspbian release of 2016-02-09 and the USB- Gadget isn’t working…can anyone confirm that or hast anyone a solution?


  13. Hello,

    after the new offical raspberry update (2016-02-09), the gadget mode isn´t working! Kernel 4.4.1+

    Can anyone confirm the problem or have anyone a Solution?


  14. 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?

  15. What happens with the OTG ethernet setting if I decide I actually want to boot up with a USB ethernet adapter or wifi dongle instead?

  16. I’m very interested in using the RPi zero to power a custom game controller. Getting it to behave as a HID sounds ideal.
    Once I have loaded the g_hid driver, how would I send commands to it?

    If I can work that out, then mapping GPIO inputs to g_hid outputs would allow me to construct a controller.

  17. 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.

  18. 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?

    1. 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.

    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.

  20. thanks for that article –
    I want to add an ethernet module to the Pi Zero (something like the ENC28J60) to build an USB mass storage, which file system, I could modify through ethernet.

    would anyone have pointer to do this or concern in its feasability?

  21. Could something like this be used to make the PI act as a custom device that talks to a computer provided that I am willing to write a driver for it?

  22. Hi,

    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
    – 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.
    # I set the default gateway to the IP of the ethernet I/F of my pc
    # Don’t know if these are really neccessary either.

    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.

  23. I have a project on the RPi 3 for which this kind of functionality would be extremely useful.

    Would it be possible to set up this kind of functionality for the Pi 3, or is it something specific to the hardware of the Pi 0?

    Please let me know. Thanks!

    1. It is unfortunately only an option for the Pi Zeros, as the full sized Pis (like Pi 3) have the USB LAN hub chip in the way.

  24. 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.

    Please let me now. Thank you.

    1. 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.

      1. I slightly misread your post- so If I get this right, you want:
        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=
        /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.

  25. Hi Andrew

    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.

    I have therefore adjusted modprobe to the following:

    sudo modprobe g_mass_storage file=/home/pi/piusb.bin stall=0 removable=1 idVendor=0x0781 idProduct=0x5572 bcdDevice=0x011a iManufacturer=”SanDisk” iProduct=”Cruzer Switch” iSerialNumber=”1234567890″

    Unfortunately this doesn’t seem to make any difference to how it is presented to the device.

    When connecting to Windows, here’s what the USB mass storage displays:


    & here’s what SanDisk shows (what I’m wanting to emulate):


  26. thanks for the article
    i try to use my pi zero as usb mass storage
    it’s work fine and window(seven) find usb storage as “drive A”

    i try to increase the size of the disk and the value of count in
    “dd if=/dev/zero of=/piusb.bin bs=512 count=2880”
    if count is bigger than 2880 then window did’nt find anymore
    the usb gadget

    have you an idea to incrise the disk space??

    sorry for my english


  27. Could this be used to pass an ISCSI device to a device that does not have the ability to directly connect to an ISCSI device? My scenario is I have a Freenas set up with about 20 Terabytes storage (about half of that currently free). What I would like is to have the PiZero connected via USB to my XBox One (which I believe supports USB storage for games and media) and use that as additional storage for my XBox One (and get the additional tolerances of ZFS).

  28. I have several embedded systems, and need to update their programming regularly. To update them, they would traditionally have a USB stick plugged in which contained the new programming file. The stick would be unplugged once the new file has been read to memory and the system is good to go.

    It would seem a Pi Zero could be my ideal link in the system if I configured it to behave as a Mass Storage device and equipped it with a WiFi connection.
    I have a few basic questions, if you wouldn’t mind helping!
    1 – would this guide apply the same to a Pi Zero W as a Pi Zero? 2 – can the parameters (for example, whether it is mounted as a drive or not) be altered remotely? (allowing me to make the USB drive emulated by the Pi exist or not exist on command)
    3 – would the Pi be connected to a USB host via the micro-USB port onboard, or via other pins, in order to act as a USB device? If so, can the 5VDC input be supplied to the board by some other route than that port? My USB hosts have a very limited USB 5V power output

    1. I’d probably suggest connecting the Pi over wifi in order to do that. SSH in and you’re gold.

      You can supply power over the GPIO pins on Pis. You’d probably want to solder the cables onto a Zero though as there are no posts.

  29. When you first get a Pi Zero the big question is — how do you access it? You can get a powered USB hub, USB keyboard, USB mouse and HDMI adapter. Or you can just plug it into your computer directly and access it over USB using ssh.

  30. Hi!
    I need help with this.
    I have a CNC machines that the only way to transfer text files ( G code), is from the usb port with a normal usb memory, so i want to connect this raspberry pi zero and lcd touch to emulate a usb memory in the port of the machine.
    So i want to access with touch connected to a wifi and download files from the server then put this files in a folder that its sharing trough usb port.
    It is possible?.
    I read this ” 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) ”
    Thanks for your help

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.