macusb
rfswift macusb
Manage USB device passthrough on macOS via Lima QEMU VM.
Synopsis
# List USB devices on macOS host
rfswift macusb list
# Attach a USB device to the Lima VM
rfswift macusb attach --vid VENDOR_ID --pid PRODUCT_ID
# Detach a USB device from the Lima VM
rfswift macusb detach --vid VENDOR_ID --pid PRODUCT_ID
# List USB devices currently attached to the Lima VM
rfswift macusb vm-devices
# Check Lima VM status for USB passthrough
rfswift macusb statusThe macusb command manages USB device passthrough on macOS. Docker Desktop and Podman on macOS run their own Linux VMs that cannot forward USB devices into containers. Lima solves this by running a QEMU VM where USB devices can be hot-plugged via the QMP protocol.
How It Works
graph LR
A[macOS USB Device] -->|QMP hot-plug| B[Lima QEMU VM]
B -->|/dev/bus/usb| C[Docker inside Lima]
C -->|container| D[RF Swift Container]
On macOS, there are two container engine modes:
| Mode | Engine flag | USB access | Use case |
|---|---|---|---|
| Docker Desktop | --engine docker (default) |
No USB | General work, no RF hardware needed |
| Lima VM | --engine lima |
USB hot-plug | RF hardware, SDR dongles |
When you need USB devices in your containers, you must:
- Attach the device to the Lima VM with
macusb attach - Run your container with
--engine limaso it runs inside Lima’s Docker (where the USB device is visible)
Subcommands
| Subcommand | Description |
|---|---|
macusb list |
List all USB devices connected to the macOS host |
macusb attach |
Hot-plug a USB device into the Lima VM |
macusb detach |
Hot-unplug a USB device from the Lima VM |
macusb vm-devices |
List USB devices currently forwarded into the VM |
macusb status |
Check Lima installation, VM status, and QMP availability |
macusb list
List all USB devices connected to the macOS host using system_profiler. Shows device name, vendor ID, product ID, and serial number.
No additional options.
macusb attach
Hot-plug a USB device from the macOS host into the Lima QEMU VM.
Options:
| Flag | Description | Required | Example |
|---|---|---|---|
--vid STRING |
USB Vendor ID (hex) | Yes | --vid 0x1d50 |
--pid STRING |
USB Product ID (hex) | Yes | --pid 0x604b |
macusb detach
Hot-unplug a USB device from the Lima QEMU VM.
Options:
| Flag | Description | Required | Example |
|---|---|---|---|
--vid STRING |
USB Vendor ID (hex) | With --pid |
--vid 0x1d50 |
--pid STRING |
USB Product ID (hex) | With --vid |
--pid 0x604b |
--devid STRING |
QMP device ID | Alternative | --devid usb-1d50-604b |
You can detach by vendor/product ID pair or by the QMP device ID shown in vm-devices.
macusb vm-devices
List USB devices currently forwarded into the Lima VM via QMP info usb.
No additional options.
macusb status
Check the full USB passthrough setup:
- Lima installation
- rfswift VM instance status
- QMP socket availability
- Currently attached USB devices
No additional options.
Global Options
| Flag | Description | Default | Example |
|---|---|---|---|
--instance STRING |
Lima instance name | rfswift |
--instance myvm |
Examples
Complete SDR Workflow on macOS
# 1. Check that Lima is ready
rfswift macusb status
# 2. List USB devices to find your SDR
rfswift macusb list
# NAME VENDOR ID PRODUCT ID SERIAL
# HackRF One 0x1d50 0x604b 000000000000000...
# RTL2838UHIDIR 0x0bda 0x2838
# 3. Attach HackRF to the Lima VM
rfswift macusb attach --vid 0x1d50 --pid 0x604b
# 4. Verify it's in the VM
rfswift macusb vm-devices
# 5. Run container via Lima's Docker (where USB device lives)
rfswift --engine lima run -i penthertz/rfswift_noble:sdr_light -n sdr_work
# 6. Inside the container, the device is accessible
# $ hackrf_info
# Found HackRF ...
# 7. When done, detach the device
rfswift macusb detach --vid 0x1d50 --pid 0x604bAttaching Multiple Devices
# Attach RTL-SDR and HackRF
rfswift macusb attach --vid 0x0bda --pid 0x2838
rfswift macusb attach --vid 0x1d50 --pid 0x604b
# Run container with both devices available
rfswift --engine lima run -i penthertz/rfswift_noble:sdr_full -n multi_sdrUsing a Custom Lima Instance
# All macusb commands support --instance for non-default VMs
rfswift macusb list --instance my_custom_vm
rfswift macusb attach --vid 0x1d50 --pid 0x604b --instance my_custom_vm
rfswift --engine lima run -i sdr_light -n my_workSetup
Prerequisites
-
Lima and QEMU must be installed:
brew install lima qemu -
The Lima VM must use
vmType: qemu(notvz) for USB passthrough support.
First-Time Setup
RF Swift can auto-create the Lima VM on first use:
# Option 1: Let RF Swift create it automatically
rfswift --engine lima run -i penthertz/rfswift_noble:sdr_light -n my_sdr
# → Detects no Lima instance, creates one, installs Docker + udev rules, starts VM
# Option 2: Create manually with the bundled template
limactl create --name rfswift lima/rfswift.yaml
limactl start rfswiftThe auto-created VM includes:
- Docker engine inside the VM
- USB libraries (
libusb,libhidapi,libftdi) - Kernel modules for USB serial devices (
cp210x,ftdi_sio,ch341) - Udev rules for all common SDR/RF devices (HackRF, RTL-SDR, USRP, BladeRF, Airspy, PlutoSDR, LimeSDR, etc.)
Supported RF Devices
The Lima VM comes pre-configured with udev rules for:
| Device | Vendor ID |
|---|---|
| HackRF, Great Scott Gadgets | 0x1d50 |
| RTL-SDR (all variants) | 0x0bda |
| Ettus USRP (B200/B210/B100) | 0x2500, 0x3923, 0xfffe |
| Nuand BladeRF (v1/v2) | 0x2cf0 |
| Airspy, Airspy HF+ | 0x1d50, 0x03eb |
| ADALM-Pluto (PlutoSDR) | 0x0456, 0x2fa2 |
| LimeSDR | 0x0403, 0x1d50 |
| FTDI devices (probes, serial) | 0x0403 |
| STM32 (VNA, bootloaders) | 0x0483 |
| FUNcube Dongle | 0x04d8 |
Customizing the Lima VM
The Lima VM is configured via a YAML file. RF Swift ships a default template at lima/rfswift.yaml, and once created, the instance config lives at ~/.lima/rfswift/lima.yaml.
Editing the Configuration
# Before creating the VM — edit the template
vim lima/rfswift.yaml
limactl create --name rfswift lima/rfswift.yaml
# After creating — edit the live config (requires VM restart)
vim ~/.lima/rfswift/lima.yaml
limactl stop rfswift && limactl start rfswift~/.lima/rfswift/lima.yaml, you must stop and start the VM for changes to take effect. Changes to provision scripts only run on first creation — use limactl shell rfswift to run commands in an existing VM.Configuration Reference
Here are the key settings you can tune:
VM Resources
Increase CPUs, memory, or disk for heavier workloads (e.g., srsRAN 5G, large IQ captures):
cpus: 8 # default: 4
memory: "16GiB" # default: 8GiB
disk: "200GiB" # default: 100GiBVM Backend
Must be qemu for USB passthrough. Do not change to vz:
vmType: qemu # required — Apple Virtualization (vz) has no USB supportHost Directory Mounts
Add extra host directories accessible inside the VM:
mounts:
- location: "~"
writable: true
- location: "/tmp/lima"
writable: true
# Add your own:
- location: "/Volumes/ExternalSSD/captures"
writable: true
mountPoint: "/captures"Port Forwarding
Forward additional ports from the VM to the macOS host:
portForwards:
# Docker socket (required — do not remove)
- guestSocket: "/run/docker.sock"
hostSocket: "{{.Dir}}/sock/docker.sock"
# noVNC desktop
- guestPort: 6080
hostPort: 6080
# PulseAudio
- guestPort: 34567
hostPort: 34567
# Add your own — e.g., srsRAN web UI
- guestPort: 7681
hostPort: 7681
# Jupyter notebook
- guestPort: 8888
hostPort: 8888Guest OS Image
Change the base Linux image (default is Ubuntu 24.04):
images:
- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-amd64.img"
arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/releases/24.04/release/ubuntu-24.04-server-cloudimg-arm64.img"
arch: "aarch64"DNS
dns:
- 8.8.8.8
- 8.8.4.4Adding Custom Udev Rules
If you have RF hardware not covered by the defaults, add udev rules in the provision section or directly inside the running VM:
# Option 1: Add to the YAML template before creation
# In the provision → system script section, add:
cat > /etc/udev/rules.d/99-custom.rules << 'UDEV'
SUBSYSTEMS=="usb", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", MODE="0666"
UDEV
udevadm control --reload-rules && udevadm trigger
# Option 2: Add to an already running VM
limactl shell rfswift -- sudo bash -c '
echo "SUBSYSTEMS==\"usb\", ATTRS{idVendor}==\"xxxx\", ATTRS{idProduct}==\"yyyy\", MODE=\"0666\"" \
> /etc/udev/rules.d/99-custom.rules
udevadm control --reload-rules && udevadm trigger
'Replace xxxx and yyyy with your device’s vendor and product IDs (find them with rfswift macusb list).
Adding Custom Kernel Modules
The default template loads common USB serial modules. To add more:
# Load a module in the running VM
limactl shell rfswift -- sudo modprobe <module_name>
# Make it persistent
limactl shell rfswift -- sudo bash -c \
'echo "<module_name>" >> /etc/modules-load.d/rfswift.conf'Installing Additional Packages
Need extra tools inside the VM (outside of containers)?
limactl shell rfswift -- sudo apt install -y <package_name>Recreating the VM from Scratch
If the VM becomes misconfigured, delete and recreate:
limactl stop rfswift
limactl delete rfswift
# Recreate from template (or let RF Swift auto-create on next run)
limactl create --name rfswift lima/rfswift.yaml
limactl start rfswift~/rfswift-workspace/) or Docker images — those live on the host.Using a Custom Template Location
RF Swift searches for the Lima template in these locations (in order):
<rfswift-binary-dir>/lima/rfswift.yaml<rfswift-binary-dir>/../lima/rfswift.yaml~/.config/rfswift/lima.yaml~/.rfswift/lima.yaml
To use your own customized template by default, place it at ~/.config/rfswift/lima.yaml:
cp lima/rfswift.yaml ~/.config/rfswift/lima.yaml
vim ~/.config/rfswift/lima.yaml # customizeRF Swift will use this template when auto-creating the VM on first --engine lima run.
Troubleshooting
Lima Not Installed
Problem: macusb commands fail because Lima is not installed
Solution:
brew install lima qemuQMP Socket Not Found
Problem: macusb status reports no QMP socket
Solution: Your Lima VM must use vmType: qemu. The Apple Virtualization framework (vmType: vz) does not support USB passthrough.
# Check your VM config
cat ~/.lima/rfswift/lima.yaml | grep vmType
# Should show: vmType: qemu
# If it shows vz, recreate with QEMU:
limactl delete rfswift
limactl create --name rfswift lima/rfswift.yaml
limactl start rfswiftDevice Not Visible in Container
Problem: Device attached via macusb attach but not visible in the container
Solution: Make sure you’re using --engine lima:
# Wrong: runs in Docker Desktop (no USB access)
rfswift run -i sdr_light -n my_sdr
# Correct: runs in Lima's Docker (USB devices visible)
rfswift --engine lima run -i sdr_light -n my_sdrAttach Fails with Permission Error
Problem: macusb attach returns a QMP error
Solution: QEMU USB passthrough may require elevated permissions on macOS:
# Check if the Lima VM is running
rfswift macusb status
# Restart the VM if needed
limactl stop rfswift && limactl start rfswiftRelated Commands
--engine- Select container engine (use--engine limafor USB)winusb- USB management on Windows/WSL2bindings- Device bindings on Linuxrun- Create containersdoctor- Diagnose environment (includes Lima checks on macOS)
brew install lima qemu). The VM must use vmType: qemu for USB passthrough support.winusb.rfswift --engine lima run ... when you need USB devices in your containers. Without --engine lima, containers run in Docker Desktop which has no USB access.