项目场景:使用STM32模拟PS4手柄
基于STM32USB-HID:
在custom-hid模式下根据下面这个Wiki进行配置
https://www.psdevwiki.com/ps4/DS4-USB#cite_ref-3
配置完成后可以作为自定义控制器使用,但是使用DS4Windows的时候有以下bug
WARNING: Failed to read serial# from a gamepad (0x054C/0x05C4). Generating MAC address from a device path. From now on you should connect this gamepad always into the same USB port or BT pairing host to keep the same device path.
问题描述
提示:这里描述项目中遇到的问题:
首先查看DS4的日志:
看了挺多github上面的问题描述,不太符合我这边的问题,所以我感觉还是我这边代码没配好……
https://github.com/Ryochan7/DS4Windows/issues/2438
使用USB Hound工具抓包,于是出现了如题目所示的stall pid问题,c0000004
经过各种试验调试,基本可以得出结论:上一句的输入不符合要求时,立即触发stall pid错误
因此这里是输出的字符 “Wireless Controller” 的发送出现了问题
找到哪里发送的这个字符
查了以下GetString这个函数没有相关参数有问题(到这里我还是完全相信STM32给的库的)
找到哪里发送的:
/**
* @brief USBD_CUSTOM_HID_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
static uint8_t USBD_CUSTOM_HID_DataOut(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
USBD_CUSTOM_HID_HandleTypeDef *hhid = (USBD_CUSTOM_HID_HandleTypeDef *)pdev->pClassData;
((USBD_CUSTOM_HID_ItfTypeDef *)pdev->pUserData)->OutEvent(hhid->Report_buf[0],
hhid->Report_buf[1]);
USBD_LL_PrepareReceive(pdev, CUSTOM_HID_EPOUT_ADDR, hhid->Report_buf,
USBD_CUSTOMHID_OUTREPORT_BUF_SIZE); //BUF_SIZE?
return USBD_OK;
}
发现这个USBD_CUSTOMHID_OUTREPORT_BUF_SIZE好像是直接发送输出report的尺寸,原来是10
然而我一般发送的数组尺寸是64的,直接在这里找到一个问题,修正为 64
重新发送一遍
问题1解决了,GET_DESCRIPTOR后面跟了正常的数据,可是还是不行,往下看:
到300多个cmd之后居然发送了一个GET REPORT
请求的数据是 a1 01 12 03 00 00 40 00
好家伙,我在库里面根本没有发现跟这个函数,先查查资料
官方文档是这样写的:Get_Report请求
自定义hid设备set_report设置和get_report获取报告描述符控制8字节数据
http://zhangzhian.blog.163.com/blog/static/23589602010426103338869/
根据手册和上面文档的一一对应,可以得到他需要的 Report ID是0x12
正好,PS4的Wiki上面有这段说明
还是找了个好的PS4手柄读了一下数据
反馈的数据是:12 c0 45 12 f2 41 8c 08 25 00 23 64 e0 fa 43 98
得了,直接按照这个来发试试!
解决方案:
添加有关GET_REPORT的程序:
官方的库中有定义 CUSTOM_HID_REQ_GET_REPORT 这个变量,但是并没有写他应该返回什么
我们直接在 usbd_customhid.c 文件中
函数 static uint8_t USBD_CUSTOM_HID_Setup(USBD_HandleTypeDef *pdev,USBD_SetupReqTypedef *req)
加上
uint8_t id12[16] = {0x12,0xc0,0x45,0x12,
0xf2,0x41,0x8c,0x08,
0x25,0x00,0x23,0x64,
0xe0,0xfa,0x43,0x98};
的 case CUSTOM_HID_REQ_SET_REPORT
下面加上这段代码
/* Get Report : a0 bmRequest Type
01 GET_REPORT
12 Report ID
03 Feature Report
0000 Interface
0040 Report Length(64)
*/
// Report ID = 0x12: 12 c0 45 12 f2 41 8c 08 25 00 23 64 e0 fa 43 98
case CUSTOM_HID_REQ_GET_REPORT:
USBD_CtlSendData(pdev, id12, 16U);
break;
这样就补充解决了GET_REPORT没有反馈的问题
不过这个只是一个补丁,如果他需要得到其他ID的REPORT,那也不知道给什么比较好……
修复问题后,STM32的模拟PS4手柄终于可以被识别到了!