mirror of
https://github.com/AxioDL/boo.git
synced 2025-07-14 17:16:07 +00:00
eliminated some hid-thread race conditions
This commit is contained in:
parent
c1dc218bd1
commit
92e7c3fb04
@ -11,8 +11,8 @@ class CDeviceBase
|
|||||||
friend CDeviceToken;
|
friend CDeviceToken;
|
||||||
void _deviceDisconnected();
|
void _deviceDisconnected();
|
||||||
public:
|
public:
|
||||||
inline CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev)
|
CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev);
|
||||||
: m_token(token), m_hidDev(hidDev) {}
|
virtual ~CDeviceBase();
|
||||||
void closeDevice();
|
void closeDevice();
|
||||||
virtual void deviceDisconnected()=0;
|
virtual void deviceDisconnected()=0;
|
||||||
};
|
};
|
||||||
|
@ -55,8 +55,9 @@ private:
|
|||||||
if (preCheck != m_tokens.end())
|
if (preCheck != m_tokens.end())
|
||||||
{
|
{
|
||||||
CDeviceToken& tok = preCheck->second;
|
CDeviceToken& tok = preCheck->second;
|
||||||
|
CDeviceBase* dev = tok.m_connectedDev;
|
||||||
tok._deviceClose();
|
tok._deviceClose();
|
||||||
deviceDisconnected(tok);
|
deviceDisconnected(tok, dev);
|
||||||
m_tokensLock.lock();
|
m_tokensLock.lock();
|
||||||
m_tokens.erase(preCheck);
|
m_tokens.erase(preCheck);
|
||||||
m_tokensLock.unlock();
|
m_tokensLock.unlock();
|
||||||
@ -127,7 +128,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void deviceConnected(CDeviceToken&) {}
|
virtual void deviceConnected(CDeviceToken&) {}
|
||||||
virtual void deviceDisconnected(CDeviceToken&) {}
|
virtual void deviceDisconnected(CDeviceToken&, CDeviceBase*) {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ class CDeviceToken
|
|||||||
friend class CDeviceFinder;
|
friend class CDeviceFinder;
|
||||||
inline void _deviceClose()
|
inline void _deviceClose()
|
||||||
{
|
{
|
||||||
printf("CLOSE %p\n", this);
|
|
||||||
if (m_connectedDev)
|
if (m_connectedDev)
|
||||||
m_connectedDev->_deviceDisconnected();
|
m_connectedDev->_deviceDisconnected();
|
||||||
m_connectedDev = NULL;
|
m_connectedDev = NULL;
|
||||||
@ -52,7 +51,6 @@ public:
|
|||||||
inline bool isDeviceOpen() const {return m_connectedDev;}
|
inline bool isDeviceOpen() const {return m_connectedDev;}
|
||||||
inline CDeviceBase* openAndGetDevice()
|
inline CDeviceBase* openAndGetDevice()
|
||||||
{
|
{
|
||||||
printf("OPEN %p\n", this);
|
|
||||||
if (!m_connectedDev)
|
if (!m_connectedDev)
|
||||||
m_connectedDev = BooDeviceNew(this);
|
m_connectedDev = BooDeviceNew(this);
|
||||||
return m_connectedDev;
|
return m_connectedDev;
|
||||||
|
@ -8,6 +8,7 @@ class CDolphinSmashAdapter final : public CDeviceBase
|
|||||||
void deviceDisconnected();
|
void deviceDisconnected();
|
||||||
public:
|
public:
|
||||||
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev);
|
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev);
|
||||||
|
~CDolphinSmashAdapter();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CDOLPHINSMASHADAPTER_HPP
|
#endif // CDOLPHINSMASHADAPTER_HPP
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
#include "CDualshockPad.hpp"
|
#include "CDualshockPad.hpp"
|
||||||
#include "CGenericPad.hpp"
|
#include "CGenericPad.hpp"
|
||||||
|
|
||||||
|
#define VID_NINTENDO 0x57e
|
||||||
|
#define PID_SMASH_ADAPTER 0x337
|
||||||
|
|
||||||
enum EDeviceMask
|
enum EDeviceMask
|
||||||
{
|
{
|
||||||
DEV_NONE = 0,
|
DEV_NONE = 0,
|
||||||
|
@ -2,17 +2,30 @@
|
|||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "inputdev/CDeviceToken.hpp"
|
||||||
#include "IHIDDevice.hpp"
|
#include "IHIDDevice.hpp"
|
||||||
|
|
||||||
|
CDeviceBase::CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev)
|
||||||
|
: m_token(token), m_hidDev(hidDev)
|
||||||
|
{
|
||||||
|
hidDev->_setDeviceImp(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CDeviceBase::~CDeviceBase()
|
||||||
|
{
|
||||||
|
delete m_hidDev;
|
||||||
|
}
|
||||||
|
|
||||||
void CDeviceBase::_deviceDisconnected()
|
void CDeviceBase::_deviceDisconnected()
|
||||||
{
|
{
|
||||||
deviceDisconnected();
|
deviceDisconnected();
|
||||||
m_token = NULL;
|
m_token = NULL;
|
||||||
m_hidDev->_deviceDisconnected();
|
if (m_hidDev)
|
||||||
m_hidDev = NULL;
|
{
|
||||||
|
m_hidDev->_deviceDisconnected();
|
||||||
|
delete m_hidDev;
|
||||||
|
m_hidDev = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CDeviceBase::closeDevice()
|
void CDeviceBase::closeDevice()
|
||||||
{
|
{
|
||||||
if (m_token)
|
if (m_token)
|
||||||
|
@ -4,10 +4,15 @@
|
|||||||
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
|
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
|
||||||
: CDeviceBase(token, hidDev)
|
: CDeviceBase(token, hidDev)
|
||||||
{
|
{
|
||||||
printf("I've been plugged!!\n");
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CDolphinSmashAdapter::~CDolphinSmashAdapter()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDolphinSmashAdapter::deviceDisconnected()
|
void CDolphinSmashAdapter::deviceDisconnected()
|
||||||
{
|
{
|
||||||
printf("I've been unplugged!!\n");
|
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,92 @@
|
|||||||
#include "IHIDDevice.hpp"
|
#include "IHIDDevice.hpp"
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "inputdev/CDeviceToken.hpp"
|
||||||
|
#include "inputdev/CDeviceBase.hpp"
|
||||||
#include <IOKit/hid/IOHIDLib.h>
|
#include <IOKit/hid/IOHIDLib.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#define MAX_REPORT_SIZE 65536
|
||||||
|
|
||||||
class CHIDDeviceIOKit final : public IHIDDevice
|
class CHIDDeviceIOKit final : public IHIDDevice
|
||||||
{
|
{
|
||||||
|
CDeviceToken* m_token;
|
||||||
IOHIDDeviceRef m_dev;
|
IOHIDDeviceRef m_dev;
|
||||||
|
std::mutex m_initMutex;
|
||||||
|
std::condition_variable m_initCond;
|
||||||
|
std::thread* m_thread;
|
||||||
|
CFRunLoopRef m_runLoop;
|
||||||
|
CDeviceBase* m_devImp;
|
||||||
|
|
||||||
|
static void _inputReport(CHIDDeviceIOKit* device,
|
||||||
|
IOReturn result,
|
||||||
|
void* sender,
|
||||||
|
IOHIDReportType type,
|
||||||
|
uint32_t reportID,
|
||||||
|
uint8_t* report,
|
||||||
|
CFIndex reportLength)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
static void _disconnect(CHIDDeviceIOKit* device,
|
||||||
|
IOReturn result,
|
||||||
|
IOHIDDeviceRef sender)
|
||||||
|
{
|
||||||
|
device->_deviceDisconnected();
|
||||||
|
}
|
||||||
|
static void _threadProc(CHIDDeviceIOKit* device)
|
||||||
|
{
|
||||||
|
char thrName[128];
|
||||||
|
snprintf(thrName, 128, "%s Device Thread", device->m_token->getProductName().c_str());
|
||||||
|
pthread_setname_np(thrName);
|
||||||
|
__block std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||||
|
device->m_runLoop = CFRunLoopGetCurrent();
|
||||||
|
CFRunLoopAddObserver(device->m_runLoop,
|
||||||
|
CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopEntry, false, 0,
|
||||||
|
^(CFRunLoopObserverRef, CFRunLoopActivity) {
|
||||||
|
lk.unlock();
|
||||||
|
device->m_initCond.notify_one();
|
||||||
|
}), kCFRunLoopCommonModes);
|
||||||
|
|
||||||
|
uint8_t* inputBuf = new uint8_t[MAX_REPORT_SIZE];
|
||||||
|
IOHIDDeviceRegisterInputReportCallback(device->m_dev, inputBuf, MAX_REPORT_SIZE,
|
||||||
|
(IOHIDReportCallback)_inputReport, device);
|
||||||
|
IOHIDDeviceRegisterRemovalCallback(device->m_dev, (IOHIDCallback)_disconnect, device);
|
||||||
|
IOHIDDeviceScheduleWithRunLoop(device->m_dev, device->m_runLoop, kCFRunLoopDefaultMode);
|
||||||
|
IOHIDDeviceOpen(device->m_dev, kIOHIDOptionsTypeNone);
|
||||||
|
CFRunLoopRun();
|
||||||
|
if (device->m_runLoop)
|
||||||
|
IOHIDDeviceClose(device->m_dev, kIOHIDOptionsTypeNone);
|
||||||
|
}
|
||||||
|
|
||||||
void _deviceDisconnected()
|
void _deviceDisconnected()
|
||||||
{
|
{
|
||||||
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
|
CFRunLoopRef rl = m_runLoop;
|
||||||
|
m_runLoop = NULL;
|
||||||
|
if (rl)
|
||||||
|
CFRunLoopStop(rl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _setDeviceImp(CDeviceBase* dev)
|
||||||
|
{
|
||||||
|
m_devImp = dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
CHIDDeviceIOKit(CDeviceToken* token)
|
CHIDDeviceIOKit(CDeviceToken* token)
|
||||||
: m_dev(token->getDeviceHandle())
|
: m_token(token),
|
||||||
|
m_dev(token->getDeviceHandle())
|
||||||
{
|
{
|
||||||
IOHIDDeviceOpen(m_dev, kIOHIDOptionsTypeNone);
|
std::unique_lock<std::mutex> lk(m_initMutex);
|
||||||
|
m_thread = new std::thread(_threadProc, this);
|
||||||
|
m_initCond.wait(lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
~CHIDDeviceIOKit()
|
~CHIDDeviceIOKit()
|
||||||
{
|
{
|
||||||
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
|
if (m_runLoop)
|
||||||
|
CFRunLoopStop(m_runLoop);
|
||||||
|
m_thread->detach();
|
||||||
|
delete m_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
{
|
{
|
||||||
CDeviceFinder& m_finder;
|
CDeviceFinder& m_finder;
|
||||||
|
|
||||||
|
CFRunLoopRef m_listenerRunLoop;
|
||||||
IOHIDManagerRef m_hidManager;
|
IOHIDManagerRef m_hidManager;
|
||||||
bool m_scanningEnabled;
|
bool m_scanningEnabled;
|
||||||
|
|
||||||
@ -31,10 +32,18 @@ class CHIDListenerIOKit final : public IHIDListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void deviceDisconnected(CHIDListenerIOKit* listener,
|
static void deviceDisconnected(CHIDListenerIOKit* listener,
|
||||||
IOReturn,
|
IOReturn ret,
|
||||||
void*,
|
void* sender,
|
||||||
IOHIDDeviceRef device)
|
IOHIDDeviceRef device)
|
||||||
{
|
{
|
||||||
|
if (CFRunLoopGetCurrent() != listener->m_listenerRunLoop)
|
||||||
|
{
|
||||||
|
CFRunLoopPerformBlock(listener->m_listenerRunLoop, kCFRunLoopDefaultMode, ^{
|
||||||
|
deviceDisconnected(listener, ret, sender, device);
|
||||||
|
});
|
||||||
|
CFRunLoopWakeUp(listener->m_listenerRunLoop);
|
||||||
|
return;
|
||||||
|
}
|
||||||
listener->m_finder._removeToken(device);
|
listener->m_finder._removeToken(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +72,8 @@ public:
|
|||||||
IOHIDManagerSetDeviceMatching(m_hidManager, NULL);
|
IOHIDManagerSetDeviceMatching(m_hidManager, NULL);
|
||||||
IOHIDManagerRegisterDeviceMatchingCallback(m_hidManager, (IOHIDDeviceCallback)deviceConnected, this);
|
IOHIDManagerRegisterDeviceMatchingCallback(m_hidManager, (IOHIDDeviceCallback)deviceConnected, this);
|
||||||
IOHIDManagerRegisterDeviceRemovalCallback(m_hidManager, (IOHIDDeviceCallback)deviceDisconnected, this);
|
IOHIDManagerRegisterDeviceRemovalCallback(m_hidManager, (IOHIDDeviceCallback)deviceDisconnected, this);
|
||||||
IOHIDManagerScheduleWithRunLoop(m_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
m_listenerRunLoop = CFRunLoopGetCurrent();
|
||||||
|
IOHIDManagerScheduleWithRunLoop(m_hidManager, m_listenerRunLoop, kCFRunLoopDefaultMode);
|
||||||
IOReturn ret = IOHIDManagerOpen(m_hidManager, kIOHIDManagerOptionNone);
|
IOReturn ret = IOHIDManagerOpen(m_hidManager, kIOHIDManagerOptionNone);
|
||||||
if (ret != kIOReturnSuccess)
|
if (ret != kIOReturnSuccess)
|
||||||
throw std::runtime_error("error establishing IOHIDManager");
|
throw std::runtime_error("error establishing IOHIDManager");
|
||||||
@ -77,7 +87,7 @@ public:
|
|||||||
|
|
||||||
~CHIDListenerIOKit()
|
~CHIDListenerIOKit()
|
||||||
{
|
{
|
||||||
IOHIDManagerUnscheduleFromRunLoop(m_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
IOHIDManagerUnscheduleFromRunLoop(m_hidManager, m_listenerRunLoop, kCFRunLoopDefaultMode);
|
||||||
IOHIDManagerClose(m_hidManager, kIOHIDManagerOptionNone);
|
IOHIDManagerClose(m_hidManager, kIOHIDManagerOptionNone);
|
||||||
CFRelease(m_hidManager);
|
CFRelease(m_hidManager);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include "inputdev/DeviceClasses.hpp"
|
#include "inputdev/DeviceClasses.hpp"
|
||||||
#include "inputdev/CDeviceToken.hpp"
|
#include "inputdev/CDeviceToken.hpp"
|
||||||
|
#include "IHIDDevice.hpp"
|
||||||
|
|
||||||
bool BooDeviceMatchToken(const CDeviceToken& token, EDeviceMask mask)
|
bool BooDeviceMatchToken(const CDeviceToken& token, EDeviceMask mask)
|
||||||
{
|
{
|
||||||
if (mask & DEV_DOL_SMASH_ADAPTER &&
|
if (mask & DEV_DOL_SMASH_ADAPTER &&
|
||||||
token.getVendorId() == 0x57e && token.getProductId() == 0x337)
|
token.getVendorId() == VID_NINTENDO && token.getProductId() == PID_SMASH_ADAPTER)
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -13,9 +14,13 @@ IHIDDevice* IHIDDeviceNew(CDeviceToken* token);
|
|||||||
CDeviceBase* BooDeviceNew(CDeviceToken* token)
|
CDeviceBase* BooDeviceNew(CDeviceToken* token)
|
||||||
{
|
{
|
||||||
IHIDDevice* newDev = IHIDDeviceNew(token);
|
IHIDDevice* newDev = IHIDDeviceNew(token);
|
||||||
|
if (!newDev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
if (token->getVendorId() == 0x57e && token->getProductId() == 0x337)
|
if (token->getVendorId() == VID_NINTENDO && token->getProductId() == PID_SMASH_ADAPTER)
|
||||||
return new CDolphinSmashAdapter(token, newDev);
|
return new CDolphinSmashAdapter(token, newDev);
|
||||||
|
else
|
||||||
|
delete newDev;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ class CDeviceBase;
|
|||||||
class IHIDDevice
|
class IHIDDevice
|
||||||
{
|
{
|
||||||
friend CDeviceBase;
|
friend CDeviceBase;
|
||||||
|
virtual void _setDeviceImp(CDeviceBase* dev)=0;
|
||||||
virtual void _deviceDisconnected()=0;
|
virtual void _deviceDisconnected()=0;
|
||||||
|
public:
|
||||||
|
inline virtual ~IHIDDevice() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IHIDDEVICE_HPP
|
#endif // IHIDDEVICE_HPP
|
||||||
|
@ -12,14 +12,15 @@ public:
|
|||||||
{}
|
{}
|
||||||
void deviceConnected(CDeviceToken& tok)
|
void deviceConnected(CDeviceToken& tok)
|
||||||
{
|
{
|
||||||
printf("CONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
|
|
||||||
smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(tok.openAndGetDevice());
|
smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(tok.openAndGetDevice());
|
||||||
}
|
}
|
||||||
void deviceDisconnected(CDeviceToken& tok)
|
void deviceDisconnected(CDeviceToken&, CDeviceBase* device)
|
||||||
{
|
{
|
||||||
printf("DISCONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
|
if (smashAdapter == device)
|
||||||
delete smashAdapter;
|
{
|
||||||
smashAdapter = NULL;
|
delete smashAdapter;
|
||||||
|
smashAdapter = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user