Skip to content

Add Rynk core service struct#850

Merged
HaoboGu merged 10 commits into
feat/rynk_protocolfrom
feat/rynk-pr2-service-core
May 14, 2026
Merged

Add Rynk core service struct#850
HaoboGu merged 10 commits into
feat/rynk_protocolfrom
feat/rynk-pr2-service-core

Conversation

@HaoboGu
Copy link
Copy Markdown
Owner

@HaoboGu HaoboGu commented May 14, 2026

No description provided.

HaoboGu added 10 commits May 13, 2026 23:39
Adds GetWpm (0x0805), GetSleepState (0x0806), GetLedIndicator (0x0807)
in the Status group. These let the host probe the latest value of the
three pure event-stream topics whose state isn't otherwise queryable
(layer/connection/battery/ble already have getters).

The snapshot source-of-truth lives in pr2; handlers land in pr3.
Drops the `Header` struct + `Header::decode`/`encode_into` in favour of
`Frame` (a type alias for `[u8]`) and the `FrameOps` trait that adds
in-place wire-header accessors (`cmd`, `seq`, `payload_len`, `payload`,
plus their setters).

Callers stop parsing a `Header` value out of the bytes and re-encoding
it back — they hand the buffer through and access fields via the trait.
The trait re-uses `RynkError::InvalidParameter` for "short buffer" /
"unknown CMD" instead of a separate `DecodeError`.

Wire layout unchanged: `[CMD u16 LE | SEQ u8 | LEN u16 LE | payload]`.

Used by pr2's dispatch refactor (single buffer in/out) and the handler
signature update in pr3.
Aliases `Result<T, RynkError>` (with `T = ()` default) so handler
modules can write `RynkResult` for empty-status responses without
re-declaring the alias in every file. Used by pr3's handlers.
Introduces rmk/src/host/rynk/{mod, codec, topics} as the dispatcher
scaffold for the on-device rynk service. Wires it into host/context
and host/mod, exposes channel hooks in src/channel.rs, and updates
src/keymap.rs and src/lib.rs to expose the new entry points.
Handlers and transports land in subsequent PRs.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
These statics are only consumed by the BLE transport added in pr4.
Move them out of the service-core PR so pr2 stays free of transport
concerns; they'll be re-introduced alongside the BLE transport.
Adds rmk/src/host/rynk/snapshot.rs: three static atomics latched by
a small `run_topic_snapshot` task that subscribes to WpmUpdateEvent,
SleepStateEvent, and LedIndicatorEvent. The matching GetWpm /
GetSleepState / GetLedIndicator handlers (pr3) read these atomics so
the host can probe the latest value without waiting for the next push.

Wires the dispatch arms for the new variants and re-exports the snapshot
task at the crate root (`rmk::host::run_topic_snapshot`). Bumps default
`subs` for wpm_update, sleep_state, and led_indicator by 1 to reserve
the snapshot subscriber's slot.

Handlers land in pr3; user wiring (run_all!) lands in pr5.
Replaces `Header::decode`/`encode_into` plumbing with the new `Frame` +
`FrameOps` surface from rmk-types:

- `dispatch` now takes `&mut Frame` (one buffer), returns
  `Result<(), RynkError>`. The request bytes and the response bytes
  share the same buffer; cmd/seq stay in place, only LEN is patched.
- The previous private `handle` function is folded into `dispatch`'s
  match — there's no second function to hop through.
- `encode_topic` renamed to `write_topic`, writes header + payload
  into the caller's frame in place (no length returned; caller reads
  `frame.payload_len()`).

Wire layout unchanged; only the firmware-side API moves.
Signed-off-by: Haobo Gu <haobogu@outlook.com>
Every header accessor on the `RynkMessage` trait now returns
`Result<T, RynkError>`, checking `self.len() >= RYNK_HEADER_SIZE` like
`cmd()` already did. There's no longer an implicit "caller must verify
length first" precondition — passing a short buffer to `seq()`,
`payload_len()`, `payload()`, etc. surfaces `Err(InvalidRequest)`
instead of indexing past the end.

Dispatcher and `write_topic` propagate the new Result with `?`;
`TopicEvent::encode` does the same. Transports already always pass
buffers sized to `RYNK_BUFFER_SIZE >= RYNK_MIN_BUFFER_SIZE >=
RYNK_HEADER_SIZE`, so the new error path is dead in practice — but
it's no longer a footgun for fresh callers (including loopback tests).

Adds `every_accessor_rejects_short_buffer` to the message tests so
this invariant doesn't regress silently.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
`dispatch` no longer encodes handler errors into the payload itself.
Each match arm uses `await?` so any `RynkError` (from `msg.cmd()`,
`payload_mut()`, the handler body, or the topic-CMD arms) propagates
out as the function's `Err`. The dispatcher stays a pure
"request bytes → response bytes or error" function with no buffer
mutation on the failure path.

Adds `write_error_response(msg, err)` next to `dispatch` and
`write_topic`. Transports call it on the dispatch `Err` arm to encode
`Err::<(), RynkError>(err)` into the same buffer's payload region and
patch LEN, then send the reply. The split keeps the wire contract
("every response is a `Result<T, RynkError>` envelope") while pulling
the error-encoding policy out of the protocol core.

`cmd` and `seq` in the header are not touched by `write_error_response`
— the host correlates the reply with its outgoing request by `seq`,
regardless of the protocol-level error.

Signed-off-by: Haobo Gu <haobogu@outlook.com>
@HaoboGu HaoboGu force-pushed the feat/rynk-pr2-service-core branch from b153f0b to 2700e72 Compare May 14, 2026 11:32
@HaoboGu HaoboGu marked this pull request as ready for review May 14, 2026 11:35
@HaoboGu HaoboGu merged commit 3c77b07 into feat/rynk_protocol May 14, 2026
@HaoboGu HaoboGu mentioned this pull request May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant