USB键盘实现——带指示灯的键盘(九)

文章目录

  • 带指示灯的键盘
    • `set_report` 类特殊请求实现
      • 类特殊请求
      • USB 控制端点收到的数据
    • 增加一个输出端点实现
      • 配置描述符集合
      • 输出端点收到的数据

带指示灯的键盘

要实现带指示灯的键盘,有两种方式

  • 除控制端点和输入端点外,不额外增加端点,根据 HID set_report 类特殊请求实现。
  • 除控制端点和输入端点外,额外增加一个输出端点实现。

set_report 类特殊请求实现

类特殊请求

在这里插入图片描述

typedef enum
{
  HID_REQ_CONTROL_GET_REPORT   = 0x01, ///< Get Report
  HID_REQ_CONTROL_GET_IDLE     = 0x02, ///< Get Idle
  HID_REQ_CONTROL_GET_PROTOCOL = 0x03, ///< Get Protocol
  HID_REQ_CONTROL_SET_REPORT   = 0x09, ///< Set Report
  HID_REQ_CONTROL_SET_IDLE     = 0x0a, ///< Set Idle
  HID_REQ_CONTROL_SET_PROTOCOL = 0x0b  ///< Set Protocol
}hid_request_enum_t;

发送到接口的类特殊请求 SET_REPORTbRequest,为 0x09,对应的 wValue 有不同的含义

  • wValue 高位表示报告类型
  • wValue 低位表示报告 ID

报告类型有如下几种形式

typedef enum
{
  HID_REPORT_TYPE_INVALID = 0,
  HID_REPORT_TYPE_INPUT,      ///< Input
  HID_REPORT_TYPE_OUTPUT,     ///< Output
  HID_REPORT_TYPE_FEATURE     ///< Feature
}hid_report_type_t;

USB 控制端点收到的数据

0x21 0x9 0x0 0x2 0x0 0x0 0x1 0x0
  • bmRequestType:0x21
    • 数据传输方向为 0,host-to-device
    • 类请求
    • 请求的接收者为接口
  • bRequest:0x09
    • SET_REPORT,设置报告
  • wValue:0x0200(LSB)
    • 低位:0x00 表示报告 ID 为0
    • 高位:0x02 表述报告类型为 OUTPUT
  • wIndex:0x0000(LSB)
    • 低位:0x00
    • 高位:0x00
  • wLength:0x0001
    • 低位:0x01
    • 高位:0x00

此类特殊请求表示主机有一次 OUT 事务,主机输出一个字节的数据。需要注意的是,这里主机输出的数据传输到了控制端点上

这一个字节的数据各个位的含义如下:

typedef enum
{
  KEYBOARD_LED_NUMLOCK    = BIT(0), ///< Num Lock LED
  KEYBOARD_LED_CAPSLOCK   = BIT(1), ///< Caps Lock LED
  KEYBOARD_LED_SCROLLLOCK = BIT(2), ///< Scroll Lock LED
  KEYBOARD_LED_COMPOSE    = BIT(3), ///< Composition Mode
  KEYBOARD_LED_KANA       = BIT(4) ///< Kana mode
}hid_keyboard_led_bm_t;

根据控制端点的数据,解析相应的位,控制 LED 灯的亮灭即可。

增加一个输出端点实现

除控制端点和输入端点外,额外增加一个输出端点实现,那么端点描述符需要增加一个输出端点的描述符,相应的配置描述符集合需要修改。

增加一个输出端点之后,配置描述符集合的结构就变为

{
    配置描述符,
    接口描述符,
    类特殊描述符(HID 描述符),
    输入端点描述符,
    输出端点描述符
}

设备描述符,字符串描述符等保持不变。

配置描述符集合

则设备返回的配置描述符集合为:

0x9 0x2 0x29 0x0 0x1 0x1 0x0 0xa0 0x32 0x9 0x4 0x0 0x0 0x2 0x3 0x1 0x1 0x0 0x9 0x21 0x11 0x1 0x0 0x1 0x22 0x41 0x0 0x7 0x5 0x81 0x3 0x8 0x0 0xa 0x7 0x5 0x1 0x3 0x8 0x0 0xa 
  • 配置描述符 (0x9 0x2 0x29 0x0 0x1 0x1 0x0 0xa0 0x32)
    • bLength:0x09
      • 描述符的长度。配置描述符的长度为 0x09。
    • bDescriptorType:0x02
      • 描述符的类型。配置描述符的类型编码为 0x02。
    • wTotalLength:0x0029
      • 整个配置描述符集合的总长度,包括配置描述符,接口描述符,类特殊描述符 (HID 描述符) 和端点描述符,注意低字节在前。
    • bNumInterfaces:0x01
      • 该配置所支持的接口数量。通常功能单一的设备只具有一个接口,而复合设备则具有多个接口 。
    • bConfigurationValue:0x01
      • 该配置的值。通常一个 USB 设备可以支持多个配置。
    • iConfiguration:0x00
      • 描述该配置的字符串的索引值,如果该值为 0 ,表示没有字符串。
    • bmAttributes:0xa0
      • 用来描述设备的一些特性。
      • bit7 reserved(set to one)
      • bit5 remote wakeup
    • bMaxPower:0x32
      • 表示设备需要从总线获取的最大电流量,单位为 2 mA。
  • 接口描述符 (0x9 0x4 0x0 0x0 0x2 0x3 0x1 0x1 0x0)
    • bLength:0x09
      • 描述符的长度。标准的 USB 接口描述符的长度为 9 字节
    • bDescriptorType:0x04
      • 描述符的类型。接口描述符的类型编码为 0x04
    • bInterfaceNumber:0x00
      • 接口的编号。当一个配置具有多个接口时,每个接口的编号都不同。第一个接口,编号为 0
    • bAlternateSetting:0x00
      • 接口的备用编号,为 0
    • bNumEndpoints:0x02
      • 非 0 端点的数目。一个输出端点,一个输入端点
    • bInterfaceClass:0x03
      • 该接口所使用的类。USB 键盘是 HID 类, HID 类的编码为 0x03
    • bInterfaceSubClass:0x01
      • 该接口所使用的子类。在 HID1.1 协议中只规定了一种子类:支持 BIOS 引导启动的子类。USB 键盘、键盘属于该子类,子类代码为 0x01
    • bInterfaceProtocol:0x01
      • 如果子类为支持引导启动的子类,则协议可选择鼠标和键盘。键盘代码为 0x01,鼠标代码为 0x02。
    • iInterface:0x00
      • 接口的字符串的索引值。
  • 类特殊描述符 (HID 描述符:0x9 0x21 0x11 0x1 0x0 0x1 0x22 0x41 0x0)
    • bLength:0x09
      • 本 HID 描述符下只有一个下级描述符。所以长度为 9 字节
    • bDescriptorType:0x21
      • HID 描述符的编号为 0x21
    • bcdHID:0x0111
      • 本协议使用的 HID 协议。低字节在先
    • bCountryCode:0x00
      • 设备适用的国家代码,大多数硬件都没有本地化,因此该值为 0
    • bNumDescriptors:0x01
      • 下级描述符的数目。我们只有一个报告描述符
    • bReportType:0x22
      • 下级描述符的类型,为报告描述符,编号为 0x22
    • wReportLength:0x0041
      • 下级描述符的长度。下级描述符为报告描述符
  • 端点描述符(输入端点) (0x7 0x5 0x81 0x3 0x8 0x0 0xa)
    • bLength:0x07
      • 描述符的长度。标准的 USB 端点描述符的长度为 7 字节
    • bDescriptorType:0x05
      • 描述符的类型,端点描述符的类型编码为 0x05
    • bEndpointAddress:0x81
      • 端点的地址, 7 位表示数据方向,输入端点 D7 为 1。所以输入端点 1 的地址为 0x81
    • bmAttributes:0x03
      • D1~D0 为端点传输类型选择, 该端点为中断端点。中断端点的编号为 3。其它位保留为 0
    • wMaxPacketSize:0x0008
      • 该端点的最大包长,低位为 0x08。端点 1 的最大包长为 8 字节, LSB 低字节在前
    • bInterval:0x0a
      • 端点查询的时间,我们设置为 10 个帧时间,即 10ms
  • 端点描述符(输出端点) (0x7 0x5 0x1 0x3 0x8 0x0 0xa)
    • bLength:0x07
      • 描述符的长度。标准的 USB 端点描述符的长度为 7 字节
    • bDescriptorType:0x05
      • 描述符的类型,端点描述符的类型编码为 0x05
    • bEndpointAddress:0x01
      • 端点的地址, 7 位表示数据方向,输出端点 D7 为 0。所以输出端点 1 的地址为 0x01
    • bmAttributes:0x03
      • D1~D0 为端点传输类型选择, 该端点为中断端点。中断端点的编号为 3。其它位保留为 0
    • wMaxPacketSize:0x0008
      • 该端点的最大包长,低位为 0x08。端点 1 的最大包长为 8 字节, LSB 低字节在前
    • bInterval:0x0a
      • 端点查询的时间,我们设置为 10 个帧时间,即 10ms

输出端点收到的数据

0x1 0x0 0x0 0x0 0x0 0x0 0x0 0x0

最低位各个 bit 的含义

typedef enum
{
  KEYBOARD_LED_NUMLOCK    = BIT(0), ///< Num Lock LED
  KEYBOARD_LED_CAPSLOCK   = BIT(1), ///< Caps Lock LED
  KEYBOARD_LED_SCROLLLOCK = BIT(2), ///< Scroll Lock LED
  KEYBOARD_LED_COMPOSE    = BIT(3), ///< Composition Mode
  KEYBOARD_LED_KANA       = BIT(4) ///< Kana mode
}hid_keyboard_led_bm_t;

上面设置输出端点的最大包长为 8 ,这里输出端点收到的数据有 8 个字节,最低为即为有效位。根据第一个字节的各个 bit 判断类型,设置相应的 LED 即可。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

不完全微分算法(SCL+ST代码)

PID控制器的基本算法,可以参看专栏的系列文章,链接如下: 三菱FX3U PLC 位置式PID算法(ST语言)_fx3u pid_RXXW_Dor的博客-CSDN博客三菱PLC自带的PID不必多说,大家可以自行查看指令说明。关于FX3U 增量式PID可以参看专栏的另一篇博客三菱PLC增量式PID算法FB(带死区设置和外部…

springCloud学习【3】之Docker完整版

文章目录一 初识Docker1.1 应用部署的环境问题1.2 Docker简介1.3 Docker解决操作系统环境差异1.4 Docker和虚拟机的区别1.5 Docker架构1.5.1 镜像和容器1.5.2 DockerHub1.5.3 Docker架构1.5.4 Docker工作流1.6 Docker的安装和启动1.7 安装步骤1.8 启动Docker1.9 配置镜像加速二…

总结802

早上&#xff1a; 6:23起床 6:43出门 7:00~7:40小湖读书 8:00~9:45机器人控制 9:50~11:30句句真研 11:31~12:10吃饭 12:12~12:22动漫 12:45~2:09午觉 2:00~4:15深度学习 4:26~4:39去图书馆 4:40~6:11高等数学第五讲 6:13~6:40跑步开合跳100胯下击掌100 6:50~7:20吃…

PS基础操作-抠图与导出-学习记录

目录 注&#xff1a;PS版本为2022&#xff0c;有个智能对象选择功能比较方便抠图 第一步&#xff1a;导入图像文件 第二步&#xff1a;基础的画布界面移动 鼠标滚轮上下滑动&#xff0c;可以是上下滚动界面 按住ctrl鼠标滚轮&#xff0c;可以左右滚动界面 按住alt鼠标滚轮…

华为OD机试题,用 Java 解【快递货车】问题 | 含解题说明

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典本篇题目:快递货车 题目 一辆运送快递的…

【python刷题】LeetCode 2057E 值相等的最小索引(5种简单高效的解法)

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于海外某世界知名高校就读计算机相关专业。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。…

问答ChatGPT-4:探索未来微数据中心IDC的发展趋势

从去年年底开始到现在&#xff0c;大众对以ChatGPT-4为主的人工智能AI的话题讨论盛况空前。这是一款由OpenAI发布的聊天机器人模型&#xff0c;一经上线&#xff0c;短短5天完成100万用户积累&#xff0c;并在最近实现月活用户破亿。实际上&#xff0c;ChatGPT和智能客服、智能…

CN RedGolf 集团利用 KEYPLUG 后门攻击 Windows 和 Linux 系统

被追踪为 RedGolf 的 CN 国家支持的威胁活动组织被归因于使用名为 KEYPLUG 的自定义 Windows 和 Linux 后门。 Recorded Future 告诉 The Hacker News&#xff1a;“RedGolf 是一个特别多产的CN国家支持的威胁组织&#xff0c;可能多年来一直活跃于全球范围内的广泛行业。” …

HandlerInterceptor拦截器的原理

是什么 HandlerInterceptor拦截的是请求&#xff0c;是springMVC项目中的拦截器&#xff0c;它拦截的目标是请求的地址。也就是说&#xff0c;它可以对请求进行拦截处理&#xff0c;所有实现了HandlerInterceptor&#xff0c;并且进行了配置的的类&#xff0c;都有这个能力&am…

第四章 共享模型之 管程 (下)

JUC并发编程系列文章 http://t.csdn.cn/UgzQi 文章目录JUC并发编程系列文章前言七、wait -- notify1、为什么使用 wait2、 wait -- notify 原理3、API 介绍八、wait -- notify 的正确姿势示例一&#xff1a;sleep会拿着锁睡觉&#xff0c;阻碍其它线程执行示例二&#xff1a;wa…

Eyeshot 2023 重大变化--2023版本将被Crack

Eyeshot 2023是一个基于 Microsoft .NET Framework 的 CAD 控件。它允许开发人员快速将 CAD 功能添加到 WinForms 和 WPF 应用程序。Eyeshot 提供了从头开始构建几何体、使用有限元方法对其进行分析并在其上生成刀具路径的工具。还可以使用 CAD 交换文件格式导入或导出几何图形…

操作系统页表

虚拟内存 虚拟地址到物理地址的映射以实现隔离性 每个程序有独立的地址空间&#xff0c;不相互影响 页表 地址操作简单流程 CPU向虚拟地址va加载或写入数据–>CPU将va交给内存管理单元MMU–>SATP寄存器存放着内存中存放虚拟地址到物理地址的表单–>MMU通过SATP查找…

03_C++函数

函数的分文件编写1.1头文件-函数声明//swap.h文件 #include<iostream> using namespace std;void swap(int a, int b);1.2源文件-函数定义在源文件中&#xff0c;要加上头文件引用#include "swap.h"//swap.cpp文件 #include "swap.h"void swap(int a…

最少砝码(思维+找规律)

最少砝码 前n个可以表示0~k; 第n1个为x&#xff08;x>k&#xff09;; 最大可测maxnkx; 第n1个和前n个放两边 可测得x-k&#xff1b; 让x-kk1&#xff0c;得到x2k1&#xff1b; maxn3k1&#xff1b; k1 可以用(2k1) - (k-0) 表示 k2 可以用(2k1) - (k-1) 表示 … 2k1 可以用…

Compose 动画 (八) : Compose中的动画差值器 AnimationSpec

1. AnimationSpec是什么 Android Compose中的AnimationSpec用来自定义动画规格。 啥意思呢&#xff0c;其实就是类似于传统View体系中的差值器Interpolator&#xff0c;但是比起差值器&#xff0c;又提供了更多的功能。 根据其不同的子类&#xff0c;可以来控制动画执行时长、…

运维1.12了解集中式日志管理工具 ELK 的基本用法,包括数据采集、搜索和展示

ELK 是一个由三个开源项目组成的日志管理工具&#xff0c;它们分别是 Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一个基于 Lucene 的搜索引擎&#xff0c;它可以提供实时的分布式搜索和分析能力&#xff1b;Logstash 是一个日志收集和处理工具&#xff0c;可以实现多…

《白帽子讲Web安全》世界观安全

1.Web安全简史1.1中国黑客简史对于现代计算机系统来说&#xff0c;在用户态的最高权限是root&#xff0c;也是黑客们最渴望能够获取的系统最高权限。不想拿到“root”的黑客&#xff0c;不是好黑客。在现实世界中&#xff0c;真正造成破坏的&#xff0c;往往并非那些挖掘并研究…

10秒去除WPS Office弹窗广告教程(2023.3.31最新)

目录 前言 步骤 1. 右击WPS Office&#xff0c;打开文件所在目录 2. 打开第二个文件夹 3. 进入office 6文件夹 4. 找到文件ksomisc.exe 5. 右击选择以管理员身份运行 6. 打开后是下面的界面&#xff0c;点击“高级(A)...” 7. 按照下图操作 8. 最后点击退出就设置完…

Mybatis配置之属性优化理解【transactionManager、dataSource、properties】

文章目录一.Mybatis配置之属性优化1.1 配置解析1.2 默认配置环境1.2.1 事务管理器&#xff08;transactionManager&#xff09;了解即可。1.2.2 数据源&#xff08;dataSource&#xff09;1.3 属性&#xff08;properties&#xff09;一.Mybatis配置之属性优化 1.1 配置解析 …

PyTorch 深度学习实战 |用 TensorFlow 训练神经网络

为了更好地理解神经网络如何解决现实世界中的问题&#xff0c;同时也为了熟悉 TensorFlow 的 API&#xff0c;本篇我们将会做一个有关如何训练神经网络的练习&#xff0c;并以此为例&#xff0c;训练一个类似的神经网络。我们即将看到的神经网络&#xff0c;是一个预训练好的用…