usb_gadget 0.3.0 copy "usb_gadget: ^0.3.0" to clipboard
usb_gadget: ^0.3.0 copied to clipboard

retracted

Expose standard or fully custom USB peripherals (gadgets) through a USB device controller (UDC) on Linux.

usb-gadget #

Important

This library is experimental and not suitable for production use. Breaking changes may occur without warning.

A comprehensive Dart library for creating USB gadgets on Linux using ConfigFS and FunctionFS. Transform your Linux device into a USB peripheral—implement keyboards, mice, storage devices, network interfaces, or create entirely custom USB protocols in pure Dart.

pub package License: Apache 2.0

Features #

Kernel-Based Functions #

Pre-configured USB functions implemented by kernel drivers, ready to use with minimal setup:

Network Interfaces

  • CDC ECM - Ethernet over USB (widely supported)
  • CDC ECM Subset - Simplified ECM for legacy hosts
  • CDC EEM - Ethernet Emulation Model (lowest overhead)
  • CDC NCM - Network Control Model (high performance)
  • RNDIS - Remote NDIS (Windows compatibility)

Serial Ports

  • CDC ACM - Abstract Control Model (standard virtual serial)
  • Generic Serial - Non-CDC serial implementation

Human Interface Devices

  • HID - Keyboards, mice, gamepads, and custom HID devices

Storage & Media

  • Mass Storage Device (MSD) - USB flash drive emulation
  • Printer - USB printer class device

Audio & Video

  • MIDI - Musical Instrument Digital Interface
  • UAC1 - USB Audio Class 1.0
  • UAC2 - USB Audio Class 2.0
  • UVC - USB Video Class (webcam emulation)

Testing & Development

  • Loopback - Data loopback for testing
  • SourceSink - Pattern generation and validation

FunctionFS (Custom USB Functions) #

FunctionFS provides complete control over USB functionality in userspace, enabling you to:

  • Define custom USB descriptors - Create devices with any interface, endpoint configuration, or capability
  • Handle USB endpoints directly - Full control over data transfer, timing, and flow control
  • Implement custom protocols - Build proprietary or specialized USB communication protocols
  • Process control requests - Handle vendor-specific, class-specific, or standard USB requests
  • React to USB events - Respond to bind, unbind, enable, disable, suspend, and resume events

Ideal for:

  • Complex HID devices with custom report descriptors
  • Proprietary USB protocols and interfaces
  • USB device prototyping and experimentation
  • Devices requiring precise timing or advanced USB features
  • Applications needing complete protocol control

The library includes HIDFunctionFs as a specialized FunctionFS implementation with built-in HID protocol handling, making custom HID devices straightforward to implement.

Requirements #

Platform Support #

  • Operating System: Linux with USB Device Controller (UDC) support
  • Architecture: ARM, ARM64, x86_64 (any architecture with Linux UDC support)
  • Dart SDK: 3.10.0 or higher

Hardware Requirements #

A Linux device with a USB Device Controller (UDC) is required. Standard desktop PCs typically do not include a UDC—they only have USB host controllers.

Compatible devices include:

  • Raspberry Pi 4, Pi Zero (USB-C or micro-USB port)
  • Raspberry Pi 5 (USB-C port)
  • Orange Pi, Banana Pi (model-dependent)
  • BeagleBone Black, BeagleBone AI
  • Most embedded Linux boards with USB OTG capability

To check if your device has a UDC:

ls /sys/class/udc/
# Should list one or more UDC devices (e.g., fe980000.usb)

System Dependencies #

Install the Linux Asynchronous I/O library:

Debian/Ubuntu:

sudo apt-get install libaio-dev

Arch Linux:

sudo pacman -S libaio

Fedora/RHEL:

sudo dnf install libaio-devel

Linux Kernel Configuration #

The following kernel options must be enabled. Most modern embedded Linux distributions include these by default.

Required Kernel Configuration Options

Core USB Gadget Support:

  • CONFIG_USB_GADGET - USB Gadget framework
  • CONFIG_USB_CONFIGFS - ConfigFS-based gadget configuration
  • CONFIG_USB_FUNCTIONFS - FunctionFS support

Kernel Function Drivers:

  • CONFIG_USB_CONFIGFS_SERIAL - Serial functions
  • CONFIG_USB_CONFIGFS_ACM - CDC ACM serial
  • CONFIG_USB_CONFIGFS_NCM - CDC NCM ethernet
  • CONFIG_USB_CONFIGFS_ECM - CDC ECM ethernet
  • CONFIG_USB_CONFIGFS_ECM_SUBSET - ECM Subset ethernet
  • CONFIG_USB_CONFIGFS_RNDIS - RNDIS ethernet
  • CONFIG_USB_CONFIGFS_EEM - CDC EEM ethernet
  • CONFIG_USB_CONFIGFS_MASS_STORAGE - Mass storage
  • CONFIG_USB_CONFIGFS_F_HID - HID functions
  • CONFIG_USB_CONFIGFS_F_PRINTER - Printer function
  • CONFIG_USB_CONFIGFS_F_MIDI - MIDI function
  • CONFIG_USB_CONFIGFS_F_UAC1 - Audio Class 1.0
  • CONFIG_USB_CONFIGFS_F_UAC2 - Audio Class 2.0
  • CONFIG_USB_CONFIGFS_F_UVC - Video Class

Check your kernel configuration:

zcat /proc/config.gz | grep -E 'CONFIG_USB_(GADGET|CONFIGFS|FUNCTIONFS)'
# or
grep -E 'CONFIG_USB_(GADGET|CONFIGFS|FUNCTIONFS)' /boot/config-$(uname -r)

Permissions #

Root privileges or the CAP_SYS_ADMIN capability are required to configure USB gadgets.

Verify ConfigFS is mounted:

mount | grep configfs
# Should show: configfs on /sys/kernel/config type configfs (rw,relatime)

Mount ConfigFS if needed:

sudo mount -t configfs none /sys/kernel/config

Running without full root (using capabilities):

# Grant CAP_SYS_ADMIN to your Dart executable
sudo setcap cap_sys_admin+ep /path/to/your/dart/executable

Installation & Usage #

Add the Package #

dart pub add usb_gadget

Basic Example: USB Keyboard #

This example creates a USB HID keyboard that types "hello world" when connected:

import 'dart:io';
import 'dart:typed_data';

import 'package:usb_gadget/usb_gadget.dart';

final _descriptor = Uint8List.fromList([0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x19, 0xE0, 0x29, 0xE7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00, 0x25, 0x65, 0x05, 0x07, 0x19, 0x00, 0x29, 0x65, 0x81, 0x00, 0xC0]);

class Keyboard extends HIDFunction {
  Keyboard()
    : super(
        name: 'keyboard',
        descriptor: _descriptor,
        protocol: .keyboard,
        subclass: .boot,
        reportLength: 8,
      );

  void sendKey(int keyCode, {int modifiers = 0}) => file
    ..writeFromSync(
      Uint8List(8)
        ..[0] = modifiers
        ..[2] = keyCode,
    )
    ..writeFromSync(Uint8List(8));
}

Future<void> main() async {
  final keyboard = Keyboard();
  final gadget = Gadget(
    name: 'hid_keyboard',
    idVendor: 0x1234,
    idProduct: 0x5679,
    deviceClass: .composite,
    deviceSubClass: .none,
    deviceProtocol: .none,
    strings: {
      .enUS: const .new(
        manufacturer: 'ACME Corp',
        product: 'USB Keyboard',
        serialnumber: 'KB001',
      ),
    },
    config: .new(functions: [keyboard]),
  );

  try {
    await gadget.bind();
    await gadget.awaitState(.configured);
    // An additional delay here prevents the first few keypresses from
    // being missed on some hosts.
    await Future<void>.delayed(const .new(milliseconds: 100));
    [0x0B, 0x08, 0x0F, 0x0F, 0x12, 0x2C, 0x1A, 0x12, 0x15, 0x0F, 0x07, 0x28]
    // Write "hello world\n"
    .forEach(keyboard.sendKey);
    stdout.writeln('Ctrl+C to exit.');
    await ProcessSignal.sigint.watch().first;
  } finally {
    await gadget.unbind();
  }
}

Running Your Gadget #

Standard execution (requires root):

sudo dart run bin/your_app.dart

Compiled executable:

dart compile exe bin/your_app.dart -o keyboard
sudo ./keyboard

With debug logging:

dart compile exe -DUSB_GADGET_DEBUG=true bin/your_app.dart -o keyboard
sudo ./keyboard

More Examples #

The examples directory contains ready-to-run implementations:

Resources #

0
likes
0
points
675
downloads

Publisher

unverified uploader

Weekly Downloads

Expose standard or fully custom USB peripherals (gadgets) through a USB device controller (UDC) on Linux.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

ffi, meta, using

More

Packages that depend on usb_gadget