macOS IOKit interface fixes; callback-change mutex for controllers

This commit is contained in:
Jack Andersen
2017-12-15 13:35:54 -10:00
parent cb99c05284
commit e0aa15610b
15 changed files with 87 additions and 52 deletions

View File

@@ -11,10 +11,6 @@ DeviceBase::DeviceBase(DeviceToken* token)
{
}
DeviceBase::~DeviceBase()
{
}
void DeviceBase::_deviceDisconnected()
{
deviceDisconnected();

View File

@@ -8,7 +8,7 @@ namespace boo
* Reference: https://github.com/ToadKing/wii-u-gc-adapter/blob/master/wii-u-gc-adapter.c
*/
DolphinSmashAdapter::DolphinSmashAdapter(DeviceToken* token) : DeviceBase(token) {}
DolphinSmashAdapter::DolphinSmashAdapter(DeviceToken* token) : TDeviceBase<IDolphinSmashAdapterCallback>(token) {}
DolphinSmashAdapter::~DolphinSmashAdapter() {}
@@ -61,6 +61,7 @@ void DolphinSmashAdapter::transferCycle()
// printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
std::lock_guard<std::mutex> lk(m_callbackLock);
if (!m_callback)
return;
@@ -74,6 +75,10 @@ void DolphinSmashAdapter::transferCycle()
EDolphinControllerType type = parseState(&state, controller, rumble);
if (type != EDolphinControllerType::None && !(m_knownControllers & 1 << i))
{
m_leftStickCal[0] = reinterpret_cast<uint8_t&>(state.m_leftStick[0]);
m_leftStickCal[1] = reinterpret_cast<uint8_t&>(state.m_leftStick[1]);
m_rightStickCal[0] = reinterpret_cast<uint8_t&>(state.m_rightStick[0]);
m_rightStickCal[1] = reinterpret_cast<uint8_t&>(state.m_rightStick[1]);
m_knownControllers |= 1 << i;
m_callback->controllerConnected(i, type);
}
@@ -83,7 +88,13 @@ void DolphinSmashAdapter::transferCycle()
m_callback->controllerDisconnected(i);
}
if (m_knownControllers & 1 << i)
{
state.m_leftStick[0] = int8_t(reinterpret_cast<uint8_t&>(state.m_leftStick[0]) - m_leftStickCal[0]);
state.m_leftStick[1] = int8_t(reinterpret_cast<uint8_t&>(state.m_leftStick[1]) - m_leftStickCal[1]);
state.m_rightStick[0] = int8_t(reinterpret_cast<uint8_t&>(state.m_rightStick[0]) - m_rightStickCal[0]);
state.m_rightStick[1] = int8_t(reinterpret_cast<uint8_t&>(state.m_rightStick[1]) - m_rightStickCal[1]);
m_callback->controllerUpdate(i, type, state);
}
rumbleMask |= rumble ? 1 << i : 0;
}
@@ -115,14 +126,14 @@ void DolphinSmashAdapter::finalCycle()
void DolphinSmashAdapter::deviceDisconnected()
{
if (!m_callback)
return;
for (uint32_t i = 0; i < 4; i++)
{
if (m_knownControllers & 1 << i)
{
m_knownControllers &= ~(1 << i);
m_callback->controllerDisconnected(i);
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected(i);
}
}
}

View File

@@ -29,8 +29,7 @@ static const uint8_t defaultReport[49] = {
};
DualshockPad::DualshockPad(DeviceToken* token)
: DeviceBase(token),
m_callback(nullptr),
: TDeviceBase<IDualshockPadCallback>(token),
m_rumbleRequest(EDualshockMotor::None),
m_rumbleState(EDualshockMotor::None)
{
@@ -44,6 +43,7 @@ DualshockPad::~DualshockPad()
void DualshockPad::deviceDisconnected()
{
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
@@ -95,8 +95,11 @@ void DualshockPad::receivedHIDReport(const uint8_t* data, size_t length, HIDRepo
state.accYaw = (atan2(accXval, accZval) + M_PI) * RAD_TO_DEG;
state.gyroZ = (state.m_gyrometerZ / 1023.f);
if (m_callback)
m_callback->controllerUpdate(*this, state);
{
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerUpdate(*this, state);
}
if (m_rumbleRequest != m_rumbleState)
{

View File

@@ -5,7 +5,7 @@ namespace boo
{
GenericPad::GenericPad(DeviceToken* token)
: DeviceBase(token)
: TDeviceBase<IGenericPadCallback>(token)
{
}
@@ -14,8 +14,9 @@ GenericPad::~GenericPad() {}
void GenericPad::deviceDisconnected()
{
if (m_cb)
m_cb->controllerDisconnected();
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
void GenericPad::initialCycle()
@@ -29,18 +30,20 @@ void GenericPad::initialCycle()
std::vector<uint8_t> reportDesc = getReportDescriptor();
m_parser.Parse(reportDesc.data(), reportDesc.size());
#endif
if (m_cb)
m_cb->controllerConnected();
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerConnected();
}
void GenericPad::receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message)
{
if (length == 0 || tp != HIDReportType::Input || !m_cb)
std::lock_guard<std::mutex> lk(m_callbackLock);
if (length == 0 || tp != HIDReportType::Input || !m_callback)
return;
std::function<bool(const HIDMainItem&, int32_t)> func =
[this](const HIDMainItem& item, int32_t value)
{
m_cb->valueUpdate(item, value);
m_callback->valueUpdate(item, value);
return true;
};
m_parser.ScanValues(func, data, length);

View File

@@ -100,14 +100,15 @@ class HIDDeviceIOKit : public IHIDDevice
IOObjectPointer<io_iterator_t> devIter;
IOObjectPointer<io_registry_entry_t> devEntry = IORegistryEntryFromPath(kIOMasterPortDefault,
device->m_devPath.data());
IORegistryEntryGetChildIterator(devEntry, kIOServicePlane, &devIter);
IOObjectPointer<io_object_t> interfaceEntry;
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(devIter))
IORegistryEntryGetChildIterator(devEntry.get(), kIOServicePlane, &devIter);
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(devIter.get()))
{
if (IOObjectConformsTo(obj, kIOUSBInterfaceClassName))
if (IOObjectConformsTo(obj.get(), kIOUSBInterfaceClassName))
{
interfaceEntry = obj;
else
IOObjectRelease(obj);
break;
}
}
if (!interfaceEntry)
{
@@ -124,7 +125,7 @@ class HIDDeviceIOKit : public IHIDDevice
IOCFPluginPointer iodev;
SInt32 score;
IOReturn err;
err = IOCreatePlugInInterfaceForService(interfaceEntry,
err = IOCreatePlugInInterfaceForService(interfaceEntry.get(),
kIOUSBInterfaceUserClientTypeID,
kIOCFPlugInInterfaceID,
&iodev,

View File

@@ -7,6 +7,7 @@
#include <IOKit/IOKitLib.h>
#include <IOKit/usb/IOUSBLib.h>
#include <IOKit/IOCFPlugIn.h>
#include <sys/utsname.h>
#include "IOKitPointer.hpp"
#include "CFPointer.hpp"
@@ -67,10 +68,11 @@ class HIDListenerIOKit : public IHIDListener
IONotificationPortRef m_llPort;
IOObjectPointer<io_iterator_t> m_llAddNotif, m_llRemoveNotif;
IOObjectPointer<io_iterator_t> m_hidAddNotif, m_hidRemoveNotif;
const char* m_usbClass;
bool m_scanningEnabled;
static void devicesConnectedUSBLL(HIDListenerIOKit* listener,
io_iterator_t iterator)
io_iterator_t iterator)
{
while (IOObjectPointer<io_service_t> obj = IOIteratorNext(iterator))
{
@@ -118,7 +120,7 @@ class HIDListenerIOKit : public IHIDListener
listener->m_finder._insertToken(std::make_unique<DeviceToken>(DeviceType::USB,
vid, pid, vstr, pstr, devPath));
//printf("ADDED %08X %s\n", obj, devPath);
//printf("ADDED %08X %s\n", obj.get(), devPath);
}
}
@@ -139,7 +141,7 @@ class HIDListenerIOKit : public IHIDListener
if (IORegistryEntryGetPath(obj.get(), kIOServicePlane, devPath) != 0)
continue;
listener->m_finder._removeToken(devPath);
//printf("REMOVED %08X %s\n", obj, devPath);
//printf("REMOVED %08X %s\n", obj.get(), devPath);
}
}
@@ -244,6 +246,11 @@ public:
HIDListenerIOKit(DeviceFinder& finder)
: m_finder(finder)
{
struct utsname kernInfo;
uname(&kernInfo);
int release = atoi(kernInfo.release);
m_usbClass = release >= 15 ? "IOUSBHostDevice" : kIOUSBDeviceClassName;
m_listenerRunLoop = CFRunLoopGetMain();
m_llPort = IONotificationPortCreate(kIOMasterPortDefault);
CFRunLoopSourceRef rlSrc = IONotificationPortGetRunLoopSource(m_llPort);
@@ -270,7 +277,7 @@ public:
/* Register Low-Level USB Matcher */
{
CFMutableDictionaryRef matchDict = IOServiceMatching(kIOUSBDeviceClassName);
CFMutableDictionaryRef matchDict = IOServiceMatching(m_usbClass);
CFRetain(matchDict);
kern_return_t llRet =
@@ -312,7 +319,7 @@ public:
{
IOObjectPointer<io_iterator_t> iter;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching(kIOUSBDeviceClassName), &iter) == kIOReturnSuccess)
IOServiceMatching(m_usbClass), &iter) == kIOReturnSuccess)
{
devicesConnectedUSBLL(this, iter.get());
}

View File

@@ -218,6 +218,7 @@ class HIDListenerWinUSB final : public IHIDListener
if (tok.m_connectedDev)
{
XInputPad& pad = static_cast<XInputPad&>(*tok.m_connectedDev);
std::lock_guard<std::mutex> lk(pad.m_callbackLock);
if (pad.m_callback)
pad.m_callback->controllerUpdate(pad, ConvertXInputState(state.Gamepad));
}

View File

@@ -3,7 +3,7 @@
namespace boo
{
NintendoPowerA::NintendoPowerA(DeviceToken* token)
: DeviceBase(token)
: TDeviceBase<INintendoPowerACallback>(token)
{
}
@@ -14,6 +14,7 @@ NintendoPowerA::~NintendoPowerA()
void NintendoPowerA::deviceDisconnected()
{
std::lock_guard<std::mutex> lk(m_callbackLock);
if (m_callback)
m_callback->controllerDisconnected();
}
@@ -29,6 +30,7 @@ void NintendoPowerA::transferCycle()
NintendoPowerAState state = *reinterpret_cast<NintendoPowerAState*>(&payload);
std::lock_guard<std::mutex> lk(m_callbackLock);
if (state != m_last && m_callback)
m_callback->controllerUpdate(state);
m_last = state;