HID协议学习

news2024/11/23 7:10:39

HID协议学习

0. 文档资料

USB_HID协议中文版_USB接口HID设备_AUJsRmB9kg.pdf

HID+报告描述符精细说明_mgCxM8_ci9.pdf

hut1_22_U3cvnwn_ZZ.pdf

1. 基本概念

HID协议是一种基于USB的通讯协议,用于在计算机和输入设备之间进行数据传输。HID协议定义了标准的数据格式、命令结构以及传输方式,使得不同厂商生产的输入设备可以被操作系统识别和兼容。

  • HID协议的实现基于USB(Universal Serial Bus)接口,因此HID设备通常都是通过USB接口与计算机相连的。在HID协议中,设备会向计算机发送一系列的报告,描述设备的状态和用户的操作。计算机则可以根据这些报告来识别设备,并对用户的操作做出相应的响应。

  • HID协议支持的设备种类非常广泛,包括但不限于键盘、鼠标、游戏手柄、摄像头、扫描仪等等。这些设备都可以通过HID协议与计算机进行通信,从而实现与用户的交互。

2. 报告描述符详解

报表描述符定义了执行设备功能的数据格式和使用方法。
报表描述符和 USB 的其他描述符是不一样的,它不是一个简单的表格,报表描述符是 USB 所有描述符中最复杂的。报表描述符非常复杂而有弹性,因为它需要处理各种用途的设备。报表的数据必须以简洁的格式来储存,这样才不会浪费设备内的储存空间以及数据传输时的总线时间。实际上可以这样理解,报表内容的简洁,是通过报表描述符全面的、复杂的数据描述实现的。
报表描述符必须先描述数据的大小与内容。报表描述符的内容与大小因设备的不同而不同,在进行报表传输之前,主机必须先请求设备的报表描述符,只有得到了报表描述符才可正确解析报表的数据。报表描述符是报表描述项目(Item)的集合,每一个描述项目都有相对统一的数据结构,项目很多,通过编码实现

2.1 项目

在这里插入图片描述

见上图,报表描述符由描述 HID 设备的数据项目(Item)组成,项目的第一个字节(项目前缀)由三部分构成,即项目类型(item type)、项目标签(item tag)和项目长度(item size)。其中项目类型说明项目的数据类型,项目标签说明项目的功能,项目长度说明项目的数据部分的长度。
HID 的项目有短项目和长项目两种,其中短项目的格式如下图

在这里插入图片描述

短项目的数据字节数由 bSize 的值定义,bSize 为 0、1、2、3 时 Data 部分的字节数分别为 0、1、2、4 个字节。短项目的项目类型由 bType 定义,bType 为 0、1、2 时分别为 Main、Global 和 Local 类型。
长项目可以携带较多的数据,其格式如下图

在这里插入图片描述

项目中的第一个字节为上图中的特定值时表明该项目是一个长项目。长项目中的bDataSize 说明 Data 部分的字节数,bLongItemTag 在 HID 规范中没有定义。
下面是通过汇编实现的一个简单的报表描述符,描述符的每一行是一个项目,该描述符描述了一个从设备接收 2 个字节的输入报表和发送 2 个字节到设备的输出报表。

HID_Report_desc_table:
db 06h, A0h, FFh ; Usage Page(Vendor defined) 定义设备功能
db 09h, A5h ; Usage(Vendor Defined) 定义用法
db A1h, 01h ; Collection(Application) 开一个集合
db 09H, A6h ; Usage(Vendor defined) 定义用法
; 输入报表
db 09h, A7h ; Usgae(Vendor defined) 定义用法
db 15h, 80h ; Logical Minimum 定义输入最小值=-128
db 25h, 7Fh ; Logical Maximum 定义输入最大值=+127
db 75h, 08h ; Report Size 定义报表数据项大小=8
db 95h, 02h ; Report Count 定义报表数据向个数=2
db 81h, 02h ; Input(Data,Variable,Absolute) 输入项目
; 输出报表
db 09h, A9h ; Usgae(Vendor defined) 定义用法
db 15h, 80h ; Logical Minimum 定义输入最小值=-128
db 25h, 7Fh ; Logical Maximum 定义输入最大值=+127
db 75h, 08h ; Report Size 定义报表数据项大小=8
db 95h, 02h ; Report Count 定义报表数据向个数=2
db 91h, 02h ; Output(Data,Variable,Absolute) 输出项目
db C0h ; End Collection 关闭集合

2.2 项目分类

报表的项目有 MainGlobalLocal 三大类,每一类都有多个不同的项目,实现不同
的描述。
Main 类项目用于定义报表描述符中的数据项。也可以组合其中的若干数据项成为一个集合。Main 项目可以分为带数据的 Main 项目和不带数据的 Main 项目。带数据项的 Main用于生成报表中的数据项,包括 Input、Output 和 Feature 项目。不带数据的 Main 项目不生成报表中的数据项,包括 Collection 和 End Collection 项目。
Global 类项目实现对数据的描述,用来识别报表并且描述报表内的数据,包括数据的功能、最大与最小允许值以及数据项的大小与数目等。改变由 Main 类项目生成的项目状态表。Global 类项目描述对后续的所有项目有效,除非遇到有新的 Global 类项目。
Local 类项目定义控制的特征,这一类项目的作用域不超过下一个 Main 项目,所以在每一 Main 项目之前可能有多个 Local 项目。Local 项目用于描述后面的 Input、Output 和Feature 项目`

在这里插入图片描述

2.3报告描述符案例解析

案例1

static const u8 hidkey_report_map[] = {
    0x05, 0x0C,        // Usage Page (Consumer)
    0x09, 0x01,        // Usage (Consumer Control)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x01,        //   Report ID (1)
    0x09, 0xE9,        //   Usage (Volume Increment)
    0x09, 0xEA,        //   Usage (Volume Decrement)
    0x09, 0xCD,        //   Usage (Play/Pause)
    0x09, 0xE2,        //   Usage (Mute)
    0x09, 0xB6,        //   Usage (Scan Previous Track)
    0x09, 0xB5,        //   Usage (Scan Next Track)
    0x09, 0xB3,        //   Usage (Fast Forward)
    0x09, 0xB4,        //   Usage (Rewind)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x10,        //   Report Count (16)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection
    // 35 bytes
};

例如看以上代码,ID设备的报告描述符(Report Descriptor)和一些使用该设备时可能需要的命名常量。报告描述符定义了所使用的HID协议中消费者设备(Consumer Device)的控制键,这些键包括音量调节、播放/暂停、静音、上一个/下一个曲目以及快进/快退。每个控制键由一个唯一的Usage ID(Usage Page + Usage ID)标识,并且在报告输入功能中使用1位来表示该键是否被按下。

这段代码定义了一个HID报告描述符,用于实现一组控制功能按键的映射。具体来说,它描述了一组使用Consumer Page的控制按键 Usage,并指定相应Usage的最小值、最大值、大小(占据多少比特)、数量等信息。

常量hidkey_report_map[]列出了描述符中的各个字段及其值:

  • 第1-2字节:Usage Page标识了所采用的设备类型(这里为0x0C,表示使用 Consumer Page)。

  • 第3-4字节:Usage标识了使用哪些控制按键(包括音量加减、播放/暂停、静音、上一曲、下一曲、快进、倒退)。

  • 第5-6字节:Collection字段说明后续定义的用途属于Application集合。类似于c语言的花括号

  • 第7字节:Report ID标识了该HID报告的唯一性,用于区分多个报告。

  • 第8~23字节:定义了使用的各个控制按键对应的Usage。

  • 第24~26字节:Logical Minimum指定了使用的控制按键取值的最小值(此处为0)。

  • 第27~29字节:Logical Maximum指定了使用的控制按键取值的最大值(此处为1)。

  • 第30字节:Report Size指定了每个Usage所占用的比特数(此处为1)。

  • 第31字节:Report Count指定了使用的Usage的数量(此处为16)。

  • 第32字节:Input字段说明了这一组控制按键的发送信息是从设备传输到主机的。

  • 第33字节:End Collection表示集合定义结束。类似于c语言的花括号

该HID报告描述符的作用在于,让USB主机知道如何解析来自HID设备的输入数据。通过正确解析描述符,实现与设备间的通信和交互。

// consumer key
#define CONSUMER_VOLUME_INC             0x0001
#define CONSUMER_VOLUME_DEC             0x0002
#define CONSUMER_PLAY_PAUSE             0x0004
#define CONSUMER_MUTE                   0x0008
#define CONSUMER_SCAN_PREV_TRACK        0x0010
#define CONSUMER_SCAN_NEXT_TRACK        0x0020
#define CONSUMER_SCAN_FRAME_FORWARD     0x0040
#define CONSUMER_SCAN_FRAME_BACK        0x0080

如看上述代码,在源码常量则将对应的控制键映射为了十六进制值,这些值可以用来生成报告数据并将其发送到主机。例如,按下音量增加键时,将使用0x0001值向主机发送包含音量增加键的报告数据。同样,通过检查从主机返回的报告数据,程序也可以知道用户是否按下了特定的控制键,以便在应用程序中执行相应的操作。那为什么0x0001可以对应音量升呢?那是因为是通过bit位来控制功能的发送,当发送的数据第一位为1时音量升高,第二位为1时音量降低,其余位都为0…具体可以看一下手绘图,这是一一对应的一个关系,这种对应关系也是官方自己定义的

在这里插入图片描述

比如发送一个 {0x00, 0x01}(相当于0x0001)的数据给usb,具体表现出来就是 音量加的功能。为什么?首先发送数据之前得知道需要发多少Bytes(发送多少Bytes = (Report Size * Report Count)/ 8);其次每一个Usage的值只能取0(Logical Minimum)或者1(Logical Maximum);那就可以知道如果要发送音量加就需要设置为{0x00, 0x01}。

在这里插入图片描述

案例2

static const u8 keyfob_report_map[] = {
    //通用按键
    0x05, 0x0C,        // Usage Page (Consumer)
    0x09, 0x01,        // Usage (Consumer Control)
    0xA1, 0x01,        // Collection (Application)
    0x85, 0x03,        //   Report ID (3)
    0x15, 0x00,        //   Logical Minimum (0)
    0x25, 0x01,        //   Logical Maximum (1)
    0x75, 0x01,        //   Report Size (1)
    0x95, 0x0B,        //   Report Count (11)
    0x0A, 0x23, 0x02,  //   Usage (AC Home)
    0x0A, 0x21, 0x02,  //   Usage (AC Search)
    0x0A, 0xB1, 0x01,  //   Usage (AL Screen Saver)
    0x09, 0xB8,        //   Usage (Eject)
    0x09, 0xB6,        //   Usage (Scan Previous Track)
    0x09, 0xCD,        //   Usage (Play/Pause)
    0x09, 0xB5,        //   Usage (Scan Next Track)
    0x09, 0xE2,        //   Usage (Mute)
    0x09, 0xEA,        //   Usage (Volume Decrement)
    0x09, 0xE9,        //   Usage (Volume Increment)
    0x09, 0x30,        //   Usage (Power)
    0x0A, 0xAE, 0x01,  //   Usage (AL Keyboard Layout)
    0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0x95, 0x01,        //   Report Count (1)
    0x75, 0x0D,        //   Report Size (13)
    0x81, 0x03,        //   Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
    0xC0,              // End Collection

    // 119 bytes
};

extern int ble_hid_data_send(u8 report_id, u8 *data, u16 len);

再来看这个案例,如果我们要实现Usage (AC Search)这个功能我们应该发送什么数据呢?依旧用位按键定位法,首先我们先算一下要发送多少字节的数据,可以看到有两个size和count,因此我们算出来的结果是111+131 = 24bit =3byte,因此我们要发送的字节数为3

在这里插入图片描述

而我们的操作数有12位,因此三字节发送的数据与之对应的是
0x000001(000000000000000000000001)—Usage (AC Home)
0x000002(000000000000000000000010)—Usage (AC Search)
0x000004(000000000000000000000100)—Usage (AL Screen Saver)
0x000008(000000000000000000001000)—Usage (Eject)
0x000100(000000000000000000010000)—Usage (Scan Previous Track)

如此往下一一按bit进行对应就可以实现自己的功能

以下是这个数组中每个数值(十六进制)的详细解释:

  • 0x05, 0x0C:使用页 (Usage Page) - Consumer。说明此hid report map定义了一个消费者设备类别。

  • 0x09, 0x01:使用 (Usage) - 消费器控制 (Consumer Control)。说明此hid report map定义了一个消费者控制按键。

  • 0xA1, 0x01:集合 (Collection) - 应用程序 (Application)。指定本HID report map包含应用程序类型的控件,并且相邻的USSAGE数据由同一集合处理。

  • 0x85, 0x03:报告 ID (Report ID) - 3。指定此hid report map定义的报告类型为ID号为3的报告。

  • 0x15, 0x00:逻辑最小值 (Logical Minimum) - 0。指定接收此报告的系统(如电脑)将接收到的字节映射到具有最小可能值的数字值。

  • 0x25, 0x01:逻辑最大值 (Logical Maximum) - 1。指定接收此报告的系统将接收到的字节映射到具有最大可能值的数字值。

  • 0x75, 0x01:报告大小 (Report Size) - 1。指定其中每个按键事件的报告数据位数是1位,即开/关状态。

  • 0x95, 0x0B:报告计数 (Report Count) - 11。指定此hid report map定义的报告中包括11个按键事件。

  • 0x0A, 0x23, 0x02:使用 (Usage) - AC Home。指定第一个按键对应于AC Home使用码,表示主页功能键。

  • 0x0A, 0x21, 0x02:使用 (Usage) - AC Search。指定第二个按键对应于AC Search使用码,表示搜索功能键。

  • 0x0A, 0xB1, 0x01:使用 (Usage) - AL Screen Saver。指定第三个按键对应于AL Screen Saver使用码,表示启动屏幕保护程序。

  • 0x09, 0xB8:使用 (Usage) - 弹出式按钮(Eject)。

  • 0x09, 0xB6:使用 (Usage) - 扫描上一曲目 (Scan Previous Track)。

  • 0x09, 0xCD:使用 (Usage) - 播放/暂停 (Play/Pause)。

  • 0x09, 0xB5:使用 (Usage) - 扫描下一曲目 (Scan Next Track)。

  • 0x09, 0xE2:使用 (Usage) - 静音 (Mute)。

  • 0x09, 0xEA:使用 (Usage) - 音量减小 (Volume Decrement)。

  • 0x09, 0xE9: 使用 (Usage) - 音量增大 (Volume Increment)。

  • 0x09, 0x30:使用 (Usage) - 电源 (Power)。

  • 0x0A, 0xAE, 0x01:使用 (Usage) - AL Keyboard Layout。指定最后一个按键对应于AL Keyboard Layout使用码,表示更改键盘布局。

  • 0x81, 0x02:输入 (Input) - 数据、变量、绝对值、没有回绕、线性、优先状态、无空位置

  • 0x95, 0x01:报告计数 (Report Count) - 1。指定此hid report map定义的报告中包括1个按键事件。

  • 0x75, 0x0D:报告大小 (Report Size) - 13。指定其中每个按键事件的报告数据位数是13位,即keyfob_report_map数组中11个字节(共88位)全部使用,报告数据位长为13位,其他5bits使用填充符号“0”进行填充。

  • 0x81, 0x03:输入 (Input) - 常量、变量、绝对值、没有回绕、线性、优先状态、无空位置。表示HID设备将输出一个全为0的字节作为该 Report ID 的最后一项,也就是按下按键后立即释放时触发的事件。因为退出报告只有该按键特殊事件,并需要调整指针来写入发送函数,所以状态应为常量。

  • 0xC0:结束集合 (End Collection)。指定此 hid report map 定义的集合结束。

参考资料

https://blog.csdn.net/pig10086/article/details/71438990

https://blog.csdn.net/lep150510/article/details/119572626

3.如何自己实现一个报告描述符实现一个功能呢?

参考

https://www.usbzh.com/article/detail-830.html

4. 特点

HID协议的优点包括以下几个方面:

  1. 简单易用:HID协议定义的指令和数据格式都很简单,易于理解并进行开发。对于绝大多数的输入设备,我们只需要遵循HID协议来实现输入输出即可。

  2. 高效性能:HID协议使用了一种类似于中断传输的方式,在需要时及时传输数据,降低了延迟,并保证了数据的实时性。这使得HID协议更适合用于实时性要求比较高的应用。

  3. 可靠性:HID协议的实现通常基于硬件设计,配合驱动程序和操作系统支持,使得输入设备能够与计算机无缝连接和互通。也因此HID协议具有高可靠性、稳定性等特点,提高了产品的品质。

此外,HID协议还支持多种输入设备类型(如键盘、鼠标、摇杆等),并且支持对输入设备进行配置和控制,如设置灯光、自定义按键功能等。

总的来说,HID协议是一种很好的通讯协议,使得输入设备的设计和使用更加简单、高效、可靠,同时也提高了用户的使用体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/650856.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

动态规划算法(子数组专题1)

动态规划算法专辑之子数组问题(1) 本专栏将从状态定义、状态转移方程、初始化、填表顺序、返回值这五大细节来详细讲述动态规划的算法的解题思路及代码实现一、什么是子数组 子数组:子数组是数组中的一个连续部分的集合,子序列可…

Python+Selenium UI自动化测试环境搭建及使用

目录 一、什么是Selenium ? 二、Selenium环境搭建 三、WebDriver API 总结: 一、什么是Selenium ? Selenium 是一个浏览器自动化测试框架,它主要用于web应用程序的自动化测试,其主要特点如下:开源、免费…

缅怀(上次写博客是2009年10月24日)

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

Nucleo-F411RE (STM32F411)LL库体验 3 - 滴嗒定时器的配置

Nucleo-F411RE (STM32F411)LL库体验 3 - 滴嗒定时器的配置 1、LL库延时 LL库初始化时钟的时候调用了LL_Init1msTick(100000000)函数,这个函数其实就是初始化了系统的滴答定时器。 LL_InitTick原型如下: load值 sysclk/1000&a…

RocketMQ架构和工作流程

一.MQ概述 1.简介 MQ,Message Queue,是一种提供消息队列服务的中间件,也称为消息中间件,是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据。一般消息的体量不会很大。 2.用途 限流削峰 MQ可以将系统的超量请求…

接口测试工具怎么选?这个技巧你一定要知道

目录 前言 一、易用性 二、灵活性 三、可靠性 测试用例 接口测试数据 自动化测试 测试报告 总结 前言 当今软性开发中,接口测试已成为必不可少的一环,该如何选择接口测试工具?选择合适的接口测试工具对于程房员来说非常重要,因为…

SQL死锁

前言: 使用脚本刷数据时,开多线程经常遇到死锁现象,面试也经常问到,故开此篇 日志错误示例: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock fo…

Tplink企业版开启ipv6

Tplink企业版开启ipv6 1、登录路由器 路由器的默认地址一般为:192.168.0.1,登录成功后如下图: 2、WAN设置ipv6 wan是设置启用ipv6模式,如果这里无法启用,主要是因为“接口模式”中启用了桥接模式,可以关闭…

多线程详解

多线程详解 Process和Thread 程序是指令和数据的有序结合,其本身没有任何运行的含义,是一个静态的概念 进程是执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位 通常在一个进程中可以包含若干个线程。线程是CPU调…

(数组) 922. 按奇偶排序数组 II ——【Leetcode每日一题】

❓922. 按奇偶排序数组 II 难度:简单 给定一个非负整数数组 nums, nums 中一半整数是 奇数 ,一半整数是 偶数 。 对数组进行排序,以便当 nums[i] 为奇数时,i 也是 奇数 ;当 nums[i] 为偶数时&#xff0c…

开发语言的更新换代,都是为了更好地提高生产力,Kotlin也是如此~

作为一名Android开发,学习Kotlin是很有必要的。以下是一些原因: 1.Kotlin是官方支持的语言。 在2017年Google宣布支持Kotlin作为官方开发语言后,Kotlin已成为Android生态系统的重要组成部分。此举表明Kotlin的发展前景非常广阔,…

uniapp兼容多pda扫描扫码

前景 网上有现成的针对单个pda扫码录入的代码,但是公司的需求是在多个不同厂商pda上运行,这就会导致不同的pda默认的广播动作和广播标签不一致的情况,目前也没有获取这俩字段的api。 单个pda扫描扫码代码 先创建一个scanCode.js的文件 le…

UnoCSS给了我一个不用tailwindcss的理由

相同的原由 & 前言 如果你没有听说过 tailwindcss 或者 unocss,请先 return 先去了解一下😝。 开发上:可能为你甚至你们的前端团队节省很多写样式的时间,也能让你或者你们的项目开发体验有很大提升生产上:你们的…

VS2013创建一个MFC工程的步骤

目录 1、新建项目,选择”MFC应用程序“; 2、应用程序类型,选择“基于对话框”; 3、对话框的标题,默认是和项目的名字一致,按需修改; 4、高级功能,可以保持默认; 5、…

一个女测试工程师的大厂日常

今天给大家分享两个朋友的故事,他们分别在国内两家顶尖的互联网大厂,一个在头条,一个在蚂蚁。 头条的故事 头条的主人公,在入职后的一年里,晚上十点半下班是比较早了,基本上都是十一点半左右下班&#xff…

低成本开发专属小程序支持自定义开发设计

传统定制开发小程序成本高,还需要不断地沟通和交流才能一步步地去实现你想要的功能和效果,那么除了传统的定制开发小程序外,用户其实还可以选择使用模板开发小程序,不仅能实现小程序的所有基础功能,还不用编程维护和开…

进程的描述与控制

文章目录 前趋图和程序执行前趋图程序顺序执行程序并发执行 进程引入目的进程的描述进程的定义进程的特征进程的基本状态与转换挂起操作和进程状态的转换挂起操作引入引入挂起操作后进程3个基本状态间的转换引入挂起操作后进程5个基本状态间的转换进程管理中的数据结构OS中用于…

antdb-upgrade大版本升级介绍

antdb-upgrade pg_upgrade 是postgresql 大版本升级的得力工具。 数据库系统数据部分通过 new version的pg_upgrade自动升级完成数据库用户数据部分,主要有两种用法: 使用pg_upgrade copy物理拷贝方式升级(非copy to/copy from逻辑拷贝)。使用pg_upgra…

内网渗透—隧道搭建SPP与NPS内网穿透

内网渗透—隧道搭建&SPP与NPS内网穿透 1. 前言2. SPP2.1. SPP代理通信2.1.1. 服务端配置2.1.2. 客户端配置2.1.3. CS设置2.1.3.1. 设置生成的监听器2.1.3.2. 设置监听的监听器 2.1.4. 执行效果 2.2. SPP隧道建立2.2.1. 服务端设置2.2.2. 客户端配置2.2.3. CS设置2.2.3.1. 设…

Mybatis学习笔记三

目录 一、MyBatis的缓存1.1 MyBatis的一级缓存1.2 MyBatis的二级缓存1.3 二级缓存的相关配置1.4 MyBatis缓存查询的顺序1.5 整合第三方缓存EHCache(了解) 二、MyBatis的逆向工程2.1 创建逆向工程的步骤2.2 简单使用查询增改 三、 分页插件3.1 分页插件使…