Skip to content

HID 通讯协议(USB 配置通道)

MeowKeyboard 无线版通过 USB HID 配置通道与 Studio(WebHID)通信。本文档以当前固件实现为准,给出 逐字节 协议定义,并补充一版可扩展的接口设计方案。

概览

项目说明
配置通道帧长64B
WebHID 模式无 Report IDreportId=0
通道方向主机发送命令帧,设备返回响应帧
字节序以字段定义为准(协议中同时存在大端/小端字段)

约定

除异步日志 KBD_CMD_LOG (0x70) 外,响应数据区 DATA[0] 均为状态码kbd_resp_t)。


配置帧格式(64B)

主机 → 设备(命令帧)

对应固件 kbd_cmd_frame_tfirmware/CH592F/keyboard/include/kbd_types.h)。

偏移大小字段说明
0x001CMD命令码(kbd_cmd_t
0x011SUB子命令/序号(层号、槽位号、宏分包序号等)
0x021LENDATA 有效长度(0~61
0x03~0x3F61DATA请求参数

设备 → 主机(响应帧)

当前固件响应帧格式与命令帧一致(CMD 为原命令回显,不携带状态码)。状态码放在 DATA[0]

偏移大小字段说明
0x001CMD原命令码回显
0x011SUBSUB 回显(如层号、槽位号)
0x021LENDATA 有效长度
0x03~0x3F61DATA响应数据(通常 DATA[0] 为状态码)

Studio / WebHID 对接(当前实现)

tools/studio/src/services/HidService.ts 使用统一封包方法:

  • sendCommand(cmd, sub, data) 构造 [CMD][SUB][LEN][DATA...]
  • sendReport(0, frame) 发送 64B
  • inputreport 回调读取 event.data.buffer(64B)
  • CMD=0x70 作为异步日志,不进入命令响应等待队列

状态码(kbd_resp_t

名称含义
0x00KBD_RESP_OK成功
0x01KBD_RESP_ERR_INVALID无效命令
0x02KBD_RESP_ERR_PARAM参数错误
0x03KBD_RESP_ERR_BUSY设备忙
0x04KBD_RESP_ERR_FLASHFlash 操作失败
0x10KBD_RESP_ERR_TOO_LARGE数据过大
0x11KBD_RESP_ERR_NO_SPACE存储空间不足
0x12KBD_RESP_ERR_NOT_FOUND未找到目标

命令码总表(当前固件)

分类命令SUB 含义Studio 当前是否封装
系统SYS_INFO0x010
系统SYS_STATUS0x020
配置CFG_SAVE0x100
配置CFG_LOAD0x110
配置CFG_RESET0x120
按键KEYMAP_GET0x20层号
按键KEYMAP_SET0x21层号
按键LAYER_GET0x220间接(状态获取可替代)
按键LAYER_SET0x230可扩展使用
RGBRGB_GET0x300
RGBRGB_SET0x310
MACRO_INFO0x40槽位号 / 0xFF协议支持,Studio 未封装
MACRO_GET0x41槽位号协议支持,Studio 未封装
MACRO_SET0x42槽位号协议支持,Studio 未封装
MACRO_DEL0x43槽位号协议支持,Studio 未封装
FNFNKEY_GET0x500
FNFNKEY_SET0x510
电源BATTERY0x600
日志LOG0x70日志类别异步接收
日志LOG_GET0x710
日志LOG_SET0x720

字节级协议定义(当前实现)

说明:下文 DATA[n] 均指帧内 0x03 起始的数据区偏移。

1. SYS_INFO (0x01)

请求

字段
SUB0x00
LEN0
DATA

响应LEN=14

DATA 偏移大小字段说明
01status状态码
11vid_hiVID 高字节
21vid_loVID 低字节
31pid_hiPID 高字节
41pid_loPID 低字节
51version_major固件主版本
61version_minor固件次版本
71version_patch固件补丁版本
81max_layers最大层数
91max_keys单层最大键位数
101macro_slots宏槽位数
111keyboard_type0=基础款, 1=五键款, 2=旋钮款
121actual_key_count当前键盘类型实际键位数
131fn_key_countFN 键数量

字节序

VID/PID 在该响应中采用 高字节在前(大端表示)

2. SYS_STATUS (0x02)

请求SUB=0x00, LEN=0

响应LEN=6

DATA 偏移大小字段说明
01status状态码
11work_mode当前模式(USB/BLE/...)
21conn_state连接状态
31current_layer当前层
41battery_level电量(0-100)
51is_charging充电状态(0/1)

3. 配置命令 CFG_SAVE / CFG_LOAD / CFG_RESET0x10/0x11/0x12

请求SUB=0x00, LEN=0

响应LEN=1

DATA 偏移大小字段
01status

4. KEYMAP_GET (0x20)

请求

字段
SUBlayer_index (0~4)
LEN0

响应(成功)LEN=36

DATA 偏移大小字段说明
01status0x00
11num_layers当前层数
21current_layer当前激活层
31default_layer默认层
4~3532layer_datakbd_layer_t(8 键 × 4B)

响应(失败)LEN=1

DATA[0]含义
KBD_RESP_ERR_PARAM层号超出 num_layers

layer_data(32B)=kbd_layer_t

每层固定 8 个按键,每键 4 字节 kbd_action_t

偏移(层内)大小字段
01type
11modifier
21param1
31param2

i 个键偏移 = i * 4

5. KEYMAP_SET (0x21)

请求(推荐 LEN=35

DATA 偏移大小字段说明
01num_layers1~KBD_MAX_LAYERS
11reserved保留(Studio 当前写 0
21default_layer默认层
3~3432layer_data目标层 kbd_layer_t

SUB = layer_index (0~4)

响应LEN=1

DATA[0]含义
status成功或失败

兼容行为

当前固件对 LEN < 35 不会直接报错,仍可能返回 OK(仅打印日志)。Studio 应始终发送完整 35B

6. LAYER_GET (0x22)

请求SUB=0x00, LEN=0

响应LEN=4

DATA 偏移大小字段
01status
11current_layer
21num_layers
31default_layer

7. LAYER_SET (0x23)

请求LEN>=1

DATA 偏移大小字段
01target_layer

响应LEN=2

DATA 偏移大小字段说明
01statusOKERR_PARAM
11current_layer实际切换后的层

8. RGB_GET (0x30)

请求SUB=0x00, LEN=0

响应LEN=10

DATA 偏移大小字段
01status
11enabled
21mode
31brightness
41speed
51color_r
61color_g
71color_b
81indicator_enabled
91indicator_brightness

9. RGB_SET (0x31)

请求(兼容 LEN=8LEN=9

DATA 偏移大小字段说明
01enabledRGB 总开关
11mode灯效模式
21brightness按键灯亮度
31speed动画速度
41color_r静态颜色 R
51color_g静态颜色 G
61color_b静态颜色 B
71indicator_enabled指示灯开关
81indicator_brightness可选;旧协议可省略

响应LEN=1):DATA[0] = status

10. FNKEY_GET (0x50)

请求SUB=0x00, LEN=0

响应LEN=33

DATA 偏移大小字段
01status
1~3232kbd_fnkey_config_t

kbd_fnkey_config_t(32B)字节布局

由 4 个 kbd_fnkey_entry_t 组成,每项 8B。

单项(8B)布局:

偏移(项内)大小字段
01click_action
11click_param
21long_action
31long_param
41long_press_ms_lo
51long_press_ms_hi
61reserved0
71reserved1

i 个 FN 项偏移 = i * 8

11. FNKEY_SET (0x51)

请求LEN=32

DATA 偏移大小字段
0~3132kbd_fnkey_config_t

响应LEN=1):DATA[0] = status

12. BATTERY (0x60)

请求SUB=0x00, LEN=0

响应LEN=5

DATA 偏移大小字段说明
01status状态码
11level电量百分比 0~100
21charging0=未充电, 1=充电中
31voltage_lo电压毫伏低字节
41voltage_hi电压毫伏高字节

字节序

voltage_mVBATTERY 响应中使用 小端序(LE)。

13. LOG_GET (0x71)

请求SUB=0x00, LEN=0

响应LEN=2

DATA 偏移大小字段
01status
11enabled

14. LOG_SET (0x72)

请求LEN=1

DATA 偏移大小字段说明
01enabled0=关, 非0=开

响应LEN=1):DATA[0] = status

15. 异步日志 LOG (0x70)

设备主动推送,不走命令应答队列。

帧格式

帧字段含义
CMD0x70
SUB日志类别 kbd_log_category_t
LEN日志数据长度(0~8
DATA日志负载(无状态码前缀

日志类别与 DATA 字节定义

SUB类别DATA 字节定义
0x01KEY_EVENT[0]=key_index, [1]=pressed, [2]=action_type, [3]=param
0x02FN_EVENT[0]=fn_id, [1]=is_long, [2]=action, [3]=param
0x03LAYER_EVENT[0]=old_layer, [1]=new_layer
0x04MODE_EVENT[0]=old_mode, [1]=new_mode
0x05BLE_EVENT[0]=state
0x06RGB_EVENT[0]=mode, [1]=brightness
0x07SYSTEM_EVENT[0]=eventBOOT/SLEEP/WAKEUP

16. MACRO_INFO (0x40)

16.1 宏总览(SUB=0xFF

请求LEN=0

响应(成功 LEN=11

DATA 偏移大小字段
01status
11macro_slots(当前为 8)
21used_count
3~108valid_flags[8]1=有效, 0=无效

16.2 宏详情(SUB=slot

请求LEN=0

响应(成功)LEN=25

DATA 偏移大小字段
01status
1~2424kbd_macro_header_t

响应(失败)LEN=1

DATA[0]含义
KBD_RESP_ERR_NOT_FOUND槽位无有效宏

kbd_macro_header_t(24B)字节布局

偏移(头内)大小字段说明
01valid0xAA=有效
11id宏 ID(0~7)
21action_count_lo小端
31action_count_hi小端
41data_size_lo小端
51data_size_hi小端
61reserved0保留
71reserved1保留
8~2316nameUTF-8 名称(可含 \0 结尾)

17. MACRO_GET (0x41)

请求SUB=slot, LEN=3

DATA 偏移大小字段说明
01offset_hi宏数据读取偏移高字节
11offset_lo宏数据读取偏移低字节
21req_len请求长度(固件内部会 clamp 到 <=56

响应(成功)LEN = 5 + read_len

DATA 偏移大小字段说明
01statusOK
11offset_hi回显偏移高字节
21offset_lo回显偏移低字节
31read_len实际读取长度
41is_last1=到达末尾, 0=仍有后续
5..read_lenchunk宏数据片段

响应(失败)LEN=1

DATA[0]含义
KBD_RESP_ERR_NOT_FOUND槽位无宏

字节序

MACRO_GEToffset 在请求/响应中均使用 高字节在前(大端表示)

18. MACRO_SET (0x42)

SUB = slotDATA[0] 为分包序号 seq,定义如下:

  • 0x00:开始写入(BeginWrite)
  • 0x01~0xFE:写入数据块(WriteChunk)
  • 0xFF:结束写入(EndWrite)

18.1 BeginWrite(seq=0x00

请求LEN=25

DATA 偏移大小字段
01seq = 0x00
1~2424kbd_macro_header_t

响应LEN=2

DATA 偏移大小字段
01statusOK/ERR_TOO_LARGE/ERR_FLASH
11seq_echo = 0x00

18.2 WriteChunk(seq=0x01~0xFE

请求LEN = 4 + chunk_len

DATA 偏移大小字段说明
01seq分包序号
11offset_hi偏移高字节
21offset_lo偏移低字节
31chunk_len数据块长度
4..chunk_lenchunk数据块

响应LEN=2

DATA[0]DATA[1]
statusOK/ERR_FLASHseq_echo

18.3 EndWrite(seq=0xFF

请求(最小 LEN=1

DATA[0]含义
0xFF结束写入

响应LEN=2

DATA[0]DATA[1]
statusOK/ERR_FLASH0xFF

19. MACRO_DEL (0x43)

请求SUB=slot, LEN=0

响应LEN=1

DATA[0]含义
statusOKERR_PARAM删除结果

Studio 当前命令调用映射(HidService

Studio 方法命令请求字节响应字节(DATA
getSysInfo()SYS_INFOstatus + 13B 信息
getSysStatus()SYS_STATUSstatus + 5B 状态
getKeymap(layer)KEYMAP_GETSUB=layerstatus + 3B 层头 + 32B层数据
setKeymap(...)KEYMAP_SET35Bstatus
getRgbConfig()RGB_GETstatus + 9B
setRgbConfig()RGB_SET9B(兼容 8B)status
getFnKeyConfig()FNKEY_GETstatus + 32B
setFnKeyConfig()FNKEY_SET32Bstatus
saveConfig()CFG_SAVEstatus
loadConfig()CFG_LOADstatus
resetConfig()CFG_RESETstatus
getBattery()BATTERYstatus + 4B
getLogConfig()LOG_GETstatus + enabled
setLogConfig()LOG_SETenabled(1B)status

可读性优先的代码设计(建议)

目标:在不破坏现有协议兼容性的前提下,提高固件与 Studio 两端代码可读性,并为按分区提交(冷热分离)预留接口。

固件端分层(建议)

文件职责
kbd_proto_codec.h/.c帧封包/解包、常用响应构造(状态码、长度检查)
kbd_proto_handlers.h/.c命令分发与各 HandleXxx 处理函数
kbd_storage_regions.h/.cBASE/KEYMAP/RUNTIME/MACRO 分区读写与 commit
kbd_storage_page.h/.c256B 页日志通用逻辑(CRC、seq、valid)

建议的最小公共接口(固件):

c
// 协议编解码层(建议)
bool KBD_Proto_RequireLen(const kbd_cmd_frame_t *f, uint8_t min_len);
void KBD_Proto_SendStatus(uint8_t cmd, uint8_t sub, kbd_resp_t st);
void KBD_Proto_SendData(uint8_t cmd, uint8_t sub, const void *data, uint8_t len);

// 存储分区层(建议)
typedef enum {
  KBD_CFG_REGION_BASE    = 1u << 0,
  KBD_CFG_REGION_KEYMAP  = 1u << 1,
  KBD_CFG_REGION_RUNTIME = 1u << 2,
} kbd_cfg_region_mask_t;

int KBD_Config_Commit(uint8_t region_mask);
int KBD_Config_GetDirtyMask(void);
int KBD_Runtime_SaveState(uint8_t layer /*, uint8_t mode, uint8_t reserved_slot */);

Studio 端分层(建议)

职责
HidService仅负责帧收发与单命令 API
ConfigSessionService(新增)管理 dirtyMask、提交策略、兼容新旧协议
deviceStoreUI 状态与草稿数据(draft)

建议的最小接口(Studio):

ts
interface ConfigCommitResult {
  requestedMask: number;
  committedMask: number;
  failedMask: number;
}

interface ConfigSessionService {
  markDirty(mask: number): void;
  getDirtyMask(): number;
  commit(mask?: number): Promise<ConfigCommitResult>;
  abort(mask?: number): Promise<void>;
}

协议扩展方案(规划,兼容现有 Studio)

以下命令为建议新增,当前固件未实现。旧版 Studio 可继续使用 KEYMAP_SET/RGB_SET/FNKEY_SET + CFG_SAVE

扩展命令建议

命令码(建议)用途
CFG_CAPS_GET0x13查询协议能力/布局能力
CFG_STATUS_GET0x14查询 dirty_mask、当前槽位、序号
CFG_COMMIT_EX0x15按分区提交(小配置按页写)
CFG_ABORT0x16丢弃未提交 RAM 草稿(可选)

CFG_CAPS_GET (0x13)(建议字节布局)

请求SUB=0, LEN=0

响应(建议 LEN=16

DATA 偏移大小字段说明
01statusOK
11proto_major协议主版本
21proto_minor协议次版本
31frame_size固定 64
41feature_flags_lo能力位低字节
51feature_flags_hi能力位高字节
61region_mask_supported支持提交的分区掩码
71config_slot_count配置槽数量
81runtime_page_countruntime 页数
91cfg_page_size_log28 表示 256B
101macro_erase_block_log212 表示 4KB
111layout_version_major存储布局主版本
121layout_version_minor存储布局次版本
131reserved0保留
141reserved1保留
151reserved2保留

CFG_STATUS_GET (0x14)(建议字节布局)

请求SUB=0, LEN=0

响应(建议 LEN=16

DATA 偏移大小字段
01status
11dirty_mask
21active_config_slot0xFF=无)
31active_runtime_page0xFF=无)
41config_save_count_0(LE)
51config_save_count_1
61config_save_count_2
71config_save_count_3
81runtime_seq_0(LE)
91runtime_seq_1
101runtime_seq_2
111runtime_seq_3
121current_layer_ram
131current_mode_ram
141reserved_profile_slot(预留未来 BLE 槽位)
151busy_flags

CFG_COMMIT_EX (0x15)(建议字节布局)

请求(建议 LEN=2

DATA 偏移大小字段说明
01commit_mask分区掩码(BASE/KEYMAP/RUNTIME
11flags提交标志(如强制/同步)

响应(建议 LEN=8

DATA 偏移大小字段
01status
11requested_mask
21committed_mask
31failed_mask
41active_config_slot
51active_runtime_page
61dirty_mask_after
71detail_code

相关文档