Usb自定义HID设备(游戏控制器)总结工程是由cubemx创建的不会创建的可以参考文章最后链接。该链接教程为未定义输入输出设备,本教程为游戏控制器属于输入设备。在建立好USB工程之后,我们主要修改的东西就两个,一个是报告描述符可以在usbd_custom_hid_if.c文件中找到报告描述符位置。还有一个是设备描述符我们可以在usbd_customhid.c文件中找到。

首先我们修改报告描述符,报告描述符如下。

/** Usb HID report descriptor. */
__ALIGN_BEGIN static uint8_t CUSTOM_HID_ReportDesc_FS[USBD_CUSTOM_HID_REPORT_DESC_SIZE] __ALIGN_END =
{   0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
//    0x09, 0x04,                    // USAGE (Joystick)0x09, 0x05,                    // USAGE (Game Pad)0xa1, 0x01,                    // COLLECTION (Application)0xa1, 0x02,                    //   COLLECTION (Logical)0x09, 0x30,                    //     USAGE (X)0x09, 0x31,                    //     USAGE (Y)0x15, 0x00,                    //     LOGICAL_MINIMUM (0)0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)0x46, 0xff, 0x00,              //     PHYSICAL_MAXIMUM (255)0x75, 0x08,                    //     REPORT_SIZE (8)0x95, 0x02,                    //     REPORT_COUNT (2)0x81, 0x02,                    //     INPUT (Data,Var,Abs)28
    0x09, 0x39,                    //   USAGE (Hat switch)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x25, 0x03,                    //   LOGICAL_MAXIMUM (3)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0x0e, 0x01,              //   PHYSICAL_MAXIMUM (270)
0x65, 0x14,                    //   UNIT (Eng Rot:Angular Pos)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)    190x09, 0x36,                    //   USAGE (Slider)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)180x09, 0x36,                    //   USAGE (Slider)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)180x09, 0x36,                    //   USAGE (Slider)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)18

//

 0x09, 0x33,                    //   USAGE (x)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)46   18

//
0x09, 0x34, // USAGE (y)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f, // PHYSICAL_MAXIMUM (32767)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)46 18

0x09, 0x35,                    //   USAGE (z)
0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)
0x75, 0x08,                    //   REPORT_SIZE (8)
0x95, 0x01,                    //   REPORT_COUNT (1)
0x81, 0x02,                    //   INPUT (Data,Var,Abs)46   18

//

 0x05, 0x09,                    //     USAGE_PAGE (Button)
0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)0x29, 0x20,                    // USAGE_MAXIMUM (Button 64)
0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)

0x95, 0x20, // REPORT_COUNT (64)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)

 0xc0,                          //     END_COLLECTION
0xc0                           // END_COLLECTION

};

报告描述符,主要是形容USB的属性功能,他会告诉PC端我这个USB自定义HID设备是干什么的,我会向PC端报告多少个字节,每个字节又有什么含义。
报告描述符就是一个数组,我们定义报告描述符的大小一定要数清楚。数好之后我们goto到USBD_CUSTOM_HID_REPORT_DESC_SIZE,
#define USBD_CUSTOM_HID_REPORT_DESC_SIZE     173//173//报告描述符长度
可以看到173就是这个报告描述符的长度。这个报告描述符我是从官方那里下载的,然后进行修改,毕竟自己定义的报告描述符没有官方的标准很多细节还是要参考官方为准。这是一个游戏手柄的例程。接下来我们看这个报告描述符到底怎么描述自己的属性,0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
告诉PC我是桌面类的0x09, 0x04,                    // USAGE (Joystick)
告诉PC我是干什么的,Joystick是一个摇杆类,同样你也可以定义别的比如 0x09, 0x05,                    // USAGE (Game Pad),
他告诉PC我是一个手柄类。他也可以定义成鼠标或者键盘,具体根据自己需求。0xa1, 0x01,                    // COLLECTION (Application)0xa1, 0x02,                    //   COLLECTION (Logical)
他告诉PC端我的物理逻辑,我们属于输入设备,以外部物理逻辑判断我们的行为再向PC端输入。0x09, 0x30,                    //     USAGE (X)
0x09, 0x31,                    //     USAGE (Y)
上面说过,这是一个游戏手柄的报告描述符,所以拥有X轴和Y轴0x15, 0x00,                    //     LOGICAL_MINIMUM (0)0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)0x46, 0xff, 0x00,              //     PHYSICAL_MAXIMUM (255)
这是形容XY轴所占的字节大小0-255,没错就是一个字节。0x75, 0x08,                    //     REPORT_SIZE (8)
一次性报告的大小,这里面的大小是按照BIT来算的,一个字节就是8个bit位,在这里我们要知道,usb向PC端报告最小是一个字节,不能比一个字节小,后面会说到按键,按键是按照一个按键占用一个BIT位,当你的按键数量不够八个的时候,也就是小于一个字节,此时我们要补足,必须要补足一个字节。0x95, 0x02,                    //     REPORT_COUNT (2)
这是报告次数的一次,X轴报告一次,Y轴报告一次共两次。一次一个字节,共两个字节。0x81, 0x02,                    //     INPUT (Data,Var,Abs)
是输入还是输出,这里的输入输出是PC端为主。0x09, 0x39,                    //   USAGE (Hat switch)
告诉PC端我们要加一个Hat switch是一个可视头盔有多个方向,0x15, 0x00,                    //   LOGICAL_MINIMUM (0)0x25, 0x03,                    //   LOGICAL_MAXIMUM (3)
告诉PC我们的最小逻辑是0,最大逻辑是3,也就是从0-3,共四个方向如果我们要定义八个方向只要将最大逻辑定义成7,0-7共八个方向。0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)0x46, 0x0e, 0x01,              //   PHYSICAL_MAXIMUM (270)
告诉PC我们的最大逻辑最小逻辑,四个方向,第一个方向是0度,第二个人方向是90,第三个是180,第四个是270,将360平均分成四份。0x65, 0x14,                    //   UNIT (Eng Rot:Angular Pos)0x75, 0x08,                    //   REPORT_SIZE (8)0x95, 0x01,                    //   REPORT_COUNT (1)0x81, 0x02,                    //   INPUT (Data,Var,Abs)
报告大小,和报告次数,以及是输入输出,可以看出这个头盔是占一个字节的。0x09, 0x36,                    //   USAGE (Slider)
告诉PC我要添加一个滑块,滑块就是一个ADC采集输入,游戏设备上的油门之类的。0x15, 0x00,                    //   LOGICAL_MINIMUM (0)0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)0x35, 0x00,                    //   PHYSICAL_MINIMUM (0)0x46, 0xff, 0x7f,              //   PHYSICAL_MAXIMUM (32767)0x75, 0x08,                    //   REPORT_SIZE (8)0x95, 0x01,                    //   REPORT_COUNT (1)0x81, 0x02,                    //   INPUT (Data,Var,Abs)18
告诉PC我的报告字节大小,输入还是输出,该滑块占用一个字节。
接下来我添加了共6个滑块,PC端最多只能添加6个滑块,添加滑块的时候要注意,这些东西都是PC上定死的,我们添加的时候要注意PC上的规定,比如滑块属性最多只能添加3个,位置在1,5,6,当你再添加的时候就不会再添加了,所以我加了x(在位置2),y(在位置3),z(在位置4)另外三个滑块凑足6个滑块。这些位置是PC定死的。0x05, 0x09,                    //     USAGE_PAGE (Button)
告诉PC我要添加按键属性0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)0x29, 0x20,                    // USAGE_MAXIMUM (Button 32)
按键最小是1最大是32,这里PC最多只能添加32个按键0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
按键逻辑最小为0,最大为1,按键就0和1的逻辑,按下和抬起。0x95, 0x20,                    // REPORT_COUNT (32)
0x75, 0x01,                    //     REPORT_SIZE (1)
按键报告是1个bit,共报告32次,所以占用4个字节0xc0,                          //     END_COLLECTION
0xc0                           // END_COLLECTION
结束,前面用到几个COLLECTION结尾就用到几个结束。
上述报告描述符共用到13个字节,X轴一个字节、Y轴一个字节、可视头盔一个字节、滑块6个共六个字节、按键32个共4个字节,加起来是13个字节。报告描述符修改完了。
接下来修改设备描述符```c
_ALIGN_BEGIN static uint8_t USBD_CUSTOM_HID_CfgFSDesc[USB_CUSTOM_HID_CONFIG_DESC_SIZ] __ALIGN_END =
{0x09, /* bLength: Configuration Descriptor size */USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */USB_CUSTOM_HID_CONFIG_DESC_SIZ,/* wTotalLength: Bytes returned */0x00,0x01,         /*bNumInterfaces: 1 interface*/0x01,         /*bConfigurationValue: Configuration value*/0x00,         /*iConfiguration: Index of string descriptor describingthe configuration*/0xC0,         /*bmAttributes: bus powered */0x32,         /*MaxPower 100 mA: this current is used for detecting Vbus*//************** Descriptor of CUSTOM HID interface ****************//* 09 */0x09,         /*bLength: Interface Descriptor size*/USB_DESC_TYPE_INTERFACE,/*bDescriptorType: Interface descriptor type*/0x00,         /*bInterfaceNumber: Number of Interface*/0x00,         /*bAlternateSetting: Alternate setting*/0x02,         /*bNumEndpoints*/0x03,         /*bInterfaceClass: CUSTOM_HID*/0x00,         /*bInterfaceSubClass : 1=BOOT, 0=no boot*/0x00,         /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*/0,            /*iInterface: Index of string descriptor*//******************** Descriptor of CUSTOM_HID *************************//* 18 */0x09,         /*bLength: CUSTOM_HID Descriptor size*/CUSTOM_HID_DESCRIPTOR_TYPE, /*bDescriptorType: CUSTOM_HID*/0x11,         /*bCUSTOM_HIDUSTOM_HID: CUSTOM_HID Class Spec release number*/0x01,0x00,         /*bCountryCode: Hardware target country*/0x01,         /*bNumDescriptors: Number of CUSTOM_HID class descriptors to follow*/0x22,         /*bDescriptorType*/USBD_CUSTOM_HID_REPORT_DESC_SIZE,/*wItemLength: Total length of Report descriptor*/0x00,/******************** Descriptor of Custom HID endpoints ********************//* 27 */0x07,          /*bLength: Endpoint Descriptor size*/USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/CUSTOM_HID_EPIN_ADDR,     /*bEndpointAddress: Endpoint Address (IN)*/0x03,          /*bmAttributes: Interrupt endpoint*/CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */0x00,CUSTOM_HID_FS_BINTERVAL,          /*bInterval: Polling Interval *//* 34 */0x07,          /* bLength: Endpoint Descriptor size */USB_DESC_TYPE_ENDPOINT, /* bDescriptorType: */CUSTOM_HID_EPOUT_ADDR,  /*bEndpointAddress: Endpoint Address (OUT)*/0x03, /* bmAttributes: Interrupt endpoint */CUSTOM_HID_EPOUT_SIZE,  /* wMaxPacketSize: 2 Bytes max  */0x00,CUSTOM_HID_FS_BINTERVAL,  /* bInterval: Polling Interval *//* 41 */
};

设备描述符,告诉PC端我有几个端点,其中输入端点要向你报告的字节多少个,输出端点要接收你的字节多少个(我们属于输入设备,这个不需要考虑)。我们只需要了解这三点,修改着三点就行了。
找到 0x02, /bNumEndpoints/
这是告诉PC我们端点数目是2,因为是gamepad设备能用到只有输入端点,添加两个也没问题,后面如果你要改成两个端点设备就不用修改了

/* 27 */
0x07, /bLength: Endpoint Descriptor size/
USB_DESC_TYPE_ENDPOINT, /bDescriptorType:/

CUSTOM_HID_EPIN_ADDR, /bEndpointAddress: Endpoint Address (IN)/
0x03, /bmAttributes: Interrupt endpoint/
CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */
0x00,
CUSTOM_HID_HS_BINTERVAL, /*bInterval: Polling Interval /
/
34 */
这一块是描述输入端点的我们可以看到 CUSTOM_HID_EPIN_ADDR, /bEndpointAddress: Endpoint Address (IN)/后面的IN就是输入的意思
CUSTOM_HID_EPIN_SIZE, /*wMaxPacketSize: 2 Byte max */这个是我们输入的大小,我们goto去修改他,上面说到我们共是13个字节,所以修改成 #define CUSTOM_HID_EPIN_SIZE 0x0dU

/* 34 */

0x07, /* bLength: Endpoint Descriptor size /
USB_DESC_TYPE_ENDPOINT, /
bDescriptorType: /
CUSTOM_HID_EPOUT_ADDR, /
bEndpointAddress: Endpoint Address (OUT)/
0x03, / bmAttributes: Interrupt endpoint /
CUSTOM_HID_EPOUT_SIZE, /
wMaxPacketSize: 2 Bytes max /
0x00,
CUSTOM_HID_HS_BINTERVAL, /
bInterval: Polling Interval /
/
41 */

这一块是描述输出端点的我们用不到,添加日后好修改,他的意思是跟输入差不多,我们只需修改接收字节大小就行了
CUSTOM_HID_EPOUT_SIZE, /* wMaxPacketSize: 2 Bytes max */

这两处修改完了你的USB自定义游戏手柄也就完成了。代码烧进板子后,我们在我的电脑,右击选择属性,找到控制面板

进入后可以看到一盒游戏手柄

右击他,选择游戏控制器
进入属性后,我们可以看到我们刚才定义的东西

32个按键、XY轴、六个滑块、一个视觉头盔,这基本满足了所有的游戏控制器,当我们不想交这个名字的时候我们可以修改usbd_desc.c文件中的
#define USBD_PRODUCT_STRING_FS “Game Control Panez”
可以看到我只改了最后一个字母。
我们同样可以修改厂商ID和设备ID也就是VID和PID也在这个文件下
#define USBD_VID 1155
#define USBD_PID_FS 22351
记住同一个设备不能拥有两个ID一样的设备,具体根据自己情况修改。
接下来我们看如何使用找到usbd_custom_hid_if.c这个文件,我们可以找到
int8_t USBD_CUSTOM_HID_SendReport_FS(uint8_t *report, uint16_t len)
{
return USBD_CUSTOM_HID_SendReport(&hUsbDeviceFS, report, len);
}
这个函数是usb发送函数,共两个参数,第一个参数是我们要报告的数组,记住我们当时定义的是13个字节,所以这个数组必须是13个字节的,否则无法识别,第二个参数是这个数组大小。
该例程只用于向PC端发数据,GAMEPAD设备无法接收PC端数据,如果要自定义可以接收和发送的HID设备可以参考该例程只用于向PC端发数据,GAMEPAD设备无法接收PC端数据,如果要自定义可以接收和发送的HID设备可以参考链接教程
最后向PC端发送数据的时候,我们定了13个字节大小的数据,数组的每个字节的意思,和我们定义的报告描述符顺序一样,如我们刚开始定义了X那么第0个字节就是X走的意思,然后我们定义了Y那个第1个字节就是Y的意思以此类推。这里要注意,视觉头盔是从0x00开始的,0x00表示上,0x01表示右,0x02表示下,0x03表示左。并非按照bit控制,按键是按照位控制的。

本人纯属自己搞着玩,有错误请大佬嘴下留情

链接:https://www.bilibili.com/video/BV1eE411o7Qf?p=3

stm32自定义usb_HID设备相关推荐

  1. stm32——自定义HID设备

    一.开发环境 硬件平台:stm32f767 软件平台:keil5,cubmx 二.cubemx创建工程 1.配置RCC 2.USB_OTG_FS,选择Device_Only模式 3.Middlewar ...

  2. STM32 自定义HID USB设备的实现

    最近需要使用STM32开发一个设备通过HID协议与主机通信,于是开始学习USB,发现USB这个体系实在太庞大了,直接看USB的例程根本看不懂,完全找不到突破口,最后在网上找到一本不错的书<圈圈教 ...

  3. STM32的USB例程JoyStickMouse改成自定义HID设备

    简介 USB HID类是USB设备的一个标准设备类,包括的设备非常多.HID类设备定义它属于人机交互操作的设备,用于控制计算机操作的一些方面,如USB鼠标.USB键盘.USB游戏操纵杆等.但HID设备 ...

  4. STM32自定义键盘(二)STM32单片机的USB接口-HID键盘

    STM32自定义键盘(二)STM32单片机的USB接口-HID键盘 HID描述符 生成HID键盘工程模板 修改HID报告描述符 键值数据发送 USB HID 键盘键值表 HID描述符 请参考这位博主的 ...

  5. STM32配置组合设备(HID+CDC)

    STM32组合设备 STM32配置组合设备(HID+CDC) 1. CDC基础工程,HID基础工程生成 2.USB工程熟悉 2.1 USB初始化 2.2USB中断 2.3 相关结构体 2.3.1 ` ...

  6. Jetson AGX Orin 连接自定义硬件设备(pinmux + 设备树)

    环境信息 Ubuntu 20.04.4 LTS 64-bit Linux kernel: tegra 5.10.65 JetPack 5.0.1-b118 目标 在Jetson AGX Orin上接入 ...

  7. playwright自定义浏览器设备、时区、经纬度、userAgent、注入脚本

    介绍 Playwright是一个强大的Python库,仅用一个API即可自动执行Chromium.Firefox.WebKit等主流浏览器自动化操作,并同时支持以无头模式.有头模式运行. 项目地址:h ...

  8. USB自定义HID设备实现-STM32

    该文档使用USB固件库,在其基础上进行了自己的定制,完成了一个USB-HID设备,首先是usb_desc.c文件,里面存放了usb各种描述符的存在 #include "usb_desc.h& ...

  9. STM32配置CH375B成HID Host模式读取自定义HID设备的数据 ——STM32配置CH375B接口函数

    接着上一篇上传,这个是STM32配置CH375B时用到的接口函数 头文件: #ifndef __BSP_CH375_H__ #define __BSP_CH375_H__#include " ...

最新文章

  1. silverlight 无法发布 如何灵活配置IP
  2. golang版try..catch..
  3. 自定义request_Spring Security 自定义登录认证(二)
  4. ajax修改按钮的html值,表格行的按钮AJAX后,怎么修改表格当前行的值
  5. [翻译]asp.net ajax xml-script教程(二)
  6. 财物机器人英文ppt演讲课件_“如何恰当使用课件动画”
  7. JavaScript--关于变量提升思考
  8. vs.php中使用apache或IIS7进行外部调试
  9. 利用Java Swing 实现游戏开发
  10. 执行nvidia-smi出错
  11. Apache Log4j2详解,【高级Java架构师系统学习
  12. 企业实战|Mysql不停机维护主从同步
  13. C语言极速学习开发——51单片机入门编程之使用KeilC51进行代码编译(点亮你心中学习的精神之灯-上)
  14. 2019-11-6-Roslyn-how-to-use-WriteLinesToFile-to-write-the-semicolons-to-file
  15. 便捷的收集数据工具—Sniffer嗅探器
  16. MYSQL学习心得6
  17. 个人博客html页面,51个漂亮的个人博客和自媒体网站
  18. ACK Acknowledgement 确认 AES Advanced Encryption Standard 高级加密标准 ATM Asynchronous Transfer Mode异步传输模式
  19. 模拟京东快递单号查询案例2020/11/24
  20. 程序员工资为什么普遍很高,原来是因为这个。。。

热门文章

  1. 农业动物相关数据集与算法——调研整理
  2. 信息收集之寻找真实ip
  3. win10找不到wifi网络_笔记本连不上WiFi怎么办?
  4. 群晖linux文件夹颜色红色,技术干货分享 | 群晖备份Linux文件夹~
  5. 虚拟机共享目录添加按钮灰色_共享按钮将成为PS4最重要的遗产
  6. 《一本书读懂财报》:系统的输入与输出的体现
  7. Windows 10 CMD简单使用
  8. 如何防御黑客的社工?
  9. Alkyne-PEG-OH 炔烃PEG羟基Alkyne-PEG-OH 炔烃PEG羟基
  10. allegro如何等长走线