基于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

相关文章

mysql的基础语句和外键查询及其语句详解(推荐)

《mysql的基础语句和外键查询及其语句详解(推荐)》:本文主要介绍mysql的基础语句和外键查询及其语句详解(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录一、mysql 基础语句1. 数据库操作 创建数据库2. 表操作 创建表3. CRUD 操作二、外键

Python基础语法中defaultdict的使用小结

《Python基础语法中defaultdict的使用小结》Python的defaultdict是collections模块中提供的一种特殊的字典类型,它与普通的字典(dict)有着相似的功能,本文主要... 目录示例1示例2python的defaultdict是collections模块中提供的一种特殊的字

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

【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 ...]