From v0.8 to v0.9
v0.9's headline change is Rynk, RMK's native host protocol, which replaces
Vial as the default. v0.9 also updates the embassy and BLE dependency stacks, unifies the
event/processor Rust API, restructures keyboard.toml to separate the electrical matrix, physical
layout, and logical keymap, and includes a few smaller breaking changes.
Each change below is labeled with who it affects. Use the table to find what applies to you, then
follow the steps in that section. Changes are grouped as Everyone and Rust API developers
(examples/use_rust); keyboard.toml users (examples/use_config) are affected only by the
Everyone changes.
Everyone
Rynk is the new default host protocol
Rynk is RMK's native host protocol — an alternative to Vial — and it is now
enabled by default. The rmk crate's default features changed:
Rynk and Vial are mutually exclusive — enable exactly one. Note that vial_lock is also no longer a
default feature; add it back explicitly if you use Vial's unlock keys.
If you relied on the defaults, your firmware now uses Rynk instead of Vial. Pick one of the paths below.
If you use keyboard.toml
The [host] section must match the rmk Cargo features — RMK checks this when it builds and stops
with an error if they disagree.
Option A — switch to Rynk (recommended). The default features already include rynk, so you only
need to update [host]:
Option B — keep Vial. Turn off default features and re-enable vial (plus vial_lock if you use
unlock keys), and keep vial_enabled = true (the default) in keyboard.toml:
See Host Configuration for the full set of options.
If you use the Rust API
Step 1 — pick the protocol in Cargo.toml. Rust projects list features explicitly, so if you
already listed vial, nothing forces a change. To move to Rynk, replace vial (and vial_lock)
with rynk in your feature list.
Step 2 — update how you wire up the host service. It no longer takes a separate KeyboardContext,
and it now attaches to a transport instead of running as its own task.
Before (v0.8):
After (v0.9):
On wireless boards, attach it to the BLE transport the same way:
HostService is protocol-agnostic — it resolves to whichever of rynk or vial you enabled, so the
wiring above is the same for both.
keyboard.toml layout restructured
Who this affects: everyone using keyboard.toml.
The keyboard description is now split into three sections: [matrix] (electrical wiring, unchanged),
[layout] (physical arrangement), and the new [keymap] (layer count and key actions). The
layer-related fields move out of [layout] into [keymap]:
[layout].rows and [layout].cols stay in [layout].
Before (v0.8):
After (v0.9):
Experimental protocol features renamed
Who this affects: the rare early adopters who enabled the experimental protocol features by name.
If your Cargo.toml used the experimental features rmk_protocol or bulk_transfer, rename them:
Dependency updates
Who this affects: everyone — these versions live in your own Cargo.toml.
v0.9 moves to newer embassy and BLE-stack releases. Update your dependency versions to match the example for your chip. The main bumps are:
embassy-time is unchanged (0.5). For nRF BLE boards, the nrf-sdc / nrf-mpsl git rev also
moves forward — copy the exact rev (and any other pins) from the matching example under examples/
for your chip, since some boards track specific git revisions.
Rust API developers
Event and processor API is unified
Who this affects: anyone who wrote custom controllers, input processors, or events.
v0.9 consolidates the previously separate controller and input_processor APIs into a single,
cohesive event/processor model. Rename the macros and functions as follows.
Macro changes
Function changes
Examples
Migrating a controller to a processor:
Migrating registration:
Migrating custom events:
Migrating multi-event enums:
Pointing device API renamed
Who this affects: anyone constructing a pointing device in Rust.
The generic PointingDevice / PointingProcessor replace the PMW3610-specific Pmw3610Device /
Pmw3610Processor. For the PMW3610, only the type name changes — the ::new() arguments are the
same:
keyboard.toml users don't need to do anything — the TOML config is unchanged.
PollingController interval is now a method
Who this affects: anyone who implemented PollingController for a custom input device.
The INTERVAL associated constant became an interval() method, so the interval can be chosen at
runtime:
MouseKeyConfig fields renamed
Who this affects: anyone building a MouseKeyConfig in Rust. (keyboard.toml users are unaffected —
the [rmk] mouse_key_interval / mouse_wheel_interval settings are unchanged.)
The renames reflect that these values now count acceleration ticks, not milliseconds.
Automatic changes (usually no action)
- Event channel subscriber counts. Several events had their default
subscount increased to make room for Rynk's host sessions. This is applied automatically. You only need to act if you pinned custom[event.<name>]subsvalues — recheck them against the new defaults. When enabling Rynk, also make sure there are enough subscriber slots, or the keyboard will panic on connect.
New in v0.9 (no migration needed)
These are new capabilities, listed so you know they exist:
rmk::bootis now public — callrmk::boot::jump_to_bootloader()from your own code.bootmagic— hold a designated key during boot to drop into the chip bootloader (works per-half on splits).- New input-device drivers — Azoteq IQS5xx trackpad and PMW3360 / PMW3389 mouse sensors.
See the changelog for the complete list.
Why these changes?
- Rynk gives RMK a native host protocol that understands every RMK feature, instead of being limited to what the Vial standard supports.
- The unified event/processor API collapses two parallel systems into one: a single
#[event]macro, a single#[processor]macro, and onepublish_event()family — simpler to learn and maintain, with no loss of functionality.