USB Gadget Scripts
Found under IO on the device's panel list.
niceusb
Turns the FreeWili 2 into a USB gadget that a host PC sees as a real keyboard
(or mouse, gamepad, or a device of your own design) and plays a script into it.
A script is a .wusb text file on the SD card: it picks what kind of device to
be and what to type or send once the host has enumerated it.
This screen lists the scripts under \niceusb\ on the card and starts the one
you pick. Starting a gadget borrows the radio's PIO block, so while it is
attached SubGHz is locked out; stopping it hands the radio back.
Controls
| Button | Action |
|---|---|
| Up and Down | move through the list |
| Center or OK | start the highlighted script |
| Green | edit the highlighted script in the text editor |
| Blue | demo - run the built-in example with no card file |
| Cancel | this help page |
There is no start button and no exit button: Center starts the highlighted script directly, and HOME leaves the app. Red does nothing here.
Where scripts live
Scripts are .wusb files under \niceusb\ on the SD card. Drop one in from a
PC and it shows up in the list; the example pack ships under category folders
like \niceusb\1-keyboard\. A file is plain text, so it opens in any editor
on a PC and in the on-device editor with Green.
What happens when you start one
The screen switches to the gadget screen and stays there until the gadget stops. The host enumerates the device, and the script's body runs once, the moment enumeration finishes - this is the autorun. It runs exactly once per attach, so a keyboard script types its text one time, not on a loop.
Stop the gadget from the console menu (below). Unplugging the USB cable also ends the session.
The console menu
Everything the screen does, and the settings it cannot show, live on the serial console under IO > niceusb:
| Key | Action |
|---|---|
| s | Start Gadget - bring the selected script up |
| t | Stop Gadget |
| i | Status - state, enumeration, selected script, last error |
| r | Run Test Script - type a built-in two-line proof |
| c | Script - the selected .wusb path on the card |
| o | Force VID/PID - override the identity (on/off) |
| v | VID - the forced vendor id, in hex |
| p | PID - the forced product id, in hex |
Start answers immediately; the script is read from the card a moment later, so watch Status for the outcome rather than the start line.
Identity and the override
A device's identity is its vendor id (VID) and product id (PID). By default the
gadget presents FreeWili's own VID and a built-in PID for the personality. A
script may declare its own VID/PID in a device_descriptor block, and that
wins over the default. Turning Force VID/PID on overrides both - it beats a
script's own descriptor - so you can pin an identity without editing the file.
Writing a script
The first thing a script does is pick a personality:
device keyboard
type "Hello from FreeWili"
key tap ENTER
device takes keyboard, mouse, gamepad, or hid. type sends a string,
key tap NAME presses and releases a named key (ENTER, TAB, and so on), and
delay 3s waits between actions so the host keeps up.
To present your own descriptors, use device hid and supply the raw bytes:
device hid
device_descriptor {
12 01 00 02 00 00 00 40 3C 09 04 20 00 01 01 02 03 01
}
hid_descriptor {
05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
75 01 95 08 81 02 95 01 75 08 81 03 C0
}
One rule ties these together: type and the key verbs need device keyboard,
and custom descriptors need device hid, so a single script cannot both
declare its own descriptors and type. A custom-descriptor script defines the
identity; a keyboard script does the typing.
A script must be under 4096 bytes.
When something is wrong
A start that cannot run says why and leaves the gadget stopped with the radio still available, rather than coming up as something unexpected:
- script not found - the selected path is not on the card.
- script larger than 4096 bytes - trim it.
- a malformed script (bad hex in a descriptor, or an unknown command) refuses to attach and reports the failing line in Status under last error.
Status always shows the last error, so a script that enumerated but did the wrong thing still leaves a trail there.
See also: USB Gadget — the console/GUI commands for this panel.