Skip to content

feat: implement bt/2.4ghz fr800x driver#26207

Draft
damex wants to merge 3 commits into
qmk:developfrom
damex:feat/freqchip-fr800x-driver
Draft

feat: implement bt/2.4ghz fr800x driver#26207
damex wants to merge 3 commits into
qmk:developfrom
damex:feat/freqchip-fr800x-driver

Conversation

@damex

@damex damex commented May 12, 2026

Copy link
Copy Markdown

Description

drivers/fr800x.{c,h}: shared core for the freqchip fr8003a uart chip.
state machine, opcode framing, queue, 6kro/nkro projection, chip init
sequence (HANDSHAKE + SLEEP_BLUETOOTH_ENABLE + SLEEP_DONGLE_ENABLE),
target switching (3 BT slots + dongle), battery query, charging-state
relay.

reconnect lifecycle: 2 s retry while DISCONNECTED re-issues target +
HANDSHAKE (timer reset by every target_change to avoid race); per-target
PAIRING-to-DISCONNECTED timeout and per-target HANDSHAKE link probe
registered by adapters via fr800x_target_set_pairing_timeout and
fr800x_target_set_probe_interval. On a dead link the chip emits 0x33
which fires the existing reconnect path.

boot order: boards must call fr800x_chip_init before any slot select
(typically before connection_host_changed_kb in keyboard_post_init_kb).
Without that order the chip's RF monitoring stays half-configured and
silent radio losses go undetected.

weak fr800x_receive_connection_cb and fr800x_receive_host_cb expose
chip state and host suspend/resume to boards.

drivers/bluetooth/fr800x.c and drivers/wireless/fr800x.c: thin adapters
routing each driver's send/profile/unpair/leds/is_connected to the
core. wireless adapter pushes dongle manufacturer/product/vid+pid
descriptors on every DONGLE select (chip's 2.4G stack needs them to
fully initialize RF monitoring) and registers 5 s pairing timeout +
5 s link probe for DONGLE. bluetooth adapter registers 30 s pairing
timeout for BT slots 1-3 (no probe; chip's BLE link supervision handles
loss). fr800x_init is idempotent so dual-enable links cleanly.

builddefs/common_features.mk: register fr800x in BLUETOOTH and
WIRELESS_2P4GHZ driver-type lists; both set FR800X_DRIVER_REQUIRED and
require UART_FRAME.

data/schemas/keyboard.jsonschema: add fr800x to both driver enums.
docs: features/wireless.md, drivers/wireless_2p4ghz.md, config_options.md,
and reference_info_json.md list fr800x as a driver option.

soc-side uart protocol reverse-engineered from traffic sniffed with a
miniware la104 on a freqchip fr8003a.

depends on the bluetooth multi-profile and 2.4ghz wireless api PRs to
land first.

Types of Changes

  • Core
  • Bugfix
  • New feature
  • Enhancement/optimization
  • Keyboard (addition or update)
  • Keymap/layout (addition or update)
  • Documentation

Issues Fixed or Closed by This PR

Checklist

  • My code follows the code style of this project: C, Python
  • I have read the PR Checklist document and have made the appropriate changes.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • I have tested the changes and verified that they work and don't break anything (as well as I can manage).

wires QK_BLUETOOTH_PROFILE_* and QK_BLUETOOTH_UNPAIR.

extends connection_config_t with 4-bit bluetooth_profile sharing
the existing byte. existing values decode unchanged.

new bluetooth.h api: get_max_profile, set_profile, get_profile, unpair.
new connection.h api: set/get/next/prev_bluetooth_profile and two weak hooks.

weak defaults keep rn42 and bluefruit_le single-profile.
docs are updated.

Signed-off-by: Roman Kuzmitskii <roman@damex.org>
@github-actions github-actions Bot added core documentation dd Data Driven Changes labels May 12, 2026
@damex damex force-pushed the feat/freqchip-fr800x-driver branch from 1306492 to 266b5bb Compare May 12, 2026 09:07
@zvecr zvecr changed the base branch from master to develop May 12, 2026 10:02
@damex damex force-pushed the feat/freqchip-fr800x-driver branch from 266b5bb to 173c6bd Compare May 12, 2026 11:38
@damex

damex commented May 12, 2026

Copy link
Copy Markdown
Author

also noticed that it needs reconnection mechanic. implemented it on disconnection. otherwise if keyboard drop connection for whatever reason (signal drop, dongle plugged out or whatever else) there is no way to get back unless you switch profiles.

it was like this:
2.4g -> drop connection-> no automatically working 2.4g
and one need to do this instead:
2.4g -> drop connection -> switch to bt or usb -> switch back to 2.4g

right now is much more user friendly:
2.4g -> drop -> reconnection attempt on 'disconnect' every 2 seconds (configurable) -> 2.4g works without user interaction

made changes, squashed and repushed those back.

@damex damex force-pushed the feat/freqchip-fr800x-driver branch 7 times, most recently from d8a287d to 94ca850 Compare May 14, 2026 16:39

@drashna drashna left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of this looks like it's using a separate path for bt and wireless. I'm not sure that's the correct path for this. Eg, it should be a unified framework that doesn't care which it is using.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new keycodes shouldn't be added to existing files. A new version should be added.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unpair keycode comes from #26203, not this pull request

Should the keycode go in its own pull request, or stay part of #26203?

Want to review all three related pull requests together (here), or separately?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@drashna i added a new version with that keycode (next available is 0.0.9). done for both #26207 and #26203

@zvecr zvecr added the awaiting_pr Relies on another PR to be merged first label May 14, 2026
@zvecr zvecr marked this pull request as draft May 14, 2026 22:16
@damex

damex commented May 15, 2026

Copy link
Copy Markdown
Author

A lot of this looks like it's using a separate path for bt and wireless. I'm not sure that's the correct path for this. Eg, it should be a unified framework that doesn't care which it is using.

fr8003a is one chip
common state machine, queue, retry, parser, indicator, link probe, and pairing timeout all live in drivers/fr800x.c.
The bt/wireless split exists because QMK has two driver-type buckets (bluetooth_driver_t, wireless_2p4ghz_driver_t), not because the code is two paths

each transport file holds only its own protocol bytes plus the framework wrappers that forward to the common driver
no shared state crosses files

Want me to collapse both into a single drivers/fr800x.{c,h} or we're good with such split?

drivers/wireless/wireless_2p4ghz.{c,h}: dispatcher with 12 weak hooks
(init, task, is_connected, can_send_nkro, keyboard_leds, send_keyboard/
nkro/mouse/consumer/system/raw_hid, unpair).

new wireless_2p4ghz_driver host_driver_t in tmk_core/protocol/host.c.
host dispatch routes to it on CONNECTION_HOST_2P4GHZ. connection
auto-detect resolves via wireless_2p4ghz_is_connected. init/task
called from quantum/keyboard.c.

new QK_2P4GHZ_UNPAIR keycode (alias WL_UNPR) wired in
process_connection.c.

opt in via WIRELESS_2P4GHZ_ENABLE + WIRELESS_2P4GHZ_DRIVER. default off.

docs, json schema, info_rules mapping, via metadata, and 12 weak-default
unit tests under quantum/connection/tests/ included.

depends on the bluetooth multi-profile pull request to be merged first
since it touch the same files process_connection.c, keycodes.h, schema
info_rules, and docs merge after that pr lands.

Signed-off-by: Roman Kuzmitskii <roman@damex.org>
@damex damex force-pushed the feat/freqchip-fr800x-driver branch from 94ca850 to df80479 Compare May 16, 2026 13:10
drivers/fr800x.{c,h}: shared core for the freqchip fr8003a uart chip.
state machine, opcode framing, queue, 6kro/nkro projection, chip init
sequence (HANDSHAKE + SLEEP_BLUETOOTH_ENABLE + SLEEP_DONGLE_ENABLE),
target switching (3 BT slots + dongle), battery query, charging-state
relay.

reconnect lifecycle: 2 s retry while DISCONNECTED re-issues target +
HANDSHAKE (timer reset by every target_change to avoid race); per-target
PAIRING-to-DISCONNECTED timeout and per-target HANDSHAKE link probe
registered by adapters via fr800x_target_set_pairing_timeout and
fr800x_target_set_probe_interval. On a dead link the chip emits 0x33
which fires the existing reconnect path.

boot order: boards must call fr800x_chip_init before any slot select
(typically before connection_host_changed_kb in keyboard_post_init_kb).
Without that order the chip's RF monitoring stays half-configured and
silent radio losses go undetected.

weak fr800x_receive_connection_cb and fr800x_receive_host_cb expose
chip state and host suspend/resume to boards.

drivers/bluetooth/fr800x.c and drivers/wireless/fr800x.c: thin adapters
routing each driver's send/profile/unpair/leds/is_connected to the
core. wireless adapter pushes dongle manufacturer/product/vid+pid
descriptors on every DONGLE select (chip's 2.4G stack needs them to
fully initialize RF monitoring) and registers 5 s pairing timeout +
5 s link probe for DONGLE. bluetooth adapter registers 30 s pairing
timeout for BT slots 1-3 (no probe; chip's BLE link supervision handles
loss). fr800x_init is idempotent so dual-enable links cleanly.

builddefs/common_features.mk: register fr800x in BLUETOOTH and
WIRELESS_2P4GHZ driver-type lists; both set FR800X_DRIVER_REQUIRED and
require UART_FRAME.

data/schemas/keyboard.jsonschema: add fr800x to both driver enums.
docs: features/wireless.md, drivers/wireless_2p4ghz.md, config_options.md,
and reference_info_json.md list fr800x as a driver option.

soc-side uart protocol reverse-engineered from traffic sniffed with a
miniware la104 on a freqchip fr8003a.

depends on the bluetooth multi-profile and 2.4ghz wireless api PRs to
land first.

Signed-off-by: Roman Kuzmitskii <roman@damex.org>
@damex damex force-pushed the feat/freqchip-fr800x-driver branch from df80479 to fd2ba5e Compare May 18, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting_pr Relies on another PR to be merged first core dd Data Driven Changes documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants