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

相关文章

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

从基础到高阶详解Python多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据