IOKit:未收到来自与蓝牙连接的 DualShock 4 控制器的 HID 中断报告
Posted
技术标签:
【中文标题】IOKit:未收到来自与蓝牙连接的 DualShock 4 控制器的 HID 中断报告【英文标题】:IOKit: Not receiving HID interrupt reports from DualShock 4 controller connected with Bluetooth 【发布时间】:2015-06-12 00:56:51 【问题描述】:简介
我正在努力使用IOKit
中的 HID 接口获得对PlayStation 4 Controller
的全面支持。控制器通过Bluetooth
连接。我可以打开与控制器的连接并开始接收报告,但是,一旦我向它发送报告,它就会突然停止。
为了完全控制 PS4 控制器(震动、触控板、LED),我一直在引用 the eleccelerator.com DualShock 4 page,其中包含有关可以/在 PS4 和 DS4 之间发送的报告的信息。
代码
首先,我创建一个IOHIDManager
,它负责检测控制器。
self.hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
// Make sure we detect ANY type of 'game controller'
NSArray *criteria = [NSArray arrayWithObjects:
CreateCriterion(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick),
CreateCriterion(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad),
CreateCriterion(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController),
nil];
IOHIDManagerSetDeviceMatchingMultiple(self.hidManager, (__bridge CFArrayRef)criteria);
IOHIDManagerScheduleWithRunLoop(self.hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerOpen(self.hidManager, kIOHIDOptionsTypeNone);
// Register callbacks
IOHIDManagerRegisterDeviceMatchingCallback(self.hidManager, ControllerConnected, (__bridge void *)self);
IOHIDManagerRegisterDeviceRemovalCallback(self.hidManager, ControllerDisconnected, (__bridge void *)self);
然后在接到ControllerConnected
的调用后,我创建了一个操纵杆类的实例,它初始化了IOHIDDeviceRef
。
- (void)registerDevice:(IOHIDDeviceRef)device
self.device = device;
// Initialize the buffer
self.receivedPacketMaxSize = 552; // When using Bluetooth
self.receivedReport = (uint8_t *)calloc(self.receivedPacketMaxSize, sizeof(uint8_t));
// Register the device report callback
IOHIDDeviceScheduleWithRunLoop(self.device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
IOHIDDeviceRegisterInputReportCallback(self.device, self.receivedReport, self.receivedPacketMaxSize, ControllerReport, (__bridge void *)self);
self.isValid = YES;
现在我确实接到了ControllerReport
的电话,但是我收到的报告属于0x01 类型,它们包含的内容有限(没有触控板或加速度计数据),但我想接收以下数据包输入0x11,其中包含来自控制器的所有数据。
为了切换控制器发送哪个数据包,网站声明This report is sent once the GET REPORT FEATURE 0x02 is received.
所以我发送该请求:
CFIndex len = self.receivedPacketMaxSize;
IOReturn featureMode2RequestError = IOHIDDeviceGetReport(self.device, kIOHIDReportTypeFeature, 0x02, self.receivedReport, &len);
if (featureMode2RequestError != kIOReturnSuccess)
NSLog(@"Could switch the controller to mode 2 :(");
此时,ControllerReport
停止被来自控制器的新报告调用。
我知道我能够向控制器发送数据,因为我能够发送改变 LED 颜色或设置震动速度的数据包。
问题
如何从 PS4 控制器获取更长的 0x11 报告?
我的尝试
我尝试过使用IOHIDDeviceGetReportWithCallback
和IOHIDDeviceGetReport
,但总是得到kIOReturnUnsupported
的回复。
我还在... it starts sending input reports in report 17. Since report 17 is undefined ...
形式的控制器的linux 驱动程序的源代码中找到了一些对这个问题的引用,但是我不知道如何告诉IOKit 处理报告17 (0x11)。
【问题讨论】:
我不能告诉你为什么你会看到那个特定的问题以及如何解决它,但如果我正在调试这个,我会检查IOKit HID family和IOKit userlib HID源代码和跟踪设备报告的路径。一旦你找到了它们被忽略的地方,解决它应该不会太难。 我现在有一个解决方案。由于这似乎是由框架中的错误引起的,因此我将在秋季 macOS 发布时再试一次。但是,如果问题仍然存在,我怀疑我是否有资源来查找和解决问题。 【参考方案1】:问题在于 IOHIDDeviceGetReport kIOHIDReportTypeOutput 通过中断端点发送输出报告; DS4 期望它通过控制端点。 AFAIK 在 OS X 上没有任何方法可以通过 ctrl 端点输出 GetReport(没有编写 kext 来覆盖它)。
【讨论】:
以上是关于IOKit:未收到来自与蓝牙连接的 DualShock 4 控制器的 HID 中断报告的主要内容,如果未能解决你的问题,请参考以下文章