Android USB Gadget

Introduction

Android USB Gadget is a feature that allows an Android device to act as a USB peripheral device. This means that the Android device can emulate various USB devices such as keyboards, mice, game controllers, and even storage devices like USB flash drives.

In this article, we will explore how to use the Android USB Gadget feature and provide some code examples to illustrate its usage.

Prerequisites

To follow along with the examples in this article, you will need the following:

  • An Android device running Android 10 (API level 29) or above.
  • Android Studio installed on your development machine.

Setting Up USB Gadget

Before we dive into the code examples, let's first set up the USB Gadget feature on our Android device.

  1. Enable Developer Options on your Android device. To do this, go to Settings -> About phone and tap on the Build number seven times. This will enable the Developer Options menu.

  2. Enable USB debugging. In the Developer Options menu, enable USB debugging by toggling the switch.

  3. Connect your Android device to your development machine using a USB cable.

  4. Open Android Studio and launch the Android Device Manager.

  5. In the Android Device Manager, select your connected Android device and click on the Enable USB Debugging button.

Creating a USB Gadget

To create a USB Gadget, we need to define a configuration file that describes the USB interfaces and endpoints supported by the device. We can then load this configuration file onto the Android device to enable the USB Gadget feature.

Let's create a simple USB Gadget that emulates a keyboard. We will define a single USB interface with an endpoint for keyboard events.

// KeyboardGadget.java
public class KeyboardGadget implements UsbGadget {

    private static final int KEYBOARD_INTERFACE_ID = 0;
    private static final int KEYBOARD_ENDPOINT_ID = 1;

    @Override
    public void configure() {
        // Create a configuration with a single interface
        UsbConfiguration configuration = new UsbConfiguration(1);

        // Create a keyboard interface
        UsbInterface keyboardInterface = new UsbInterface(KEYBOARD_INTERFACE_ID);

        // Create a keyboard endpoint
        UsbEndpoint keyboardEndpoint = new UsbEndpoint(KEYBOARD_ENDPOINT_ID);

        // Add the endpoint to the interface
        keyboardInterface.addEndpoint(keyboardEndpoint);

        // Add the interface to the configuration
        configuration.addInterface(keyboardInterface);

        // Set the configuration on the USB device
        UsbDevice.setConfiguration(configuration);
    }

    @Override
    public void start() {
        // Start emulating the keyboard
        // ...
    }

    @Override
    public void stop() {
        // Stop emulating the keyboard
        // ...
    }
}

To load the USB Gadget configuration onto the Android device, we need to use the adb command-line tool. Open a terminal window and run the following command:

$ adb shell su -c 'echo "g1" > /sys/kernel/config/usb_gadget/android/functions'
$ adb shell su -c 'echo "0x1234" > /sys/kernel/config/usb_gadget/android/idProduct'
$ adb shell su -c 'echo "0xabcd" > /sys/kernel/config/usb_gadget/android/idVendor'
$ adb shell su -c 'echo "keyboard" > /sys/kernel/config/usb_gadget/android/strings/0x409/serialnumber'
$ adb shell su -c 'echo "Keyboard Gadget" > /sys/kernel/config/usb_gadget/android/strings/0x409/manufacturer'
$ adb shell su -c 'echo "Keyboard" > /sys/kernel/config/usb_gadget/android/strings/0x409/product'
$ adb shell su -c 'echo "1" > /sys/kernel/config/usb_gadget/android/configs/c.1/MaxPower'
$ adb shell su -c 'ln -s /sys/kernel/config/usb_gadget/android /dev/usb-ffs/android'
$ adb shell su -c 'echo "cdc_acm" > /sys/kernel/config/usb_gadget/android/configs/c.1/strings/0x409/configuration'
$ adb shell su -c 'echo "acm.usb0" > /sys/kernel/config/usb_gadget/android/configs/c.1/strings/0x409/function'
$ adb shell su -c 'echo "usb0" > /sys/class/android_usb/android0/f_rmnet/instance'
$ adb shell su -c 'echo "1" > /sys/kernel/config/usb_gadget/android/os_desc/use'
$ adb shell su -c 'echo "0xcd" > /sys/kernel/config/usb_gadget/android/os_desc/b_vendor_code'
$ adb shell su -c 'echo "1" > /sys/kernel/config/usb_gadget/android/os_desc/b_vendor_code'
$ adb shell su -c 'echo "0x0100" > /sys/kernel/config/usb_gadget/android/os_desc/w_bcdDevice'

$ adb shell su -c 'mkdir -p /storage/usbgadget/keyboard'
$ adb shell su -c 'mount -t functionfs android /storage/usbgadget/keyboard'
$ adb shell