AIWORK / HID BYTE ATLAS / VOL. L

把 HID 报文
拆到每一个字节

这不是又一份设备选购指南。本页只做一件事:把描述符与数据帧摊开,逐字节标出偏移、位宽、字节序与解释值,让「为什么这一帧读出来是这个数」变成能回到原始 hex 的确定结论。十五簇、九十篇逐字节拆解记录,按三十天逐日释放。

REPORT DESCRIPTOR15 CLUSTERS90 PAPERS159 TERMS45 FIGURESDAILY × 30
90 篇逐字节拆解记录 · 三十天逐日释放
15 簇从前缀字节到异常帧回归
45 张等距分层配图 · 无水印可引用
159 词长尾词分散进标题与正文语境
§ 01

字节现场:先把范围钉死

FIELD NOTES / 0x00

讨论 HID 设备时,大多数资料停在「能连上、能按键、能移动」这一层,一旦追问「这一串字节里哪一位代表什么」,就只剩下零散的规范摘录。本专题把视角压到字节层面:描述符是变长的项序列,数据帧是按位宽拼出来的字段集合,两者之间靠一张状态机联系起来。前缀字节的低两位决定后面跟几个数据字节,全局项赋值之后一直沿用到下一次同项出现,局部项在遇到主项之后立即清空;这三条规则合在一起,才解释得了为什么同样的十六进制值在不同位置会被读成完全不同的东西。

我们的记录方式很朴素:先截取一段完整原始帧,连同采集时刻、设备标识与所用规则版本一起存;再按描述符确定每个字段的偏移与位宽,逐字节标注十六进制值、十进制解释与中文名称;然后由第二个人用另一套规则独立解一遍,把分歧列成对照表;最后把原始 hex dump、标注稿与判定结论归入同一目录,历史版本只读不覆盖。这样整理出来的结果,半年之后回看仍能逐条追到具体帧,而不是靠当事人补写记忆。文中出现的所有偏移与阈值都来自可控环境下的重复抓包,用于建立同一套比较基准,换设备批次、换报表格式之后应当重测;把测量条件连同数字一起归档,比只留一个结论有用得多。

十五簇覆盖报表描述符总览、Usage Page 与 Usage、Collection 嵌套、全局项状态机、局部项复位、三类主项位标志、中断端点轮询、控制传输类请求、引导协议切换、修饰键位域、补码位移、小端拼装、报表 ID 分流、抓包校验与异常帧回归。每簇六个角度:字段定义、逐字节拆解、十六进制实例、误读边界、抓包复现、复核清单。九十篇互为补充,与站内其他专题各自负责不同环节,不重复叙述。读者若需要设备形态、接入拓扑、效能核算或工位搭配,可从页脚的全站入口进入对应专题。

§ 02

五层协议栈:点一层,看一层

ISOMETRIC STACK / 5 LAYERS
L5 / APPLICATION

应用层

键值、位移与滚轮等业务语义在这一层落地。上层拿到的是解释后的字段,而不是原始字节;本层出错通常表现为「动作对了、含义错了」。

Usage键值槽相对位移

等距图不是装饰。五层分别对应物理层、传输层、描述符层、报表层与应用层,任何一次解析争议都可以先定位到某一层再讨论:物理层看端点方向与最大包长,传输层看轮询间隔与帧重组,描述符层看前缀与项序列,报表层看位宽、字节序与报表 ID,应用层看 Usage 编号与业务语义。点击左侧任意一层即可切换右侧说明与典型字段。

§ 03

报文解析器:亲手解一帧

LIVE DECODER / INTERACTIVE

INPUT / HEX FRAME

输入空格分隔的十六进制字节,例如 01 00 1A 00 00 00 00 00。默认按带保留字节的八字节键盘引导报表解释。

HOW TO READ / 字段口径

第 0 字节是修饰键位域,八位分别对应左右 Ctrl、Shift、Alt、GUI,判断某个键是否按下要做按位与,不等于零即有效;把它当成一个键码数值是最常见的误读。

第 1 字节固定为保留位,正常应恒为零。长期非零时优先怀疑描述符与解析规则不匹配,而不是先改业务代码。

第 2 到第 7 字节是六个键值槽,槽里放的是 Usage 编号,不是 ASCII 码。全零帧表示所有键已释放,属于正常状态,统计按键次数时应排除。

若设备带报表 ID,整帧最前面会多一字节前缀,且它不计入描述符算出的位宽;此时请把输入改成九字节再观察第一槽如何整体后移一位。

§ 04

位域实验台:八位怎么拼成一个字节

BITFIELD LAB / 8 BITS

MODIFIER BYTE / 点击位开关

0x00  ·  0000 0000  ·  0
每点一位,右侧数值实时按 value |= (1 << n) 更新。组合键就是同一字节里多个位同时置一,不需要额外字节。

SIGN & ORDER / 同一字节的两种解释

把 0xFE 当无符号读,得到 254;按 8 位补码读,得到 -2。鼠标向左移动两格与向右猛移 254 格,在十六进制里长得一模一样,区别全在符号扩展有没有做。

超过一字节的数值还要按小端顺序拼回来:低位字节在前、高位字节在后。字段若落在非整字节边界上,例如 12 位字段跨两个字节,必须先用移位与掩码取出,再按声明的逻辑范围决定要不要做符号扩展。

因此解析器的输入不止是字节串,还包括三项前提:位宽、字节序、逻辑范围。三项缺一,解释值就只是猜测。

§ 05

十五簇节点树与长尾词导览

CLUSTER TREE / 159 UNIQUE TERMS

下面这些长尾词按主题分散进入九十篇文章的标题、二级标题、十六进制对照表与复核清单,而不是集中堆在落地页标题里。这样做的目的很朴素:让每篇文章回答一个具体问题,例如「缺一个 0xC0 之后字段如何整体偏移」「0xFE 为什么不是 254」,而不是用一串词去换一个排名。落地页元信息只保留少量核心词,其余全部落到正文语境中;点击任意节点可展开该簇的字节边界说明。

HID报表描述符HID描述符解析HID短项前缀HID长项前缀HID项标签HID字节偏移HID Usage PageHID Usage编号HID通用桌面页HID键盘页HID消费者页HID编号对照表HID CollectionHID End CollectionHID Application集合HID Physical集合HID嵌套深度HID配对校验HID全局项HID Report SizeHID Report CountHID Logical MinimumHID Logical MaximumHID状态继承HID局部项HID主项HID局部项复位HID Usage列表HID DesignatorHID String索引HID Input报表HID Output报表HID Feature报表HID位标志HID绝对值字段HID相对值字段HID中断端点HID bIntervalHID轮询间隔HID最大包长HID报文重组HID采样窗口HID Get_ReportHID Set_ReportHID类请求HID wValueHID bmRequestTypeHID控制传输
CLUSTER 01 / 06 PAPERS
报表描述符总览
前缀字节低两位決定数据长度,0xFE 走长项分支,逐项记录起始偏移。
CLUSTER 02 / 12 PAPERS
Usage Page 与 Usage
同一 Usage 数值在不同页下含义不同,跨段解析必须带上页号。
CLUSTER 03 / 18 PAPERS
Collection 嵌套与闭合
0xA1 入栈、0xC0 出栈,结束时栈必须为空,深度建议三层以内。
CLUSTER 04 / 24 PAPERS
全局项状态机
Report Size 乘 Report Count 才是本段位宽,负数按补码解释。
CLUSTER 05 / 30 PAPERS
局部项作用域与复位
局部项在遇到主项后立即清空,复位次数应等于主项个数。
CLUSTER 06 / 36 PAPERS
Input / Output / Feature 报表
0x81 / 0x91 / 0xB1 后随字节是位标志,不是数值。
CLUSTER 07 / 42 PAPERS
中断端点与轮询间隔
bInterval 单位随速率变化,超长报表必须重组后再解释。
CLUSTER 08 / 48 PAPERS
控制传输与 HID 类请求
wValue 高字节是报表类型、低字节是报表 ID,方向位先判。
CLUSTER 09 / 54 PAPERS
引导协议与报表协议
固定八字节引导帧与自定义报表帧要分段用两套规则解释。
CLUSTER 10 / 60 PAPERS
修饰键位域与保留字节
首字节按位展开,第二字节保留恒零,六槽放 Usage 编号。
CLUSTER 11 / 66 PAPERS
鼠标位移与滚轮编码
相对位移带符号,多帧合计要带符号相加,不取绝对值。
CLUSTER 12 / 72 PAPERS
多字节数值与字节序
小端拼装、移位掩码、逻辑范围三者共同决定最终数值。
CLUSTER 13 / 78 PAPERS
报表 ID 前缀与多路复用
有 Report ID 项时首字节是前缀,按 ID 查分流表选帧长度。
CLUSTER 14 / 84 PAPERS
抓包对照与帧校验
原始 hex、标注稿、结论三方对照,历史版本只读不覆盖。
CLUSTER 15 / 90 PAPERS
枚举识别与异常帧回归
枚举顺序完整、接口类 0x03、四类异常帧回归全通过才放行。
§ 06

时序泳道与正常/异常帧对照

TIMING LANES / DIFF SLIDER

INTERRUPT IN / 轮询与上报泳道

HOSTIN EPFRAMEDECODE
主机按 bInterval 轮询,设备在有事件时于中断输入端点上报。事件密集时一次轮询可能取到累积状态,这是合并上报而非丢包;采样窗口取轮询间隔的整数倍,统计才不随窗口起止位置抖动。

DIFF / 拖动滑块对照两帧

正常帧 / 8 BYTE BOOT REPORT OFFSET 00 01 02 03 04 05 06 07 HEX 00 00 04 00 00 00 00 00 MOD 0x00 保留 0x00 KEYS 04 00... 解释 左 Ctrl 未按 / 保留位为零 槽 1 = 0x04 (Usage a) 结论 PASS · 字段边界对齐
异常帧 / 漏读 REPORT ID 前缀 OFFSET 00 01 02 03 04 05 06 07 HEX 02 00 00 04 00 00 00 00 MOD 0x02 → 误判右 Shift 按下 保留 0x00 KEYS 00 04 00... 解释 实际首字节 0x02 是报表 ID 结论 FAIL · 整体错移一位
NORMALSHIFTED
§ 07

五段演示:从枚举到异常帧

SIGNAL DEMO / 5 CLIPS
DEMO 01枚举 · 设备与接口描述符
DEMO 02拆帧 · 前缀与项序列
DEMO 03键值 · 修饰键位域与六槽
DEMO 04位移 · 补码与滚轮编码
DEMO 05回归 · 异常帧与对照归档
§ 08

逐字节拆解记录 · 五栏

ARCHIVE / 3 PUBLISHED · 3 PER DAY
§ 09

常见追问与全站入口

FAQ / CROSS LINKS
Q 01 / 点击翻面为什么同一串字节有两种解释?
因为解析前提不同。引导协议用固定八字节格式,报表协议由描述符自由定义;切换点前后必须用两套规则。带报表 ID 时还会多一字节前缀。
Q 02 / 点击翻面0xFE 到底是 254 还是 -2?
取决于逻辑范围。Logical Minimum 为负时按补码解释得 -2;按无符号读得 254。位宽与符号位由描述符声明,不能靠猜。
Q 03 / 点击翻面全局项和局部项差在哪?
全局项赋值后一直沿用到下一次同项出现,是状态机;局部项只作用于紧随其后的主项,主项结束立即复位。混用两者会让字段贴错标签。
Q 04 / 点击翻面抓包里帧数变少是丢包吗?
不一定是。事件密集时一次轮询可取到累积状态,表现为合并上报。先看轮询间隔与采样窗口,再判断是否为真丢包。
Q 05 / 点击翻面为什么要有复核清单?
字节级结论必须能回到原始帧。原始 hex、标注稿、判定结论三方对齐,历史版本只读,人员更替后仍可独立复现。
Q 06 / 点击翻面这些记录和其他专题冲突吗?
不冲突。这里只处理报文落到字节层面后的解释问题;设备形态、接入拓扑、效能核算与工位搭配各有独立专题,互为补充。
×