基于STM32处理器的USB HID模拟鼠标键盘(1) - USB HID基础

2024-04-20 22:38

本文主要是介绍基于STM32处理器的USB HID模拟鼠标键盘(1) - USB HID基础,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HID是Human Interface Device的缩写,HID设备是直接与人交互的设备,例如键盘、鼠标与游戏杆等。不过HID设备并不一定要有人机接口,只要符合HID类别规范的设备都是HID设备。交换的数据存储在称为报表或报告(report)的结构内,设备的固件必须支持HID报表的格式。主机在控制与中断传输中传送与要求报表,来传送与接收数据。报表的格式非常有弹性,可以处理任何类别的数据。设备除了HID接口之外,它可能同时还包含有其他的USB接口。例如影像显示设备可能使用HID接口来做亮度,对比,与更新率的软件控制,而使用传统的影 像接口来传送要显示的数据。USB扩音器可以使用实时传输来播放语音,同时使用HID接口来控制音量,震荡,与低音等。HID接口通常比传统的控制接口来得便宜。USB协议的介绍可以参考网上的教程:

USB设备枚举过程介绍http://lastnight1034.blog.163.com/blog/static/167118149201211710164820/

USB设备描述符http://blog.csdn.net/saloon_yuan/article/details/7837492


使用STM32的USB功能可以实现HID设备的功能,使用的是ST官方的USB库,在官方的例程上可以进行修改。修改设备描述符、配置描述符、接口描述符、HID描述符、端点描述符、字符串描述符,还有就是HID设备专有的报告描述符,以完成特定功能。

报告以及报告描述符简介参考:http://www.baiheee.com/Documents/081126/081126115257.htm

USB HID设备是通过报告来给传送数据的,报告有输入报告和输出报告。输入报告是USB设备发送给主机的,例如USB鼠标将鼠标移动和鼠标点击等信息返回给电脑,键盘将按键数据数据返回给电脑等;输出报告是主机发送给USB设备的,例如键盘上的数字键盘锁定灯和大写字母锁定灯等。报告是一个数据包,里面包含的是所要传送的数据。输入报告是通过中断输入端点输入的,而输出报告有点区别,当没有中断输出端点时,可以通过控制输出端点0发送,当有中断输出端点时,通过中断输出端点发出。 
而报告描述符,是描述一个报告以及报告里面的数据是用来干什么用的。通过它,USB HOST可以分析出报告里面的数据所表示的意思。它通过控制输入端点0返回,主机使用获取报告描述符命令来获取报告描述符,注意这个请求是发送到接口的,而不是到设备。一个报告描述符可以描述多个报告,不同的报告通过报告ID来识别,报告ID在报告最前面,即第一个字节(设备发送的第一个字节数据为报告ID用于
让主机识别报告的类型以及使用什么报告描述符来解析这个报告。当报告描述符中没有规定报告ID时,报告中就没有ID字段,开始就是数据。更详细的说明请参看USB HID协议。USB报告描述符可以通过使用HID Descriptor tool来生成,这个工具可以网上下载。 

具体的描述符如下所示:

/* USB Standard Device Descriptor */
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{0x12,                       /*bLength */USB_DEVICE_DESCRIPTOR_TYPE, /*bDescriptorType*/0x00,                       /*bcdUSB */0x02,0x00,                       /*bDeviceClass*/0x00,                       /*bDeviceSubClass*/0x00,                       /*bDeviceProtocol*/0x40,                       /*bMaxPacketSize40*/0x34,                       /*idVendor (0x1234)*/0x12,0x21,                       /*idProduct = 0x4321*/0x44,0x00,                       /*bcdDevice rel. 2.00*/0x02,1,                          /*Index of string descriptor describing manufacturer */2,                          /*Index of string descriptor describing product*/3,                          /*Index of string descriptor describing the device serial number */0x01                        /*bNumConfigurations*/
}; /* Joystick_DeviceDescriptor */const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{//ÒÔÏÂΪÅäÖÃÃèÊö·û0x09, /* bLength: Configuation Descriptor size */USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType: Configuration */JOYSTICK_SIZ_CONFIG_DESC,/* wTotalLength: Bytes returned */0x00,0x01,         /*bNumInterfaces: 1 interface*/0x01,         /*bConfigurationValue: Configuration value*/0x00,         /*iConfiguration: Index of string descriptor describing the configuration*/0xC0,         /*bmAttributes: self powered */0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*///ÒÔÏÂΪ½Ó¿ÚÃèÊö·û/************** Descriptor of Joystick Mouse interface ****************//* 09 */0x09,         /*bLength: Interface Descriptor size*/USB_INTERFACE_DESCRIPTOR_TYPE,/*bDescriptorType: Interface descriptor type*/0x00,         /*bInterfaceNumber: Number of Interface*/0x00,         /*bAlternateSetting: Alternate setting*/0x02,         /*bNumEndpoints*/0x03,         /*bInterfaceClass: HID*/0x01,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/0x01,         /*bInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/0,            /*iInterface: Index of string descriptor*///ÒÔÏÂΪHIDÃèÊö·û/******************** Descriptor of Joystick Mouse HID ********************//* 18 */0x09,         /*bLength: HID Descriptor size*/HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/0x00,         /*bcdHID: HID Class Spec release number*/0x01,0x00,         /*bCountryCode: Hardware target country*/0x01,         /*bNumDescriptors: Number of HID class descriptors to follow*/0x22,         /*bDescriptorType*/JOYSTICK_SIZ_REPORT_DESC,/*wItemLength: Total length of Report descriptor*/0x00,//ÒÔÏÂΪÊäÈë¶Ëµã1ÃèÊö·û/******************** Descriptor of Joystick Mouse endpoint ********************//* 27 */0x07,          /*bLength: Endpoint Descriptor size*/USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/0x81,          /*bEndpointAddress: Endpoint Address (IN)*/0x03,          /*bmAttributes: Interrupt endpoint*/0x0A,          /*wMaxPacketSize: 10 Byte max */0x00,0x20,          /*bInterval: Polling Interval (32 ms)*///ÒÔÏÂΪÊä³ö¶Ëµ«1ÃèÊö·û/* 34 */0x07,          /*bLength: Endpoint Descriptor size*/USB_ENDPOINT_DESCRIPTOR_TYPE, /*bDescriptorType:*/0x01,          /*bEndpointAddress: Endpoint Address (OUT)*/0x03,          /*bmAttributes: Interrupt endpoint*/0x0A,          /*wMaxPacketSize: 10 Byte max */0x00,0x20,          /*bInterval: Polling Interval (32 ms)*//* 41 */
}; /* MOUSE_ConfigDescriptor */const u8 Joystick_ReportDescriptor[JOYSTICK_SIZ_REPORT_DESC] =
{/************************USB¼üÅ̲¿·Ö±¨¸æÃèÊö·û**********************//*******************************************************************/0x05, 0x01, // USAGE_PAGE (Generic Desktop)0x09, 0x06, // USAGE (Keyboard)0xa1, 0x01, // COLLECTION (Application)0x85, 0x01, // Report ID (1)0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0x01, // LOGICAL_MAXIMUM (1)0x95, 0x08, // REPORT_COUNT (8)0x75, 0x01, // REPORT_SIZE (1)0x81, 0x02, // INPUT (Data,Var,Abs)0x95, 0x01, // REPORT_COUNT (1)0x75, 0x08, // REPORT_SIZE (8)0x81, 0x03, // INPUT (Cnst,Var,Abs)0x95, 0x06, // REPORT_COUNT (6)0x75, 0x08, // REPORT_SIZE (8)0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0xFF, // LOGICAL_MAXIMUM (255)0x05, 0x07, // USAGE_PAGE (Keyboard/Keypad)0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)0x81, 0x00, // INPUT (Data,Ary,Abs)0x25, 0x01, // LOGICAL_MAXIMUM (1) 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)//3¸öbitÀ´´Õ³ÉÒ»×Ö½Ú¡£										0x91, 0x03, // OUTPUT (Cnst,Var,Abs)0xc0,		// END_COLLECTION/************************USBÊó±ê²¿·Ö±¨¸æÃèÊö·û**********************//*******************************************************************/0x05, 0x01, // USAGE_PAGE (Generic Desktop)0x09, 0x02, // USAGE (Mouse)0xa1, 0x01, // COLLECTION (Application)0x85, 0x02, // Report ID (2)0x09, 0x01, // USAGE (Pointer)0xa1, 0x00, // COLLECTION (Physical)0x05, 0x09, // USAGE_PAGE (Button)0x19, 0x01, // USAGE_MINIMUM (Button 1)0x29, 0x03, // USAGE_MAXIMUM (Button 3)						  0x15, 0x00, // LOGICAL_MINIMUM (0)0x25, 0x01, // LOGICAL_MAXIMUM (1)0x95, 0x03, // REPORT_COUNT (3)0x75, 0x01, // REPORT_SIZE (1)0x81, 0x02, // INPUT (Data,Var,Abs)0x95, 0x01, // REPORT_COUNT (1)0x75, 0x05, // REPORT_SIZE (5)0x81, 0x03, // INPUT (Cnst,Var,Abs)0x05, 0x01, // USAGE_PAGE (Generic Desktop)0x09, 0x30, // USAGE (X)0x09, 0x31, // USAGE (Y)0x09, 0x38, // USAGE (Wheel)0x15, 0x81, // LOGICAL_MINIMUM (-127)0x25, 0x7f, // LOGICAL_MAXIMUM (127)0x75, 0x08, // REPORT_SIZE (8)0x95, 0x03, // REPORT_COUNT (3)0x81, 0x06, // INPUT (Data,Var,Rel)0xc0,       // END_COLLECTION0xc0        // END_COLLECTION
};/* USB String Descriptors (optional) */
const u8 Joystick_StringLangID[JOYSTICK_SIZ_STRING_LANGID] =
{JOYSTICK_SIZ_STRING_LANGID,USB_STRING_DESCRIPTOR_TYPE,0x09,0x04
}; /* LangID = 0x0409: U.S. English */const u8 Joystick_StringVendor[JOYSTICK_SIZ_STRING_VENDOR] =
{JOYSTICK_SIZ_STRING_VENDOR, /* Size of Vendor string */USB_STRING_DESCRIPTOR_TYPE,  /* bDescriptorType*//* Manufacturer: "STMicroelectronics" */'S', 0, 'T', 0, 'M', 0, 'i', 0, 'c', 0, 'r', 0, 'o', 0, 'e', 0,'l', 0, 'e', 0, 'c', 0, 't', 0, 'r', 0, 'o', 0, 'n', 0, 'i', 0,'c', 0, 's', 0
};const u8 Joystick_StringProduct[JOYSTICK_SIZ_STRING_PRODUCT] =
{JOYSTICK_SIZ_STRING_PRODUCT,          /* bLength */USB_STRING_DESCRIPTOR_TYPE,        /* bDescriptorType */'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, ' ', 0, 'J', 0,'o', 0, 'y', 0, 's', 0, 't', 0, 'i', 0, 'c', 0, 'k', 0
};u8 Joystick_StringSerial[JOYSTICK_SIZ_STRING_SERIAL] =
{JOYSTICK_SIZ_STRING_SERIAL,           /* bLength */USB_STRING_DESCRIPTOR_TYPE,        /* bDescriptorType */'S', 0, 'T', 0, 'M', 0, '3', 0, '2', 0, '1', 0, '0', 0
};


下面主要介绍一下上面的几个描述符。下图是各个描述符的类型值。

1、设备描述符DeviceDesciptor

2、配置描述符ConfigurationDescriptor

3、接口描述符InterfaceDescriptor

4、HID描述符HIDDescriptor

HID设备专有的描述符,用于配置HID设备的属性和报告描述符的大小。

5、端点描述符EndpointDescriptor

端点描述符是用于配置端点号以及端点的输入输出。

6、报告描述符ReportDescriptor

报告描述符在前文以及介绍地很详细了,他是HID设备专有的描述符,适用于描述传输的数据的格式,用来告诉主机以什么样的方式来解析从机传过来的数据。

7、字符串描述符StringDescriptor



这篇关于基于STM32处理器的USB HID模拟鼠标键盘(1) - USB HID基础的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/921509

相关文章

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

韦季李输入法_输入法和鼠标的深度融合

在数字化输入的新纪元,传统键盘输入方式正悄然进化。以往,面对实体键盘,我们常需目光游离于屏幕与键盘之间,以确认指尖下的精准位置。而屏幕键盘虽直观可见,却常因占据屏幕空间,迫使我们在操作与视野间做出妥协,频繁调整布局以兼顾输入与界面浏览。 幸而,韦季李输入法的横空出世,彻底颠覆了这一现状。它不仅对输入界面进行了革命性的重构,更巧妙地将鼠标这一传统外设融入其中,开创了一种前所未有的交互体验。 想象

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

hdu4431麻将模拟

给13张牌。问增加哪些牌可以胡牌。 胡牌有以下几种情况: 1、一个对子 + 4组 3个相同的牌或者顺子。 2、7个不同的对子。 3、13幺 贪心的思想: 对于某张牌>=3个,先减去3个相同,再组合顺子。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOExcepti

键盘快捷键:提高工作效率与电脑操作的利器

键盘快捷键:提高工作效率与电脑操作的利器 在数字化时代,键盘快捷键成为了提高工作效率和优化电脑操作的重要工具。无论是日常办公、图像编辑、编程开发,还是游戏娱乐,掌握键盘快捷键都能带来极大的便利。本文将详细介绍键盘快捷键的概念、重要性、以及在不同应用场景中的具体应用。 什么是键盘快捷键? 键盘快捷键,也称为热键或快捷键,是指通过按下键盘上的一组键来完成特定命令或操作的方式。这些快捷键通常涉及同

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点