【USB-HID】“自动化键盘“ - 模拟键盘输入

目录

  • 【USB-HID】"自动化键盘" - 模拟键盘输入
    • 1. 前言
    • 2. 模拟键盘
      • 2.1 STM32CubeMX 配置
      • 2.2 修改代码配置
      • 2.3 发送按键信息
    • 3. 接收主机Setup数据
      • 3.1 获取PC下发的数据
    • 4. 总结

【USB-HID】“自动化键盘” - 模拟键盘输入

1. 前言

对于模拟键盘的实现,网上有很多的教程说明,我参考了网上的例程,很轻松的实现了模拟键盘的功能,实现了按键的输入,这篇文章我的主要目的是记录我的实现过程。

2. 模拟键盘

硬件:STM32F04 开发板
软件:STM32CubeMX + Keil5

2.1 STM32CubeMX 配置

只需要按照如图配置选择即可。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2 修改代码配置

  1. 修改协议类型:nInterfaceProtocol改为keyboard
  2. 修改报告描述长度:HID_MOUSE_REPORT_DESC_SIZE 改为 63
  3. 修改报告描述符:如下代码块所示

USB协议中这些配置信息是重点,后面需要深入去了解。

在这里插入图片描述 在这里插入图片描述

__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
    0x95, 0x05,                    //   REPORT_COUNT (5)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x05, 0x08,                    //   USAGE_PAGE (LEDs)
    0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
    0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
    0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x03,                    //   REPORT_SIZE (3)
    0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
    0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
    0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0                           // END_COLLECTION
};

2.3 发送按键信息

首先实现一个发送按键数据的函数,按键数据一共8个字节,每个字节的描述如下所示,字节0每个Bit代表特殊按键,字节2-7每个字节代表一个普通按键,按键的键值码去网上搜一下就有,或者去找USB-HID协议文档看一下。然后再实现一个按键松开的函数,这里所有数据发送0表示所有按键都松开,初步先这样实现,后续再改。接着在main函数中调用,实现按键按下时发送组合键【Ctrl + A】。从Bus Hound监控的数据我们可以看到,数据【01 00 04 00 00 00 00 00】即为我们下位机发送的按键数据。

void MX_USB_KEYBOARD_PRESS(uint8_t *sendBuffer)
{
	/*
	 * buffer[0] - bit0: Left CTRL
	 *           -bit1: Left SHIFT
	 *           -bit2: Left ALT
	 *           -bit3: Left GUI(win)
	 *           -bit4: Right CTRL
	 *           -bit5: Right SHIFT
	 *           -bit6: Right ALT
	 *           -bit7: Right GUI ()
	 * buffer[1] - Padding = Always 0x00
	 * buffer[2] - Key 1
	 * buffer[3] - Key 2
	 * buffer[4] - Key 3
	 * buffer[5] - Key 4
	 * buffer[6] - Key 5
	 * buffer[7] - Key 6
	 */
	USBD_HID_SendReport(&hUsbDeviceFS, sendBuffer, 8);
	HAL_Delay(20);
}

void MX_USB_KEYBOARD_RELEASE(void)
{
	uint8_t buffere_clear[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	USBD_HID_SendReport(&hUsbDeviceFS, buffere_clear, sizeof(buffere_clear));
	HAL_Delay(20);
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();

  while (1)
  {
	  if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2))
	  {
		  void MX_USB_KEYBOARD_PRESS(uint8_t *sendBuffer);
		  void MX_USB_KEYBOARD_RELEASE(void);
		  uint8_t buffere[8] = {0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
		  MX_USB_KEYBOARD_PRESS(buffere);
		  MX_USB_KEYBOARD_RELEASE();
	  }
  }
}

在这里插入图片描述

3. 接收主机Setup数据

在学习别人的教程的过程中,我了解到按下【caps lock】 / 【num clk】这些按键的时候,PC会下发请求控制点灯。也就是说我们下位机发送【caps lock】按键指令就能控制笔记本上的【caps lock】按键灯,下位机发送【caps lock】指令给PC后,PC会给键盘下发一个Setup请求,并且跟随一个字节的数据,这个数据是发给断点0。,该字节数据中的每个位代表这些按键的信息,如下表所示。
在这里插入图片描述
我们将程序按键改为操作【caps lock】按键,程序运行后,按下按键,我们可以看到电脑上的指示灯会跟着变化。

	  if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2))
	  {
		  void MX_USB_KEYBOARD_PRESS(uint8_t *sendBuffer);
		  uint8_t buffere[8] = {0x00, 0x00, KEYBOARD_CAPS_LOCK, 0x00, 0x00, 0x00, 0x00, 0x00};
		  MX_USB_KEYBOARD_PRESS(buffere);
	  }
	  else
	  {
		  void MX_USB_KEYBOARD_RELEASE(void);
		  MX_USB_KEYBOARD_RELEASE();
	  }

我们按下笔记本上的【caps lock】按键,可以观察到下发的数据中对应的Bit位实现翻转。
在这里插入图片描述
通过仿真我们可以看到下位机接收的数据与上位机下发的是一致的。
在这里插入图片描述
在这里插入图片描述

3.1 获取PC下发的数据

这里如何获取PC下发的Setup数据,我找了很多帖子,基本都是介绍只发不收,最终我还是找到了如何获取数据的方法,这里记录一下。因为PC下发的是一个Class类型的Steup请求,所以我们要在USBD_HID_Setup回调函数中实现HID_REQ_SET_REPORT的处理,通过USBD_CtlPrepareRx获取数据,然后再回调给应用层,这里MX_USB_HID_Set_Reporter_CallBack函数再应用层中实现即可。(没做过USB协议,我不确定是不是这样实现的,或者这个库本身就支持?)
在这里插入图片描述

4. 总结

不懂USB协议的前提下,照着网上依样画葫芦还是不容易的,看似别人的例程简单,但是都五花八门,甚至很多都是错的,比如键盘的报告描述符配置成63个,但是实际数组中的个数都超过63个了,编译都不过。有些还说接收PC端发送【caps lock】按键的数据还要配置输出端口,结果我赔了USB通讯都报Error了,真的很无语。建议这些配置一开始就去参考USB-HID协议文档,文档中都有给出。实在懒得看去问问AI至少靠谱一点。实现之后还要去深入了解这些配置的含义。

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

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

相关文章

图-遍历(DFS+BFS)

图-遍历 1.简介2.深度优先遍历dfs3.广度优先遍历bfs4.具体问题4.1 岛屿的最大面积4.2 岛屿的数量 5.总结 1.简介 图是数据结构中的另一种数据结构,通常用来表示多对多的关系。在 C 中,图通常可以通过邻接表或邻接矩阵表示。 例如: 2.深度优…

python中向量指的是什么意思

一、向量是什么 在数学中,向量(也称为欧几里得向量、几何向量、矢量),指具有大小(magnitude)和方向的量。它可以形象化地表示为带箭头的线段。箭头所指:代表向量的方向;线段长度&am…

Vulhub:Log4j[漏洞复现]

CVE-2017-5645(Log4j反序列化) 启动靶场环境 docker-compose up -d 靶机IPV4地址 ifconfig | grep eth0 -A 5 ┌──(root㉿kali)-[/home/kali/Desktop/temp] └─# ifconfig | grep eth0 -A 5 eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 in…

[OpenGL] Transform feedback 介绍以及使用示例

一、简介 本文介绍了 OpenGL 中 Transform Feedback 方法的基本概念和代码示例。 二、Transform Feedback 介绍 1. Transform Feedback 简介 根据 OpenGL-wiki&#xff0c;Transform Feedback 是捕获由顶点处理步骤&#xff08;vertex shader 和 geometry shader&#xff0…

探秘 AI Agent 之 Coze 智能体:从简介到搭建全攻略(4/30)

一、Coze 智能体概述 &#xff08;一&#xff09;Coze 智能体是什么 Coze 智能体是基于机器学习和自然语言处理技术的软件实体&#xff0c;它在人工智能领域扮演着重要的角色&#xff0c;能够像一个智能助手一样&#xff0c;通过与外界环境进行交互学习&#xff0c;进而执行各…

游戏引擎学习第47天

仓库: https://gitee.com/mrxiao_com/2d_game 昨天我们花了一点时间来修复一个问题&#xff0c;但基本上是在修复这个问题的过程中&#xff0c;我们决定添加一个功能&#xff0c;那就是在屏幕上控制多个实体。所以如果我有一个手柄&#xff0c;我可以添加另一个角色&#xff0…

CAPL如何设置或修改CANoe TCP/IP协议栈的底层配置

在CANoe中创建网络节点作为以太网主机时,可以给其配置独立的TCP/IP Stack。 配置的协议栈有一些底层配置参数可以在界面上设置或修改,比如: MTU上图中MTU显示500只是图形界面显示错误,正确值是1500。 TCP延迟确认这些参数也可以通过CAPL动态配置,甚至CAPL还可以配置很多界…

RabbitMQ实现消息发送接收——实战篇(路由模式)

本篇博文将带领大家一起学习rabbitMQ如何进行消息发送接收&#xff0c;我也是在写项目的时候边学边写&#xff0c;有不足的地方希望在评论区留下你的建议&#xff0c;我们一起讨论学习呀~ 需求背景 先说一下我的项目需求背景&#xff0c;社区之间可以进行物资借用&#xff0c…

计算机进制的介绍

一.进制介绍 对于整数&#xff0c;有四种表示方式: 1&#xff09;二进制:0,1&#xff0c;满2进1。 在golang中&#xff0c;不能直接使用二进制来表示一个整数&#xff0c;它沿用了c的特点。 参考:Go语言标准库文档中文版 | Go语言中文网 | Golang中文社区 | Golang中国 //赋值…

基于卷积神经网络的Caser算法

将一段交互序列嵌入到一个以时间为纵轴的平面空间中形成“一张图”后&#xff0c;基于卷积序列嵌入的推荐&#xff08;Caser&#xff09;算法利用多个不同大小的卷积滤波器&#xff0c;来捕捉序列中物品间的点级&#xff08;point-level&#xff09;、联合的&#xff08;union-…

基于STM32设计的粮食仓库(粮仓)环境监测系统

一、前言 当前项目使用的相关软件工具、传感器源代码工程已经上传到网盘&#xff08;实时更新项目内容&#xff09;&#xff1a;https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?fromfrom_copylink 1.1 项目开发背景 随着现代农业的发展和粮食储存规模的…

计算机网络-传输层 TCP协议(上)

目录 报头结构 TCP的可靠传输机制 核心机制一&#xff1a;确认应答 TCP的序号和确认序号 核心机制二&#xff1a;丢包重传 核心机制三&#xff1a;连接管理 建立连接-三次握手 断开连接-四次挥手 核心机制四&#xff1a;滑动窗口 数据包已经抵达, ACK被丢了 数据包就…

【经验分享】容器云运维的知识点

最近忙于备考没关注&#xff0c;有次点进某小黄鱼发现首页出现了我的笔记还被人收费了 虽然我也卖了一些资源&#xff0c;但我以交流、交换为主&#xff0c;笔记都是免费给别人看的 由于当时刚刚接触写的并不成熟&#xff0c;为了避免更多人花没必要的钱&#xff0c;所以决定公…

纯血鸿蒙崛起,原生Android挑战?两大操作系统巅峰对决,智能设备未来谁主沉浮?

鸿蒙HarmonyOS和原生Android系统虽然在一些方面相似&#xff0c;但在架构、设计理念、API、开发工具等方面存在一些差异。鸿蒙系统的目标是跨设备、分布式的操作系统&#xff0c;强调多设备协同和资源共享&#xff0c;而Android则主要集中在智能手机和移动设备领域。 下面将从…

新手快速入门!低功耗4G模组Air780E——使用文件系统存储温湿度数据来啦~

小伙伴们&#xff0c;今天我们来学习低功耗4G模组Air780E快速入门之使用文件系统存储温湿度数据。一起接着看下去吧&#xff01; 一、编写脚本 1.1 准备资料 780E开发板 780E开发板设计资料 LuatOS-Air780E-文件系统的使用-程序源码demo TCP/UDP测试服务器 API使用介绍 …

vscode中插件ofExtensions的debug模式也无法查看U、p等openfoam中foam类型的变量

插件介绍&#xff1a; 主要内容如下&#xff1a; 以自编译的$HOME/OpenFOAM-7例&#xff0c;如果OFdebugopt设置为WM_COMPILE_OPTIONDebug&#xff0c;那最终的激活环境的命令为source $HOME/OpenFOAM/OpenFOAM-8/etc/bashrc WM_COMPILE_OPTIONDebug&#xff0c;这时候$FOAM_…

【收藏】Cesium 限制相机倾斜角(pitch)滑动范围

1.效果 2.思路 在项目开发的时候&#xff0c;有一个需求是限制相机倾斜角&#xff0c;也就是鼠标中键调整视图俯角时&#xff0c;不能过大&#xff0c;一般 pitch 角度范围在 0 至 -90之间&#xff0c;-90刚好为正俯视。 在网上查阅了很多资料&#xff0c;发现并没有一个合适的…

【经验分享】私有云运维的知识点

最近忙于备考没关注&#xff0c;有次点进某小黄鱼发现首页出现了我的笔记还被人收费了 虽然我也卖了一些资源&#xff0c;但我以交流、交换为主&#xff0c;笔记都是免费给别人看的 由于当时刚刚接触写的并不成熟&#xff0c;为了避免更多人花没必要的钱&#xff0c;所以决定公…

Please activate LaTeX Workshop sidebar item to render the thumbnail of a PDF

Latex代码中使用pdf图片&#xff0c;无法预览&#xff0c;提示&#xff1a; Please activate LaTeX Workshop sidebar item to render the thumbnail of a PDF 解决办法&#xff1a; 点击左边这个刷新下即可

QT:Widgets中的事件

事件的处理 (1)重新实现部件的paintEvent()、mousePressEvent()等事件处理函数。这是最常用的一种方法&#xff0c;不过它只能用来处理特定部件的特定事件。 (2)重新实现notify()函数。这个函数功能强大&#xff0c;提供了完全的控制&#xff0c;可以在事件过滤器得到事件之前…