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;
|
||||
void _deviceDisconnected();
|
||||
public:
|
||||
inline CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev)
|
||||
: m_token(token), m_hidDev(hidDev) {}
|
||||
CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev);
|
||||
virtual ~CDeviceBase();
|
||||
void closeDevice();
|
||||
virtual void deviceDisconnected()=0;
|
||||
};
|
||||
|
@ -55,8 +55,9 @@ private:
|
||||
if (preCheck != m_tokens.end())
|
||||
{
|
||||
CDeviceToken& tok = preCheck->second;
|
||||
CDeviceBase* dev = tok.m_connectedDev;
|
||||
tok._deviceClose();
|
||||
deviceDisconnected(tok);
|
||||
deviceDisconnected(tok, dev);
|
||||
m_tokensLock.lock();
|
||||
m_tokens.erase(preCheck);
|
||||
m_tokensLock.unlock();
|
||||
@ -127,7 +128,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void deviceConnected(CDeviceToken&) {}
|
||||
virtual void deviceDisconnected(CDeviceToken&) {}
|
||||
virtual void deviceDisconnected(CDeviceToken&, CDeviceBase*) {}
|
||||
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,6 @@ class CDeviceToken
|
||||
friend class CDeviceFinder;
|
||||
inline void _deviceClose()
|
||||
{
|
||||
printf("CLOSE %p\n", this);
|
||||
if (m_connectedDev)
|
||||
m_connectedDev->_deviceDisconnected();
|
||||
m_connectedDev = NULL;
|
||||
@ -52,7 +51,6 @@ public:
|
||||
inline bool isDeviceOpen() const {return m_connectedDev;}
|
||||
inline CDeviceBase* openAndGetDevice()
|
||||
{
|
||||
printf("OPEN %p\n", this);
|
||||
if (!m_connectedDev)
|
||||
m_connectedDev = BooDeviceNew(this);
|
||||
return m_connectedDev;
|
||||
|
@ -8,6 +8,7 @@ class CDolphinSmashAdapter final : public CDeviceBase
|
||||
void deviceDisconnected();
|
||||
public:
|
||||
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev);
|
||||
~CDolphinSmashAdapter();
|
||||
};
|
||||
|
||||
#endif // CDOLPHINSMASHADAPTER_HPP
|
||||
|
@ -7,6 +7,9 @@
|
||||
#include "CDualshockPad.hpp"
|
||||
#include "CGenericPad.hpp"
|
||||
|
||||
#define VID_NINTENDO 0x57e
|
||||
#define PID_SMASH_ADAPTER 0x337
|
||||
|
||||
enum EDeviceMask
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
|
@ -2,17 +2,30 @@
|
||||
#include "inputdev/CDeviceToken.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()
|
||||
{
|
||||
deviceDisconnected();
|
||||
m_token = NULL;
|
||||
m_hidDev->_deviceDisconnected();
|
||||
m_hidDev = NULL;
|
||||
if (m_hidDev)
|
||||
{
|
||||
m_hidDev->_deviceDisconnected();
|
||||
delete m_hidDev;
|
||||
m_hidDev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CDeviceBase::closeDevice()
|
||||
{
|
||||
if (m_token)
|
||||
|
@ -4,10 +4,15 @@
|
||||
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
|
||||
: CDeviceBase(token, hidDev)
|
||||
{
|
||||
printf("I've been plugged!!\n");
|
||||
|
||||
}
|
||||
|
||||
CDolphinSmashAdapter::~CDolphinSmashAdapter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDolphinSmashAdapter::deviceDisconnected()
|
||||
{
|
||||
printf("I've been unplugged!!\n");
|
||||
|
||||
}
|
||||
|
@ -1,27 +1,92 @@
|
||||
#include "IHIDDevice.hpp"
|
||||
#include "inputdev/CDeviceToken.hpp"
|
||||
#include "inputdev/CDeviceBase.hpp"
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <thread>
|
||||
|
||||
#define MAX_REPORT_SIZE 65536
|
||||
|
||||
class CHIDDeviceIOKit final : public IHIDDevice
|
||||
{
|
||||
CDeviceToken* m_token;
|
||||
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()
|
||||
{
|
||||
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
|
||||
CFRunLoopRef rl = m_runLoop;
|
||||
m_runLoop = NULL;
|
||||
if (rl)
|
||||
CFRunLoopStop(rl);
|
||||
}
|
||||
|
||||
void _setDeviceImp(CDeviceBase* dev)
|
||||
{
|
||||
m_devImp = dev;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
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()
|
||||
{
|
||||
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;
|
||||
|
||||
CFRunLoopRef m_listenerRunLoop;
|
||||
IOHIDManagerRef m_hidManager;
|
||||
bool m_scanningEnabled;
|
||||
|
||||
@ -31,10 +32,18 @@ class CHIDListenerIOKit final : public IHIDListener
|
||||
}
|
||||
|
||||
static void deviceDisconnected(CHIDListenerIOKit* listener,
|
||||
IOReturn,
|
||||
void*,
|
||||
IOReturn ret,
|
||||
void* sender,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -63,7 +72,8 @@ public:
|
||||
IOHIDManagerSetDeviceMatching(m_hidManager, NULL);
|
||||
IOHIDManagerRegisterDeviceMatchingCallback(m_hidManager, (IOHIDDeviceCallback)deviceConnected, 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);
|
||||
if (ret != kIOReturnSuccess)
|
||||
throw std::runtime_error("error establishing IOHIDManager");
|
||||
@ -77,7 +87,7 @@ public:
|
||||
|
||||
~CHIDListenerIOKit()
|
||||
{
|
||||
IOHIDManagerUnscheduleFromRunLoop(m_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
IOHIDManagerUnscheduleFromRunLoop(m_hidManager, m_listenerRunLoop, kCFRunLoopDefaultMode);
|
||||
IOHIDManagerClose(m_hidManager, kIOHIDManagerOptionNone);
|
||||
CFRelease(m_hidManager);
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
#include "inputdev/DeviceClasses.hpp"
|
||||
#include "inputdev/CDeviceToken.hpp"
|
||||
#include "IHIDDevice.hpp"
|
||||
|
||||
bool BooDeviceMatchToken(const CDeviceToken& token, EDeviceMask mask)
|
||||
{
|
||||
if (mask & DEV_DOL_SMASH_ADAPTER &&
|
||||
token.getVendorId() == 0x57e && token.getProductId() == 0x337)
|
||||
token.getVendorId() == VID_NINTENDO && token.getProductId() == PID_SMASH_ADAPTER)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -13,9 +14,13 @@ IHIDDevice* IHIDDeviceNew(CDeviceToken* token);
|
||||
CDeviceBase* BooDeviceNew(CDeviceToken* 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);
|
||||
else
|
||||
delete newDev;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ class CDeviceBase;
|
||||
class IHIDDevice
|
||||
{
|
||||
friend CDeviceBase;
|
||||
virtual void _setDeviceImp(CDeviceBase* dev)=0;
|
||||
virtual void _deviceDisconnected()=0;
|
||||
public:
|
||||
inline virtual ~IHIDDevice() {};
|
||||
};
|
||||
|
||||
#endif // IHIDDEVICE_HPP
|
||||
|
@ -12,14 +12,15 @@ public:
|
||||
{}
|
||||
void deviceConnected(CDeviceToken& tok)
|
||||
{
|
||||
printf("CONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
|
||||
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());
|
||||
delete smashAdapter;
|
||||
smashAdapter = NULL;
|
||||
if (smashAdapter == device)
|
||||
{
|
||||
delete smashAdapter;
|
||||
smashAdapter = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user