Problem
On split keyboards with displays on both halves (e.g. Corne-ish Zen), the peripheral does not know which layer is active. Only the central processes key events and tracks layer state. Peripheral displays that show the current layer can only reflect stale or default state.
Use Case
I have a Corne-ish Zen with an e-ink display on each half. The right (peripheral) half shows a layer widget, but it always displays the default layer because it never receives layer state updates from the central.
Possible Approaches
I see two possible directions and would like maintainer guidance on which is preferred before submitting a PR.
Option A: Per-feature GATT characteristic
Add a dedicated BLE GATT characteristic (e.g. UUID 0x07) that relays the highest active layer index from central to peripheral, following the same pattern as the HID indicators relay (CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS):
- New
ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_LAYER_STATE command
- Peripheral receives the layer index and raises
zmk_split_peripheral_layer_changed
- Gated by
CONFIG_ZMK_SPLIT_PERIPHERAL_LAYER_STATE
I have a working implementation of this approach in my fork:
https://github.com/paoloantinor/zmk (commit abb8daf)
Option B: Generic data channel (PR #2036)
PR #2036 proposes a generic tagged-data channel for central-to-peripheral state relay, with layer state explicitly listed as one of its data tags. This would be a cleaner long-term architecture, but the PR has been open since December 2023 and appears to need significant rework after the wired split transport refactor.
Questions
Environment
Problem
On split keyboards with displays on both halves (e.g. Corne-ish Zen), the peripheral does not know which layer is active. Only the central processes key events and tracks layer state. Peripheral displays that show the current layer can only reflect stale or default state.
Use Case
I have a Corne-ish Zen with an e-ink display on each half. The right (peripheral) half shows a layer widget, but it always displays the default layer because it never receives layer state updates from the central.
Possible Approaches
I see two possible directions and would like maintainer guidance on which is preferred before submitting a PR.
Option A: Per-feature GATT characteristic
Add a dedicated BLE GATT characteristic (e.g. UUID 0x07) that relays the highest active layer index from central to peripheral, following the same pattern as the HID indicators relay (
CONFIG_ZMK_SPLIT_PERIPHERAL_HID_INDICATORS):ZMK_SPLIT_TRANSPORT_CENTRAL_CMD_TYPE_SET_LAYER_STATEcommandzmk_split_peripheral_layer_changedCONFIG_ZMK_SPLIT_PERIPHERAL_LAYER_STATEI have a working implementation of this approach in my fork:
https://github.com/paoloantinor/zmk (commit abb8daf)
Option B: Generic data channel (PR #2036)
PR #2036 proposes a generic tagged-data channel for central-to-peripheral state relay, with layer state explicitly listed as one of its data tags. This would be a cleaner long-term architecture, but the PR has been open since December 2023 and appears to need significant rework after the wired split transport refactor.
Questions
Environment