Repository navigation
Releases
v0.7.2
Changed
- Firmware: frames to the host are queued, not written in place.
firmware/common/tx.cencodes each
frame into one of two rings (one for the USB side, one for the receive side) and feeds the UART
from them;hal_uart_writeis replaced byhal_uart_tx_start,hal_uart_tx_busyand
hal_uart_tx_wait_done. On the RP2040 and RP2350 the UART output is a DMA channel and the
critical section around every write is gone: before, anEP_OUTframe, an event or a control data
stage written by the USB core spun on the UART byte by byte with interrupts off on that core, so the
target's IN transfers waited for it. The other ports send from the CPU insidehal_uart_tx_startas
before. Each port'smimusb_limits.hstatesMIMUSB_TX_RING_BYTESandMIMUSB_TX_RX_RING_BYTES
(the build stops when they are missing; testsmissing_*_limit). The ring replaces the 2 KiB
long-frame buffer of the USB side. - Firmware: an
ASKrule on a host-to-device request with a data stage no longer stops the USB side while
the host decides. The vendor callback of the data stage returns at once and the board keeps the
status stage the stack asks for until the verdict is in (mimusb_control_hold_status); reports on
the other endpoints go out meanwhile.mimusb_control_set_single_contextis gone, since nothing
waits any more. The wire protocol is unchanged. - Firmware: the queue's lock is released with an atomic exchange, not a store. On the RP2040 (Cortex-M0+) the
exchange runs under a hardware spinlock and a plain store does not, so a release landing inside the other
core's exchange was overwritten and the lock stayed taken (the board stopped answering).
Added
firmware/tests/test_tx.c: the frame queue against a UART that stays busy (ring wrap, frames of every
length, two producers in order, a full ring, the rate change after the queue, a producer that does not
wait for the line).- Tests of the held status stage in
firmware/tests/test_core.c: refused, accepted, no verdict in time,
and voided by a new setup packet.
Firmware Binary Third-Party Notices
The host library (libmimusb) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimusb_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimusb_firmware-rp2040-*, mimusb_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimusb_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimusb_firmware-THIRD_PARTY_NOTICES-0.7.2.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.7.1
The API has one shape for every kind of function: a factory makes a Spec, mimusb_node_open opens any
Spec at a placement, and control rules are the one way a class talks on endpoint 0, for HID and for
any class that comes after it. The wire protocol and the firmware are unchanged apart from the version
they report (a board must run firmware of the same minor version, 0.7).
Added
mimusb_spec_create_cdc_acmandmimusb_cdc_acm_options: a CDC-ACM function as a Spec. The library
writes the two interfaces, the class descriptors, the Interface Association descriptor and the
three rules (SET_LINE_CODING,GET_LINE_CODING,SET_CONTROL_LINE_STATE); the data is the
program's. RolesMIMUSB_ROLE_CDC_NOTIFY,_CDC_DATA_IN,_CDC_DATA_OUT; kind
MIMUSB_PROFILE_CDC_ACM.src/classes/cdc_acm.cppis where a class without a state lives: it only
makes interfaces and rules at the placement and opens them as any interfaces are.mimusb_node_placement.extra_rulesandextra_rule_count: control rules of the caller's own for a
Node of any Spec (a HID profile too), tried before the rules the Spec brings. A request is answered by
the first rule that matches, so a rule of the caller's can take over one the library would answer.mimusb_node_find_ruleandmimusb_rule_slot(MIMUSB_RULE_SLOT_CDC_LINE_CODING): a rule a Spec
names is found by name, not by its place among the Node's rules.mimusb_spec_interface_countandmimusb_spec_rule_cost: how many interface numbers a Spec takes
and what it adds to the board's rule memory.mimusb_target_limits(mimusb_device_config.target): what the target machine limits, whatever the
function. Its one member islinux_hid.docs/API.md: Kinds of Spec, one table of every factory with its interfaces, roles, rules and
state.
Changed
mimusb_spec_create_rawismimusb_spec_create_hid, andmimusb_raw_options,mimusb_raw_report,
mimusb_raw_options_init,mimusb_raw_submitandMIMUSB_PROFILE_RAWare
mimusb_hid_options,mimusb_hid_report,mimusb_hid_options_init,mimusb_hid_submitand
MIMUSB_PROFILE_HID: it was always a HID Spec, with a report descriptor of the caller's own. The
fields of its errors begin withhid.instead ofraw.. "Raw" now means only a Device given as
bytes (mimusb_device_set_descriptors).MIMUSB_HID_ROLE_INand_OUTareMIMUSB_ROLE_HID_INand_HID_OUT: a role is named for the kind
of Spec that has it.mimusb_transport_options.linux_hidismimusb_device_config.target.linux_hid, and it is required
when a Node of a HID Spec is opened (MIMUSB_ERR_UNSET_FIELDotherwise), not when the Device is
opened: a Device that opens only CDC-ACM or interfaces Nodes leaves it 0.mimusb_node_placementis 56 bytes (was 40) andmimusb_device_confighastargetafter
transport; the layout golden file and the generated bindings follow. The control rules of every
Node, not only those of amimusb_spec_create_interfacesSpec, come first in the table the board
holds, before those the library writes for the HID profiles and those of the Device.mimusb_node_set_rule_datanumbers a Node's rules as itsextra_rulesfirst, then the rules its
Spec brings.- Inside the library, HID is a class like any other: every class is a
FunctionClass
(src/classes/function_class.hpp) that builds a Node's interfaces and rules at its placement, lays
out its Nodes at each commit and hears the requests its rules take. The device layer (src/api)
knows no class; HID's report state is the runtime of a HID Node (HidNode), and the HID code lives
insrc/classes/hid/, one file per profile for the Spec factories (spec_*.cpp) and the state
machines (state_*.cpp). The rules a class answers live (HID'sGET_IDLE,GET_PROTOCOL) are
marked as such instead of being known by their kind. No change to the API, the ABI or the wire.
Removed
mimusb_hid_descriptor_bytesandmimusb_hid_descriptor_rule: a HID interface of the caller's own is
amimusb_spec_create_hidSpec; for one whose descriptor must not be checked the 9 bytes and the rule
are written out in amimusb_spec_create_interfacesSpec (examples/c/hid_interface.c).mimusb_cdc_acm_descriptors,mimusb_cdc_acm_descriptors_makeandmimusb_cdc_acm_rules:
replaced bymimusb_spec_create_cdc_acm.
Firmware Binary Third-Party Notices
The host library (libmimusb) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimusb_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimusb_firmware-rp2040-*, mimusb_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimusb_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimusb_firmware-THIRD_PARTY_NOTICES-0.7.1.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.6.1
The firmware's RAM limits are the port's, and none has a default. The wire protocol and the C ABI
are unchanged; the board reports its limits in the PONG as before, so a host library reads the larger
numbers without change. A board has to be flashed with this firmware to have them.
Changed
firmware/common/config.hno longer definesMIMUSB_MAX_INTERFACES,MIMUSB_MAX_CONFIG_BYTES,
MIMUSB_MAX_BOS_BYTES,MIMUSB_MAX_STRINGS,MIMUSB_MAX_STRING_BYTES,MIMUSB_MAX_REPORT_BYTES,
MIMUSB_CONTROL_DATA_MAX,MIMUSB_EP_POOL_SLOTS,MIMUSB_CONTROL_RULES,MIMUSB_ANSWER_BYTESor
MIMUSB_LAST_SENT_SLOTSwhen a port leaves them out. Every port states all of them in its own
mimusb_limits.h(RP2040, RP2350, nRF52840, four STM32F4 RAM classes, ESP32-S3), and a build without
the file or with one limit missing stops with a message that names it (firmware/tests:
missing_*_limit).- The limits are raised to what each chip's RAM holds. Largest on the RP2350 and the nRF52840: a
configuration descriptor of 8192 bytes (was 1024), 128 strings (24), 254 control rules (160), 32768
bytes of answer memory (4096), a control data stage of 4088 bytes (1024), a BOS of 1024 bytes (256).
The RP2040: 4096, 64, 254, 16384, 2048, 512. The STM32F401, with 64 kB of RAM, has 2048, 24, 96, 4096,
1024, 256: its control rules go down from 160 to 96 (the other figures are as before or larger), so
that 6 KiB of its RAM stay free (the former figures left about 5 KiB, measured on the F411 build). The
figures are in docs/LIMITS.md; the protocol bounds them (254
rules, a 4088-byte control data stage, 16-bit lengths). MIMUSB_MAX_STRING_BYTESis its own limit and no longerMIMUSB_MAX_STRINGSstrings of 254 bytes: a
store of fewer long strings than the count is refused withNAK_OVERFLOWwhen it is full.
Added
firmware/tools/check_ram.pyandcheck_ram.cmake: after the link, the build prints the RAM the image
takes (data + bss, plus a stack outside them) and stops when fewer than the reserve the port states
are left. Every firmware build here runs it; the ESP-IDF build does not (ESP-IDF has its own memory
summary).firmware/tests/limits_probe.cand the testsmissing_mimusb_limits_handmissing_*_limit.
Verified
Hardware-verified on 2026-11-13 for the parts listed here. Built: RP2040, RP2350 (Pico SDK), nRF52840
(pca10056), STM32F401, F411, F439 and F412 boards (TinyUSB BSP); not built: the ESP32-S3 (no ESP-IDF
here). ctest of the host library (23 tests, mimusb.sim-* against the real ports' limits) and of
firmware/tests (30) pass.
Run on a board: a Raspberry Pi Pico (RP2040) with a Prolific PL2303 adapter (7,812,500 baud), the target
the same Linux machine (Linux 7.2.11, a VMware guest, both USB devices passed through). The board ran
0.6.0, was restarted with mimusb_device_enter_bootloader, written with this release's UF2 image, and
reported firmware 0.6.1 and the new limits (configuration 4096, strings 64, rules 254, answer memory
16384, control data 2048, BOS 512, queue slots 72) with no CRC, framing or overrun error. hw_bulk wait|newest|oldest, hw_control_rules, hw_composite, hw_bytes bytes|bos, hw_iso, hw_cdc,
hw_msc, hw_ecm, hw_dfu, hw_printer and hw_midi all passed. Not run: a second machine as the
target, Windows or macOS, the RP2350 and the other boards (their limits are built, not run), the
mimusb_verify_* programs.
Firmware Binary Third-Party Notices
The host library (libmimusb) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimusb_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimusb_firmware-rp2040-*, mimusb_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimusb_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimusb_firmware-THIRD_PARTY_NOTICES-0.6.1.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.6.0
The C ABI changes: one way to open a Node. A Spec says what a function is, a placement says where
it goes on a Device. The wire protocol is unchanged; the firmware has one fix (below).
Hardware-verified on 2026-11-13 (see "Run on a board") for the parts listed there. A 0.5.0
board has to be flashed with this release's firmware, because the library refuses a board of another
minor version.
Run on a board
2026-11-13, a Raspberry Pi Pico (RP2040) flashed with this release's firmware image through
mimusb_device_enter_bootloader, a Prolific PL2303 adapter (7,812,500 baud), the target the same
Linux machine (a VMware guest, both USB devices passed through). Not run: a second machine as the
target, Windows or macOS, the RP2350, the other boards, the mimusb_verify_* programs.
hw_bulk wait|newest|oldest,hw_control_rules,hw_composite,hw_bytes bytes|bos,hw_iso,
hw_cdc: all passed, with no error on the link counters.hw_msc(new): a mass storage function; the kernel'susb-storagefound the disk, 4 KiB reads and
writes matched byte for byte, and the Bulk-Only Mass Storage Reset passed. It failed before the
firmware fix below: the first CBW after aclear_haltof an endpoint that was not halted was lost.hw_ecm(new): a CDC-ECM network adapter; the kernel made the interface, ARP and ICMP echo of frames
from 60 to 1514 bytes and 200 full-size round trips passed.hw_dfu,hw_printer(the kernel'susblpbound it),hw_midi(the kernel'ssnd-usb-audiomade a
sound card) (all new): passed.
Changed
mimusb_node_open(device, spec, placement, timeouts, &node)is the only way to open a Node. It
replacesmimusb_node_open_profileand the oldmimusb_node_open(device, node_config, ...).mimusb_node_placement(interface number, string, the endpoints of the Spec's roles) replaces
mimusb_hid_node_config, which is gone together withmimusb_hid_node_config_init.
mimusb_node_placement_initandmimusb_placed_endpointare new.- The HID descriptor and Interface descriptor values (
bcd_hid,subclass,protocol,
country_code) moved from the Node's config to the Spec: every HID options structure ends with a
requiredmimusb_hid_function function. A zerobcd_hidisMIMUSB_ERR_UNSET_FIELD. - Any class of Node is a Spec too:
mimusb_spec_create_interfaces(mimusb_node_config*)copies the
interfaces, items and rules into a Spec of kindMIMUSB_PROFILE_INTERFACES, which is opened with
an empty placement.
Fixed
- Firmware (RP2040, RP2350):
CLEAR_FEATURE(ENDPOINT_HALT)on an endpoint that was not halted left an
armed OUT transfer expecting the old data toggle, so the target's next packet (DATA0) was taken for
a retransmission and dropped. The toggle is now returned to DATA0 at once (USB 2.0 9.4.5), which is
what a Bulk-Only Mass Storage Reset needs.
Added
mimusb_spec_roleslists the endpoint roles of a Spec (MIMUSB_HID_ROLE_IN, required;
MIMUSB_HID_ROLE_OUT, optional), so a caller sees what its placement must give.- Refusals with the field named in
mimusb_error_detail: a role given twice or one the Spec does not
have, a nonzero reserved field, a missing IN role, a non-empty placement for a Spec of interfaces.
Firmware Binary Third-Party Notices
The host library (libmimusb) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimusb_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimusb_firmware-rp2040-*, mimusb_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimusb_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimusb_firmware-THIRD_PARTY_NOTICES-0.6.0.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.5.0
Not hardware-verified. Nothing of this release was run on a board: the simulated board (the
firmware core on a fake HAL) and the scripted board cover it. The wire protocol and the firmware
behaviour are unchanged from 0.4.0; the firmware images differ only in the version they report.
The C ABI changes (mimusb_usb_endpoint is 12 bytes, mimusb_usb_interface has settings), so a
program built against 0.4.0 needs the changes below, and the shared library keeps SOVERSION 0
while the version is 0.x.
Added
mimusb_cdc_acm_descriptors_makeandmimusb_cdc_acm_rules: the class descriptors, the
Interface Association descriptor and the line-coding control rules of a CDC-ACM function, for a
Node opened withmimusb_node_open.
Changed
-
An interface of a Node is a list of alternate settings, and a setting is a sequence of
items (mimusb_usb_interface.settings,mimusb_usb_setting,mimusb_usb_item): an endpoint
or one whole descriptor, in bus order. This replacesclass_descriptors,endpointsand
endpoint_count, and takes class descriptors that sit between or after endpoints (CDC, audio,
video, MIDI).mimusb_usb_endpointis 12 bytes: it gainsaudio_form,refresh,
synch_address,sync_typeandusage_typefor the 9-byte audio endpoint form and the
isochronous synchronization and usage types. -
A Node can carry isochronous endpoints, in a setting other than 0;
INTERFACE_ALTERNATEnames
the Node that owns the interface (node_id). Nodes and Devices given as bytes share one
endpoint check. -
Renamed from libmimhid to libmimusb, because the library is no longer about HID alone. Every
public name changes with it: themimhid_prefix ismimusb_,MIMHID_isMIMUSB_, the
headers aremimusb.handmimusb.hpp, the CMake package ismimusb(targetsmimusb::mimusb,
mimusb::mimusb_static,mimusb::cpp), the pkg-config files aremimusb.pcand
mimusb-static.pc, the CMake options areMIMUSB_*, the Python, Rust and C# packages are
mimusb,mimusb-sysandMimUsb, and the repository isnemarpuc/libmimusb. The wire
protocol and the firmware behaviour are unchanged; the names inproto/mimusb_proto.hchange
with the prefix. Code that uses 0.4.0 changes names only.
Firmware Binary Third-Party Notices
The host library (libmimusb) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimusb_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimusb_firmware-rp2040-*, mimusb_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimusb_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimusb_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimusb_firmware-THIRD_PARTY_NOTICES-0.5.0.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.4.0
Not hardware-verified as tests/hw/README.md defines it; what was run on a board is listed under
"Run on a board" below. The wire protocol changes (a new event, a new bit in the PONG's
transfer_types): a 0.3.x board and this library do not talk to each other, and the firmware of
this release is needed to use isochronous endpoints.
Run on a board
2026-11-12, a Raspberry Pi Pico (RP2040), a Prolific PL2303 adapter, a Windows 10 machine as the
target. Not run: Linux, macOS or Android as the target, the RP2350, the other boards, audio
classes, an isochronous OUT endpoint, the mimhid_verify_* programs.
- A UVC camera (128x96 YUY2, 256-byte isochronous packets, descriptors as bytes) enumerated by
Windows, opened by its camera application, and streamed: four openings and closings of the
stream in a row, then a program restart with the stream open, three times, with no stop of the
board and no error on the link counters. - Before the fix under "Fixed", the second opening of the stream stopped the board (its USB core:
commands that run there timed out while the serial link still answered) until it was unplugged.
Added
- Alternate settings and isochronous endpoints in a Device given as bytes
(mimhid_device_set_descriptors): interfaces may have settings 0, 1, 2, ... in order, an endpoint
may be named by several settings of its interface, and a board whosetransfer_typeshas
MIMHID_TRANSFER_ISOCHRONOUS(the RP2040 and RP2350 firmware: packets up to 1023 bytes) takes
isochronous endpoints, which is what the audio and video classes stream on. Endpoint descriptors
may be 7 bytes or the 9-byte audio-class form. The target'sSET_INTERFACEswitches the
isochronous endpoints of the interface and is reported asMIMHID_EVENT_INTERFACE_ALTERNATE
(wire eventSET_INTERFACE, 14);GET_INTERFACEanswers the selected setting. The board adds
nothing to a stream: no padding, no pacing, no resampling. mimhid_device_endpoint_writerefuses an isochronous transfer longer than the endpoint's packet.- Simulated-board scenario
mimhid.sim-iso, host walker and firmware tests for settings and
isochronous descriptors.
Fixed
- A target that leaves an alternate setting with an isochronous endpoint and selects it again (a
camera application closed and opened again) stopped the RP2040 and RP2350 board: the transfer
armed on the controller was never taken by the target, and TinyUSB's driver stops with "ep was
already available" when the next one is armed on top of it.SET_INTERFACEnow takes the armed
transfer off the controller of every isochronous endpoint it stops or starts
(hal_usb_clear_endpoint). Seen on a board: four openings and closings of a UVC stream in a row,
and a detach while streaming followed by three attaches, with no stop; before, the second opening
stopped the board until it was unplugged.
Changed
- A Node still has bulk and interrupt endpoints only: an isochronous
transfer_typein a Node is
MIMHID_ERR_UNSUPPORTED(it needs settings, which a Device given as bytes has). - On a board with isochronous endpoints
max_transfer_bytesis its isochronous packet (1023, 64
before), so a long write to a bulk endpoint goes in frames of up to 960 bytes (a multiple of the
endpoint's packet size) instead of 64; the target sees the same transfer. - A configuration for the RP2040 and RP2350 is checked against the controller's 3712 bytes of
packet memory atCOMMIT(NAK_OVERFLOW): the driver stopped the board when it ran out. - The wire protocol gains an event and the PONG's
transfer_typesa bit; the firmware version
number is not changed here (the release's to choose).
Firmware Binary Third-Party Notices
The host library (libmimhid) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimhid_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimhid_firmware-rp2040-*, mimhid_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimhid_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimhid_firmware-THIRD_PARTY_NOTICES-0.4.0.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.3.0
Not hardware-verified as tests/hw/README.md defines it; what was run
on a board is listed under "Run on a board" below. The wire protocol and the C ABI change: a
0.2.1 board and this library do not talk to each other. The board becomes a generic USB device: the
host composes every descriptor, or is given them as bytes, and the firmware has no HID driver.
Run on a board
2026-11-12, a Raspberry Pi Pico (RP2040), a Prolific PL2303 adapter, the target the same Linux
machine (a VMware guest, both USB devices passed through). Not run: a second machine as the target,
Windows or macOS, the mimhid_verify_* programs (they type into the target, which here is the
session), the other boards.
- Discovery and the rate search (7,812,500 baud, no errors on the link counters in any run).
- A keyboard profile Node: enumerated by Linux, 10 runs of 400 presses and 400 releases with the
event device grabbed, none lost; latency indocs/LATENCY.md, not different from 0.2.1. - A vendor Node with bulk IN and OUT: transfers of 1 to 292 bytes with their boundaries, a
zero-length packet, 262,100 bytes without loss under the wait policy, 200 packets from the target,
the drop-newest and drop-oldest policies with a target that does not read, stall and clear. - An HID interface written by hand: every control rule action answered to the host (
ANSWER,
ANSWER_LAST_SENT,ACCEPTwith a data stage,ASK, a stall for a request no rule matches), a
rule's bytes replaced, and an Output report on the OUT endpoint. - A composite device opened in one batch: a keyboard profile and a two-interface Node with an
interface association. - A device given as bytes (
tests/hw/hw_bytes bytes): the device, configuration and BOS descriptors and
two strings read back by Linux byte for byte, the vendor request answered by a rule of the Device,
bulk IN with its boundaries and a zero-length packet, bulk OUT as events of node 0 (a transfer of 70
bytes is two packets), Halt and clear. A composed Device with a BOS descriptor andbcdUSB0x0210
(hw_bytes bos). The BOS of both names the Microsoft OS 2.0 capability, so the target asks for its
descriptor set and the Device has a rule that answers; without it, or withbcdUSB0x0210 and no BOS,
the target did not enumerate the device. Not run: Windows. hw_bulk wait|newest|oldest,hw_control_rulesandhw_compositeagain on the same firmware; the
latency of ten runs indocs/LATENCY.md.mimhid_device_enter_bootloader, used to write the firmware some forty times.
Wire protocol
- The host sends every descriptor as bytes.
DESC_RESET(0x10),DESC_BEGIN(0x11) and
DESC_DATA(0x12) carry the device, configuration, string, BOS andANSWERdescriptors
(MIMHID_DESC_*); they replaceDEVICE_CONFIG,NODE_BEGINandNODE_DATA. AtCOMMITthe board
walks the staged configuration once and refuses one that does not hold together (NAK_DESCRIPTOR, the
previous configuration kept; docs/PROTOCOL.md). - A BOS descriptor is a descriptor kind (
MIMHID_DESC_BOS, 6) the board serves byte for byte; it needs
bcdUSB0x0201 or more. - Data frames name endpoints.
EP_IN(0x41..0x4F) andEP_OUT(0xC1..0xCF) carry the endpoint
number, not a node id. New commandsEP_CONFIG(0x1B, replacesQUEUE_DEPTH: address, depth, policy
drop-newest, drop-oldest or wait),EP_STALL(0x1E),EP_FLUSH(0x1F),RULE(0x18, was
CONTROL_CONFIG),RULES_APPLY(0x21),RULE_DATA(0x22),BOOTLOADER(0x20); new events
EV_EP_DONE,EV_EP_HALT;REPORT_LOSTbecameTRANSFER_LOST, which names the endpoint.
DESC_HID_REPORT(4),FEATURE(0x14) and the eventsSET_REPORT,SET_PROTOCOL,SET_IDLE,
OUTPUT_REPORT(5 to 8) are gone and not reused. - An
ANSWERrule has a capacity and a length (RULEbytes 14..15 and 16..17). The board reserves the
capacity,RULE_DATAsets any length up to it, so a shortened answer can grow again after the table
is rebuilt. - A
COMMITthat attaches is refused withNAK_STATEwhile the board is attached: it would change
the descriptors under a device the target has enumerated.mimhid_device_connecton a configured
Device sends nothing and returnsMIMHID_OK. PONG(MIMHID_PONG_MIN_LEN49): bytes 4, 5, 21..22 and 25..26 are reserved, zero; new fields
max_endpoint_number(34),max_interfaces_any,max_config_descriptor_bytes,max_strings,
max_transfer_bytes,endpoint_queue_slots,transfer_types(36 to 44),max_answer_bytes(45..46)
andmax_bos_bytes(47..48); the unique id starts at 49. The board's limits: 160 rules, 4096 bytes of
answers, 32ANSWER_LAST_SENTrules, 256 bytes of BOS (MIMHID_CONTROL_RULES,MIMHID_ANSWER_BYTES,
MIMHID_LAST_SENT_SLOTS,MIMHID_MAX_BOS_BYTES).
API
mimhid_node_opentakes interfaces of any class, HID included (mimhid_node_config: interfaces,
bulk and interrupt endpoints, class descriptors, an interface association, control rules). Profile
Nodes (keyboard, mouse, ...) aremimhid_node_open_profilewithmimhid_hid_node_config. Helpers
mimhid_hid_descriptor_bytesandmimhid_hid_descriptor_rule; examplesvendor_bulk.cand
hid_interface.c.- A Device can be given as bytes:
mimhid_device_set_descriptors/_clear_descriptors
(mimhid_device_descriptors), raw stringsmimhid_device_set_string/_clear_string(any index and
language), and the endpoint calls by addressmimhid_device_endpoint_set_policy,_write,_stall,
_clear_stall,_flush. The library checks the bytes without reading any class and names the field
and the byte offset of what is wrong. The OUT data of such a device isMIMHID_EVENT_ENDPOINT_DATA
with node id 0. It is exclusive with Nodes (MIMHID_ERR_BUSYboth ways). Example
examples/c/device_from_descriptors.c. - BOS descriptor:
mimhid_device_set_bosfor a composed Device, or inmimhid_device_descriptors;
mimhid_board_limits.max_bos_bytes. A commit with a BOS and abcd_usbbelow 0x0201 is
MIMHID_ERR_PARAM. Exampleexamples/c/winusb_bulk.c(the Microsoft OS 2.0 platform capability and
the vendor request that answers it): not run on Windows. - Control rules replace control routing:
mimhid_device_set_control_rules,mimhid_device_set_rule_data,
mimhid_node_set_rule_data; actionsMIMHID_CONTROL_ANSWER,_ANSWER_LAST_SENT,_ACCEPT,_ASK
(timeout_ms,when_late),_STALL; the rules of the Nodes come first, then the Device's. A request
no rule matches is stalled apart from the standard requests of the stack. New flag
MIMHID_CONTROL_FLAG_ACCEPTED.mimhid_*_set_rule_datatakes any length up to the rule's capacity. - Endpoint calls of a Node:
mimhid_node_endpoint_write,_stall,_clear_stall,_flush,
_set_policy(replacingmimhid_node_set_queue_depth); a profile Node's IN endpoint takes them too, with
any of the three policies; a write longer than the board's frame limit is split, and a timeout of 0 is
accepted with a drop policy.mimhid_device_add_string/_remove_string. New events
MIMHID_EVENT_ENDPOINT_DATA,_ENDPOINT_HALT,_TRANSFER_LOST(replacingREPORT_LOST). iface.numberis the realbInterfaceNumber. The numbers in use are 0, 1, 2, ... without a gap;
otherwise the commit fails withMIMHID_ERR_PARAMbefore anything is sent, the missing number in
mimhid_error_detail.offset. Open Nodes in number order (or in one batch) and close the highest first.- Limits: the 16-Node limit is gone (up to 65534 within the board's limits);
mimhid_device_info.max_nodesandmimhid_board_limits.max_hid_interfacesare removed
(max_answer_bytesand the new fields replace them). - Removed:
mimhid_node_open_raw,mimhid_report_send,mimhid_device_set_control_routing,
MIMHID_CONTROL_MAX_RULES,MIMHID_HID_ITFS,MIMHID_NODE_DATA_CHUNK(nowMIMHID_DESC_DATA_CHUNK),
MIMHID_DEVFLAG_SERIAL_FROM_ID(nowMIMHID_DESC_F_SERIAL_FROM_ID). - Changed for the target and the program:
- A Feature report read with no answer set is stalled (it was an empty answer).
GET_REPORTof an Input report returns the last report sent with that Report ID.- A
GET_IDLEstraight after aSET_IDLEmay still return the old value for one round trip. MIMHID_EVENT_OUTPUT_REPORT/_FEATURE_REPORTfor aSET_REPORTarrive when its data stage has.- Nodes on a shared interface that use the wait policy count against the first live Node of it.
- A Device with no Node holds no rules: they are kept until the first commit; inside a batch a change
of rules marks the Device for the commit at the end. - A
COMMITapplies the staged rules withreport_all0; the library sendsRULES_APPLYwith it
straight after an attach when it is set.
Firmware
- The firmware builds no descriptor and has no HID driver (
CFG_TUD_HIDis 0). Every interface runs
on a generic driver (firmware/common/generic.c, TinyUSB 0.18.0'susbd_edpt_*); what HID asks of
endpoint 0 is a table of control rules (control.c: two copies,RULES_APPLYswaps them and
RULE_DATAchanges an answer in place, bothNAK_BUSYwhile an answer is being sent). The ESP32-S3
port'shid_device.cis removed. - A BOS descriptor is served by
tud_descriptor_bos_cb; none is a stall. firmware/tests/itfs_probe.cis nowport_probe.c.
A board a program left attached
- The board leaves the bus before every configuration, the first of a Device too. A program that
ended without closing its Device (or closed it withkeep_attached) leaves the board on the
target's bus. The next program's first configuration used to reach a board that was attached:
its descriptors changed under a device the target had already enumerated, the target never saw
the new device, and `mi...
v0.2.1
Not hardware-verified. The wire protocol and the C ABI are those of 0.2.0 (a 0.2.0 board and this library
talk to each other); this release fixes four bugs, changes the release packaging and adds tests and
documentation. None of it has run on a board. Asset names changed: a script that downloads the old
-shared / -static names must be changed.
Fixed
- Null options and configuration pointers are recorded in
mimhid_last_error. Passing a null
optionsorconfigpointer to the ninemimhid_spec_create_*factories,mimhid_device_open,
mimhid_node_open,mimhid_node_open_raw, or the calls takingmimhid_commit_timeoutsnow
populatesmimhid_last_error()withMIMHID_ERR_PARAMand the structure name instead of leaving
the thread-local error detail atMIMHID_OK. - Frame type names.
mimhid_frame_type_namenow returns"PROBE"forMIMHID_T_PROBE
(0x1C) and"COUNTERS"forMIMHID_T_COUNTERS(0x1D). - 3-byte detach
COMMITon close.mimhid_device_closenow sends the standard 3-byte
{1, 0, 0}detachCOMMITpayload matchingLink::disconnectandcommit_deviceinstead of a
1-byte{1}payload. device->closingcheck across all device calls.mimhid_device_wait_ready,
mimhid_device_remote_wakeup,mimhid_device_board_info,mimhid_device_link_counters, and
mimhid_device_limitsnow reject a closingmimhid_device*withMIMHID_ERR_PARAM, matching
the other device operations.
Changed
- Tests. A scripted board on a pseudo-terminal (
mimhid.scripted) tests the transport and the C
ABI when the board NAKs, stays silent, refuses a rate or hangs up; new unit suites cover every
factory and input refusal. The pseudo-terminal tests of the real firmware core are now called
sim (mimhid.sim-*). A Coverage CI job measuressrc/with gcovr.tests/README.mddescribes
the unit, scripted, sim and hardware layers;tests/hw/README.mdis the hardware procedure;
docs/VERIFICATION.mdsummarizes what is verified across all four layers. - The release no longer publishes
*-runtimebundles. The*-sharedarchive already carries the
shared library with the same license documents, and nothing in the project consumed the smaller
bundle. A release now has 35 assets instead of 41. - One archive per platform, one SBOM per release; asset names change. Each platform's archive
is nowlibmimhid-X.Y.Z-<platform>-<arch>[-ubuntu22.04].tar.gz|zip, without the-shared/
-staticsuffix, and holds both libraries (the static one islibmimhid_static.a/
mimhid_static.lib), the CMake package files of both components and both pkg-config files;
find_package(mimhid COMPONENTS shared)andCOMPONENTS staticboth work from it. The twelve
.spdx.jsonsidecars are replaced bylibmimhid-X.Y.Z.spdx.json, one SPDX 2.3 document with a
package per archive. A release has 18 assets instead of 35; a script that downloads the old
names must be changed. The release workflow also gained aworkflow_dispatchdry run
(dry_run, on by default) that builds and checks every asset and keeps them as a workflow
artifact without publishing anything.
Firmware Binary Third-Party Notices
The host library (libmimhid) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimhid_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimhid_firmware-rp2040-*, mimhid_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimhid_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimhid_firmware-THIRD_PARTY_NOTICES-0.2.1.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.2.0
The wire protocol, the C ABI and the firmware build interface change; a 0.1.0 board and a 0.2.0
library do not talk to each other (MIMHID_ERR_PROTOCOL), and the reverse. Not
hardware-verified: the changes are tested with the firmware core's own tests, with the simulated
board over a pseudo-terminal, and by building every port (RP2040, RP2350, nRF52840, STM32F4;
the ESP32-S3 build is left to CI); none of it has run on a board yet.
- Nothing about the chip is assumed by the firmware build. Each port states the interfaces
(MIMHID_HID_ITFS), the highest endpoint number (MIMHID_MAX_ENDPOINT_NUMBER), the endpoint
packet size (MIMHID_MAX_ENDPOINT_BYTES),CFG_TUSB_OS,CFG_TUSB_RHPORT0_MODEand
CFG_TUD_MAX_SPEEDon the command line; a missing one is a compile error that names it. The
nRF52840 no longer gets 7 by default,core.hno longer picks 15 for the RP chips from
PICO_RP2040, andtusb_config.hno longer defaults to full speed and no OS. The Pico build
needsPICO_PLATFORM,PICO_BOARD,MIMHID_UART_ID,MIMHID_UART_TX_PINand
MIMHID_UART_RX_PIN; the ESP32-S3 build both pins; the nRF52840 and STM32F4 builds-DBOARD
(the STM32F4 port records the endpoint count of each board's MCU and refuses an unlisted board,
and gives the F412 boards 5 interfaces, not 3). - A number the controller does not have is refused. Until now an endpoint address such as
0x8Fwas accepted by the host and the board, TinyUSB then failed the target's
SET_CONFIGURATION, and the commit ended inMIMHID_ERR_TIMEOUT(on the nRF52840 the endpoint
number 8 was opened as a corrupt isochronous endpoint without an error). The PONG now carries
max_endpoint_number(byte 34; the unique id moved to 35 and 36..;MIMHID_PONG_MIN_LEN36),
mimhid_device_info.reserved8becamemax_endpoint_number,mimhid_board_limitsgained
max_endpoint_number(its size is 36), andmimhid_node_openreturnsMIMHID_ERR_OVERFLOW
for a larger number. The firmware refuses it withNAK_OVERFLOW. - The firmware fills nothing in. A zero LANGID,
bcdUSB,bcdHID, IN endpoint address, size
or interval, anbmAttributeswithout bit 7, and an OUT endpoint that is only partly given are
refused (NAK_PARAM); a COMMIT whose nodes of one interface differ, or that uses an endpoint
number twice in one direction, is refused (NAK_DESCRIPTOR). The host library already
required all of these, so a program that works with the library is not affected. - The initializers fill nothing in. Every
mimhid_*_initfunction (and itsmimhid::twin)
zeroes the structure and setsstruct_size, and nothing else: the pid.codes test IDs, the
strings, the boot rate, the handshake and commit timeouts, the report size, the Linux HID limits,
bm_attributes, the node's class,bcdHID, endpoint and interval, and every profile's fields
(the mouse buttons and ranges, the keyboard Usages, the gamepad axes, the touch and pen
fields) are the program's to set, and a required one left at zero is refused with
MIMHID_ERR_UNSET_FIELD.mimhid_node_config_initandmimhid::node_config()lost their
interface_numberargument (setiface.numberandep_in.addressyourself), and the four
constantsMIMHID_CONTROL_TIMEOUT_MS,MIMHID_SEND_TIMEOUT_MS,MIMHID_DRAIN_TIMEOUT_MSand
MIMHID_RECONNECT_TIMEOUT_MSare gone. The README,docs/API.md(which lists what each
structure requires) and the examples show every value set. - A vendor ID of zero is refused.
usb_device.vendor_idjoinedbcd_usb,language_idand
ep0_max_packet_sizeas a field the library will not guess, so a program that forgot it no
longer presents0000:xxxx(or, until now, the pid.codes test IDs the initializer used to put
in). A product ID of zero is still a valid one. - nRF52840: the D+ pull-up is taken down again after every USB power event until a
configuration is committed, so a board that has not been committed no longer enumerates as
CAFE:4000with no interface when the cable is plugged in.
Firmware Binary Third-Party Notices
The host library (libmimhid) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimhid_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimhid_firmware-rp2040-*, mimhid_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimhid_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimhid_firmware-THIRD_PARTY_NOTICES-0.2.0.txt and in THIRD_PARTY_NOTICES.md / NOTICE.
v0.1.0
The first release of this line. Not hardware-verified: the host library, the protocol and the
firmware core are tested with a simulated board over a pseudo-terminal and with the firmware
core's own tests; an earlier firmware ran on a Raspberry Pi Pico, this one has not yet.
- What it is. A PC-managed USB emulation coprocessor: a host library (C ABI in
include/mimhid.h, header-only C++ forwarders inmimhid.hpp, Python, C# and Rust bindings) and
the firmware of a board that turns serial frames into the reports of a USB HID composite
device. Boards: RP2040 and RP2350 (the reference), STM32F4, nRF52840 and ESP32-S3 (build-only
ports). - Devices and Nodes. A Device is one board on one serial port. Its Nodes are HID interfaces
with an immutable specification: keyboard, mouse, touchscreen, touchpad, pen, digitizer, gamepad,
toggle controls, or a raw report descriptor. Descriptors, interface and endpoint numbers, polling intervals, strings
and the USB identity are given by the program; nothing is inferred. - Strings are Unicode. UTF-8 on the API, UTF-16 in the string descriptor (USB 2.0 9.6.7), up
to 126 code units; control characters and malformed text are refused. - The line is as fast as it carries. Frames end in a CRC-16/CCITT-FALSE. There is no table of
rates: the board starts at 115,200 baud and makes any rate its UART divider gives within 2 %;
MIMHID_BAUD_FASTESTmeasures the fastest rate the port, adapter and board carry without loss
(counters on the board judge it). A UART BREAK returns a board to the boot rate, so a program
that went away cannot lose it.mimhid_device_link_countersreads the board's error counters. - Versions. The firmware and the library of one release agree on the protocol: a host talks to
a board whose major and minor version equal its own. A board of another version is listed by
mimhid_discoverwith only its version and refused withMIMHID_ERR_PROTOCOL. - Control transfers. Control routing rules hand chosen requests to the program, which answers
them (a proxy of a real device is built on this); Feature reports, idle and protocol requests,
output reports and the other events are reported to the program. - Reports are sent through a per-Node queue with optional loss reporting; batches commit a
configuration change once. - Build and release. CMake presets (
dev,release,tsan), an ABI golden file, symbol
lint, and release archives for Linux, macOS and Windows with the firmware images.
Firmware Binary Third-Party Notices
The host library (libmimhid) is licensed under the MIT License and has no third-party runtime library dependencies.
Prebuilt microcontroller firmware images (mimhid_firmware-*) incorporate third-party SDK and USB stack components under permissive licenses:
| Firmware asset | Third-party components & licenses |
|---|---|
mimhid_firmware-rp2040-*, mimhid_firmware-rp2350-* |
TinyUSB 0.18.0 (MIT), Raspberry Pi Pico SDK 2.2.0 (BSD-3-Clause, Copyright (c) 2020 Raspberry Pi (Trading) Ltd.), Arm CMSIS Core (Apache-2.0), Newlib C runtime |
mimhid_firmware-nrf52840-* |
TinyUSB 0.18.0 (MIT), Nordic Semiconductor nrfx (BSD-3-Clause, Copyright (c) 2017-2024 Nordic Semiconductor ASA), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-stm32f4-* |
TinyUSB 0.18.0 (MIT), STMicroelectronics cmsis_device_f4 & stm32f4xx_hal_driver (BSD-3-Clause / Apache-2.0, Copyright (c) 2016-2019 STMicroelectronics), Arm CMSIS 5 (Apache-2.0), Newlib C runtime |
mimhid_firmware-esp32s3-* |
TinyUSB 0.18.0 (MIT), Espressif ESP-IDF v5.4.2 (Apache-2.0, Copyright 2015-2025 Espressif Systems), Amazon FreeRTOS Kernel (MIT), Newlib C runtime |
Complete copyright notices, license texts, and warranty disclaimers for all firmware binaries are provided in the release asset mimhid_firmware-THIRD_PARTY_NOTICES-0.1.0.txt and in THIRD_PARTY_NOTICES.md / NOTICE.