1"use strict";(self.rspackChunkrmk_rspress=self.rspackChunkrmk_rspress||[]).push([[2932],{6495(e,n,d){d.r(n);var s=d(1684),r=d(506);function c(e){let n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",span:"span",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:["\n",(0,s.jsxs)(n.h1,{id:"rynk-protocol-reference",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#rynk-protocol-reference",children:"#"}),"Rynk Protocol Reference"]}),"\n",(0,s.jsxs)(n.p,{children:["Current protocol version: ",(0,s.jsx)(n.strong,{children:"0.1"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Every transport (USB vendor bulk, BLE GATT, BLE HID) carries the same frame â a 3-byte header plus a ",(0,s.jsx)(n.a,{href:"https://docs.rs/postcard",rel:"noopener noreferrer",target:"_blank",children:"postcard"}),"-encoded payload:"]}),"\n",(0,s.jsx)(s.Fragment,{children:(0,s.jsx)(n.pre,{className:"shiki css-variables",style:{backgroundColor:"var(--shiki-background)",color:"var(--shiki-foreground)"},tabIndex:"0",lang:"text",children:(0,s.jsxs)(n.code,{children:[(0,s.jsx)(n.span,{className:"line",children:(0,s.jsx)(n.span,{children:"ââââââââââââââââ¬ââââââââââââ"})}),"\n",(0,s.jsx)(n.span,{className:"line",children:(0,s.jsx)(n.span,{children:"â CMD u16 LE â SEQ u8 â â 3-byte header"})}),"\n",(0,s.jsx)(n.span,{className:"line",children:(0,s.jsx)(n.span,{children:"ââââââââââââââââ´ââââââââââââ¤"})}),"\n",(0,s.jsx)(n.span,{className:"line",children:(0,s.jsx)(n.span,{children:"â postcard-encoded payload â"})}),"\n",(0,s.jsx)(n.span,{className:"line",children:(0,s.jsx)(n.span,{children:"ââââââââââââââââââââââââââââ"})})]})})}),"\n",(0,s.jsxs)(n.p,{children:["On the wire the whole frame is COBS-encoded and terminated by a single ",(0,s.jsx)(n.code,{children:"0x00"})," delimiter, so the byte stream is self-synchronizing."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Requests"})," use CMD ",(0,s.jsx)(n.code,{children:"0x0000..=0x7FFF"}),". The response echoes CMD and SEQ and wraps its payload in postcard ",(0,s.jsx)(n.code,{children:"Result<T, RynkError>"})," (",(0,s.jsx)(n.code,{children:"T = ()"})," for ",(0,s.jsx)(n.code,{children:"Set*"}),")."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Topics"})," use CMD ",(0,s.jsx)(n.code,{children:"0x8000..=0xFFFF"})," (server â host push, SEQ ",(0,s.jsx)(n.code,{children:"0"}),", bare payload)."]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["Which commands a firmware answers depends on the RMK Cargo features it was built with: a row with no ",(0,s.jsx)(n.strong,{children:"Feature"})," is present once ",(0,s.jsx)(n.code,{children:"rynk"})," is on, and the rest need their feature (",(0,s.jsx)(n.code,{children:"_ble"}),", ",(0,s.jsx)(n.code,{children:"split"}),", â¦) compiled in. A command the firmware wasn't built with answers ",(0,s.jsx)(n.code,{children:"UnknownCmd"}),"."]}),"\n",(0,s.jsxs)(n.h2,{id:"transports",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#transports",children:"#"}),"Transports"]}),"\n",(0,s.jsx)(n.p,{children:"The same COBS-framed byte stream runs over every transport; only how a host finds and opens the link differs."}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Transport"}),(0,s.jsx)(n.th,{children:"How the host reaches it"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"USB vendor bulk"}),(0,s.jsxs)(n.td,{children:["A vendor-specific interface with class/subclass/protocol ",(0,s.jsx)(n.code,{children:"0xFF"}),"/",(0,s.jsx)(n.code,{children:"0x52"}),"/",(0,s.jsx)(n.code,{children:"0x52"})," and one bulk IN + one bulk OUT endpoint. Hosts discover keyboards by that interface triple, not by VID/PID. An MS OS 2.0 descriptor binds it to WinUSB, so Windows needs no driver. The firmware also prefixes its USB serial number with ",(0,s.jsx)(n.code,{children:"rynk:"})," as an informational marker."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"BLE GATT"}),(0,s.jsxs)(n.td,{children:["Service ",(0,s.jsx)(n.code,{children:"10900067-537f-4f0a-9b55-929e271f61ab"})," with two characteristics: the host writes request bytes to ",(0,s.jsx)(n.code,{children:"output_data"})," (",(0,s.jsx)(n.code,{children:"19802524-6f90-4346-93c2-63dbc509ab55"}),") and subscribes to notifications on ",(0,s.jsx)(n.code,{children:"input_data"})," (",(0,s.jsx)(n.code,{children:"80f9319b-0c74-43a5-9738-c59d6dda3db9"}),"). Both require an encrypted link. A single write or notification carries at most 244 bytes; a longer frame spans several."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:"BLE HID"}),(0,s.jsxs)(n.td,{children:["A vendor HID report (usage page ",(0,s.jsx)(n.code,{children:"0xFF14"}),", usage ",(0,s.jsx)(n.code,{children:"0x61"}),") alongside the keyboard's HID-over-GATT service, so a bonded keyboard is reachable through the OS HID stack (for example WebHID) without a second pairing. Each report is exactly 32 bytes: the host splits a frame across reports and zero-pads the last one, and the receiver treats padding as empty COBS frames."]})]})]})]}),"\n",(0,s.jsxs)(n.p,{children:["A ",(0,s.jsx)(n.a,{href:"/docs/features/dongle.html",children:"dongle"})," relays these frames untouched, so a host talks to the dongle's USB interface exactly as it would to the keyboard."]}),"\n",(0,s.jsxs)(n.h2,{id:"sizing-and-bulk-transfer",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#sizing-and-bulk-transfer",children:"#"}),"Sizing and bulk transfer"]}),"\n",(0,s.jsxs)(n.p,{children:["Each peer holds one frame in a buffer of ",(0,s.jsx)(n.code,{children:"rynk_buffer_size"})," bytes (a ",(0,s.jsx)(n.code,{children:"[rmk]"})," option, see ",(0,s.jsx)(n.a,{href:"/docs/configuration/rmk_config.html#rynk-protocol-configuration",children:"RMK config"}),"). The largest payload a frame can carry is what remains after COBS overhead, the delimiter, and the 3-byte header; the firmware reports it as ",(0,s.jsx)(n.code,{children:"DeviceCapabilities.max_payload_size"}),". Read the capabilities and size requests from them rather than assuming a fixed limit."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"DeviceCapabilities"})," also advertises ",(0,s.jsx)(n.code,{children:"bulk_transfer_supported"})," and the paging strides ",(0,s.jsx)(n.code,{children:"max_bulk_keys"})," (worst-case keys per ",(0,s.jsx)(n.code,{children:"GetKeymapBulk"})," page) and ",(0,s.jsx)(n.code,{children:"max_bulk_items"})," (worst-case entries per ",(0,s.jsx)(n.code,{children:"GetComboBulk"}),"/",(0,s.jsx)(n.code,{children:"GetMorseBulk"})," page). A bulk read names a start â for the keymap ",(0,s.jsx)(n.code,{children:"(layer, row, col)"}),", read forward through the flat row-major, layer-major keymap; for combos and morses a slot index â and returns as many consecutive entries as fit in one payload, or fewer at the end. A host pages by advancing its start by the stride; a short page ends the read. A bulk write carries a start plus a list of entries and is packed by encoded size up to ",(0,s.jsx)(n.code,{children:"max_payload_size"}),". A reply that does not fit beside other pipelined requests answers ",(0,s.jsx)(n.code,{children:"Busy"}),"; retry once they complete."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"GetLayout"})," serves the compressed layout blob 244 bytes per call: the request is a byte offset and ",(0,s.jsx)(n.code,{children:"LayoutChunk"})," carries ",(0,s.jsx)(n.code,{children:"total_len"})," plus that page's bytes. Macros move in ",(0,s.jsx)(n.code,{children:"macro_chunk_size"})," pieces (",(0,s.jsx)(n.code,{children:"protocol_macro_chunk_size"})," in ",(0,s.jsx)(n.code,{children:"[rmk]"}),") addressed by byte offset."]}),"\n",(0,s.jsxs)(n.h2,{id:"errors",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#errors",children:"#"}),"Errors"]}),"\n",(0,s.jsxs)(n.p,{children:["A request's response is postcard ",(0,s.jsx)(n.code,{children:"Result<T, RynkError>"}),"; the ",(0,s.jsx)(n.code,{children:"Err"})," side is one of these variants."]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Variant"}),(0,s.jsx)(n.th,{children:"Meaning"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Malformed"})}),(0,s.jsx)(n.td,{children:"The request could not be decoded."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"NotReady"})}),(0,s.jsx)(n.td,{children:"The device is not in a state to satisfy the request."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"StorageFault"})}),(0,s.jsx)(n.td,{children:"Persistent storage failed on a write (flash erase/write error)."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Internal"})}),(0,s.jsx)(n.td,{children:"Internal firmware fault."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Unimplemented"})}),(0,s.jsx)(n.td,{children:"The command is recognized but its handler is not implemented yet."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Invalid"})}),(0,s.jsx)(n.td,{children:"The request decoded cleanly but is semantically invalid (out-of-range index, bad value)."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"UnknownCmd"})}),(0,s.jsx)(n.td,{children:"The frame is well-formed but its CMD is unknown to this firmware."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Locked"})}),(0,s.jsx)(n.td,{children:"The command is gated by the lock and this session is locked (see Lock)."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Busy"})}),(0,s.jsx)(n.td,{children:"Transient backpressure: the reply did not fit beside pipelined requests still queued. Retry once they complete."})]})]})]}),"\n",(0,s.jsxs)(n.h2,{id:"lock",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#lock",children:"#"}),"Lock"]}),"\n",(0,s.jsxs)(n.p,{children:["Commands that can flash firmware, wipe storage, or read the matrix sit behind a physical-presence unlock. ",(0,s.jsx)(n.code,{children:"BootloaderJump"}),", ",(0,s.jsx)(n.code,{children:"StorageReset"}),", ",(0,s.jsx)(n.code,{children:"GetMatrixState"}),", and (with ",(0,s.jsx)(n.code,{children:"_ble"}),") ",(0,s.jsx)(n.code,{children:"ClearBleProfile"})," always need an unlocked session; every ",(0,s.jsx)(n.code,{children:"Set*"})," command joins them when the firmware was built with ",(0,s.jsx)(n.code,{children:"[host] write_requires_unlock = true"}),". A gated command on a locked session answers ",(0,s.jsx)(n.code,{children:"Locked"})," and does nothing. ",(0,s.jsx)(n.code,{children:"GetLockStatus"}),", ",(0,s.jsx)(n.code,{children:"UnlockPoll"}),", and ",(0,s.jsx)(n.code,{children:"Lock"})," are never gated."]}),"\n",(0,s.jsxs)(n.p,{children:["The lock is per session and starts locked; ",(0,s.jsx)(n.code,{children:"Lock"})," or the end of the session (unplug, BLE disconnect) relocks it. To unlock, a host polls ",(0,s.jsx)(n.code,{children:"UnlockPoll"})," while the user holds the challenge keys that ",(0,s.jsx)(n.code,{children:"LockStatus.key_positions"})," reports (",(0,s.jsx)(n.code,{children:"[host].unlock_keys"}),"); the session is unlocked once ",(0,s.jsx)(n.code,{children:"locked"})," clears. With no ",(0,s.jsx)(n.code,{children:"unlock_keys"})," configured the challenge is empty and the gated commands can never be unlocked; a firmware built with ",(0,s.jsx)(n.code,{children:"[host] insecure = true"})," starts unlocked and ignores ",(0,s.jsx)(n.code,{children:"Lock"}),". See ",(0,s.jsx)(n.a,{href:"/docs/features/rynk.html#locking-dangerous-operations",children:"Rynk"})," for the user-facing side."]}),"\n",(0,s.jsxs)(n.h2,{id:"endpoints",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#endpoints",children:"#"}),"Endpoints"]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"CMD"}),(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Request"}),(0,s.jsx)(n.th,{children:"Response"}),(0,s.jsx)(n.th,{children:"Feature"}),(0,s.jsx)(n.th,{children:"Notes"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0001"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetVersion"})}
1),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ProtocolVersion"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0002"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetCapabilities"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"DeviceCapabilities"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0003"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Reboot"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0004"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BootloaderJump"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0005"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"StorageReset"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"StorageResetMode"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0006"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetLockStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LockStatus"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"Pure read of the current lock state â no side effects."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0007"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"UnlockPoll"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LockStatus"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"Arms/refreshes the unlock attempt and samples the held challenge keys."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0008"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Lock"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"Relock immediately."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0009"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetLayout"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u32"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LayoutChunk"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Get layout blob chunk. ",(0,s.jsx)(n.code,{children:"u32"})," is the byte offset."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x000A"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetDeviceInfo"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"DeviceInfo"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Identity strings and USB ids; feature gating stays in ",(0,s.jsx)(n.code,{children:"GetCapabilities"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0101"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetKeyAction"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"KeyPosition"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"KeyAction"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0102"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetKeyAction"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetKeyRequest"})}
1),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0103"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetDefaultLayer"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0104"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetDefaultLayer"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0105"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetEncoderAction"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetEncoderRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"EncoderAction"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0106"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetEncoderAction"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetEncoderRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0107"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetKeymapBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetKeymapBulkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetKeymapBulkResponse"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0108"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetKeymapBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetKeymapBulkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0201"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMacro"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMacroRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"MacroData"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0202"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMacro"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMacroRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0301"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetCombo"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Combo"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0302"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetCombo"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetComboRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0303"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetComboBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetComboBulkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetComboBulkResponse"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0304"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetComboBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetComboBulkRequest"})}
1),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0401"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMorse"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Morse"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0402"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMorse"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMorseRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0403"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMorseBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMorseBulkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMorseBulkResponse"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0404"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMorseBulk"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetMorseBulkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0501"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetFork"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"Fork"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0502"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetFork"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetForkRequest"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0601"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetBehaviorConfig"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BehaviorConfig"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0602"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SetBehaviorConfig"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BehaviorConfig"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0701"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetConnectionType"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ConnectionType"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0702"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetConnectionStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ConnectionStatus"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Full ",(0,s.jsx)(n.code,{children:"ConnectionStatus"})," snapshot."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0703"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetBleStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BleStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"_ble"})}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0704"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SwitchBleProfile"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}
1),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"_ble"})}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0705"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ClearBleProfile"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"_ble"})}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0801"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetCurrentLayer"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0802"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetMatrixState"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"MatrixState"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0803"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetBatteryStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BatteryStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"_ble"})}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0804"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetPeripheralStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"PeripheralStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"split"})}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0805"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetWpm"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u16"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Latest WPM, sourced from the ",(0,s.jsx)(n.code,{children:"WpmUpdate"})," topic snapshot."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0806"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetSleepState"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"bool"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Latest sleep flag, sourced from the ",(0,s.jsx)(n.code,{children:"SleepState"})," topic snapshot."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x0807"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"GetLedIndicator"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"()"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LedIndicator"})}),(0,s.jsx)(n.td,{}),(0,s.jsxs)(n.td,{children:["Latest HID LED bitmap, sourced from the ",(0,s.jsx)(n.code,{children:"LedIndicatorChange"})," topic snapshot."]})]})]})]}),"\n",(0,s.jsxs)(n.h2,{id:"topics",children:[(0,s.jsx)(n.a,{className:"rp-header-anchor","aria-hidden":"true",href:"#topics",children:"#"}),"Topics"]}),"\n",(0,s.jsxs)(n.p,{children:["Topics are best-effort pushes; the ",(0,s.jsx)(n.code,{children:"Get*"})," endpoints above mirror their payloads so a host can recover a missed push."]}),"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"CMD"}),(0,s.jsx)(n.th,{children:"Name"}),(0,s.jsx)(n.th,{children:"Payload"}),(0,s.jsx)(n.th,{children:"Feature"}),(0,s.jsx)(n.th,{children:"Notes"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8001"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LayerChange"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u8"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8002"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"WpmUpdate"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"u16"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8003"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ConnectionChange"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"ConnectionStatus"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8004"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"SleepState"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"bool"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8005"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LedIndicatorChange"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"LedIndicator"})}),(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"0x8006"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BatteryStatusChange"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"BatteryStatus"})}),(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"_ble"})}),(0,s.jsx)(n.td,{})]})]})]})]})}function t(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}t.__RSPRESS_PAGE_META={},t.__RSPRESS_PAGE_META["v0.9%2Fdocs%2Fdevelopment%2Frynk_protocol.md"]={toc:[{id:"transports",text:"Trans
1ports",depth:2},{id:"sizing-and-bulk-transfer",text:"Sizing and bulk transfer",depth:2},{id:"errors",text:"Errors",depth:2},{id:"lock",text:"Lock",depth:2},{id:"endpoints",text:"Endpoints",depth:2},{id:"topics",text:"Topics",depth:2}],title:"Rynk Protocol Reference",headingTitle:"Rynk Protocol Reference",frontmatter:{}},d.d(n,{default:()=>t})}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.