Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transport Templates

A transport template is a prepackaged .vhb that gives you everything above the device-specific behavior for one communication mode — the intercept targets, the syscall vocabulary, the decode schemas, and a dump-and-default TCL stub for every call — so you only fill in the logic that makes your device your device.

Importing a template is one action: File → New from Template. You pick a transport, EMU opens a fresh unsaved session pre-wired with that transport’s targets, embedded schemas, and stubs. Run your unmodified target application against it and every intercepted call prints its decoded fields; turn the mock into a working device by editing only the marked USER-LOGIC sections.

Bundled transports

TemplateIntercept targetClass
usb/dev/bus/usb/*/* (usbfs ioctls incl. async URB submit/reap)device-file
i2c/dev/i2c-* (I2C_RDWR, I2C_SMBUS, slave/funcs)device-file
spi/dev/spidev* (mode/speed/bits, SPI_IOC_MESSAGE)device-file
tty/dev/ttyS*, ttyUSB*, ttyACM* (termios, modem lines)device-file
hidraw/dev/hidraw* (report descriptor + report streams)device-file
socket-inetAF_INET / AF_INET6 TCP/UDPsocket-family
wifi-nl80211AF_NETLINK/NETLINK_GENERIC → nl80211socket-family
bluetooth-hciAF_BLUETOOTH/BTPROTO_HCIsocket-family
socketcanAF_CAN/CAN_RAWsocket-family

Intercept target syntax

Device-file transports target glob patterns (e.g. /dev/bus/usb/*/*, /dev/ttyUSB*). Socket-family transports use the socket: prefix: socket:AF_FAMILY or socket:AF_FAMILY/PROTOCOL, for example socket:AF_CAN/CAN_RAW or socket:AF_NETLINK/NETLINK_GENERIC. A family-only spec matches any protocol of that family.

Anatomy of a template

A template is authored as a source directory and compiled with certo emu package-template:

templates/usb/
  manifest.json                 # targets, headers, and the syscall list
  tcl/
    _dict_printer.tcl           # shared decode-and-print helper (inlined)
    open_template.tcl           # one dump-and-default stub per syscall
    USBDEVFS_SUBMITURB_template.tcl
    ...

manifest.json names the intercept targets, the kernel headers to scan for decode schemas, and each syscall (its type, the ioctl/ schema it decodes, and the stub file that handles it). The packager scans the headers, embeds the resulting schemas directly in the .vhb, and inlines each stub as the syscall’s TCL — so the produced file is fully self-contained and loads like any project.

Async transports and the waker

Asynchronous transports (USB URBs, netlink, HCI events) split one operation across a submit syscall and a later collect syscall. The stubs hold the completion in device-model state and hand it back on collect. When the target blocks in poll/epoll between the two calls, the stub announces readiness with certo_set_ready_in; see Asynchronous Readiness.

Extending a template into a real device

Each stub prints the decoded call and returns a permissive default, with the spot you edit clearly marked:

# i2c :: I2C_SMBUS — SMBus byte/word/block transfer.
set req_addr [lindex $certo::arguments 2]
set smbus [::certo::dump_struct i2c_smbus_ioctl_data $req_addr "smbus"]

# --- USER-LOGIC: implement your register map -----------------------------------
# On a read, write the register value back through the data union pointer.
# -------------------------------------------------------------------------------

certo_set_return_value 0

Device state lives in your own model variables (the stubs use globals like ::usb_pending_urbs as a starting point). See the TCL API Reference for the decode, memory, and return-value helpers available inside a stub.