better event handling

This commit is contained in:
Jack Andersen 2015-04-22 11:48:23 -10:00
parent edaebc5e50
commit c1dc218bd1
12 changed files with 85 additions and 45 deletions

View File

@ -8,10 +8,12 @@ class CDeviceBase
{ {
CDeviceToken* m_token; CDeviceToken* m_token;
IHIDDevice* m_hidDev; IHIDDevice* m_hidDev;
friend CDeviceToken;
void _deviceDisconnected();
public: public:
inline CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev) inline CDeviceBase(CDeviceToken* token, IHIDDevice* hidDev)
: m_token(token), m_hidDev(hidDev) {} : m_token(token), m_hidDev(hidDev) {}
void _deviceDisconnected(); void closeDevice();
virtual void deviceDisconnected()=0; virtual void deviceDisconnected()=0;
}; };

View File

@ -44,8 +44,9 @@ private:
{ {
if (BooDeviceMatchToken(token, m_types)) { if (BooDeviceMatchToken(token, m_types)) {
m_tokensLock.lock(); m_tokensLock.lock();
m_tokens.insert(std::make_pair(token.getDeviceHandle(), token)); TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token.getDeviceHandle(), std::move(token)));
m_tokensLock.unlock(); m_tokensLock.unlock();
deviceConnected(inseredTok.first->second);
} }
} }
inline void _removeToken(TDeviceHandle handle) inline void _removeToken(TDeviceHandle handle)
@ -55,6 +56,7 @@ private:
{ {
CDeviceToken& tok = preCheck->second; CDeviceToken& tok = preCheck->second;
tok._deviceClose(); tok._deviceClose();
deviceDisconnected(tok);
m_tokensLock.lock(); m_tokensLock.lock();
m_tokens.erase(preCheck); m_tokens.erase(preCheck);
m_tokensLock.unlock(); m_tokensLock.unlock();
@ -75,14 +77,12 @@ public:
}; };
/* Application must specify its interested device-types */ /* Application must specify its interested device-types */
CDeviceFinder(EDeviceMask types, bool autoScan=true) CDeviceFinder(EDeviceMask types)
: m_types(types), m_listener(NULL) : m_types(types), m_listener(NULL)
{ {
if (skDevFinder) if (skDevFinder)
throw std::runtime_error("only one instance of CDeviceFinder may be constructed"); throw std::runtime_error("only one instance of CDeviceFinder may be constructed");
skDevFinder = this; skDevFinder = this;
if (autoScan)
startScanning();
} }
~CDeviceFinder() ~CDeviceFinder()
{ {
@ -126,6 +126,9 @@ public:
return false; return false;
} }
virtual void deviceConnected(CDeviceToken&) {}
virtual void deviceDisconnected(CDeviceToken&) {}
}; };
#endif // CDEVICEFINDER_HPP #endif // CDEVICEFINDER_HPP

View File

@ -12,8 +12,6 @@ typedef IOHIDDeviceRef TDeviceHandle;
#elif __linux__ #elif __linux__
#endif #endif
class CDeviceBase;
class CDeviceToken class CDeviceToken
{ {
unsigned m_vendorId; unsigned m_vendorId;
@ -22,10 +20,21 @@ class CDeviceToken
std::string m_productName; std::string m_productName;
TDeviceHandle m_devHandle; TDeviceHandle m_devHandle;
friend CDeviceBase; friend class CDeviceBase;
CDeviceBase* m_connectedDev; CDeviceBase* m_connectedDev;
friend class CDeviceFinder;
inline void _deviceClose()
{
printf("CLOSE %p\n", this);
if (m_connectedDev)
m_connectedDev->_deviceDisconnected();
m_connectedDev = NULL;
}
public: public:
CDeviceToken(const CDeviceToken&) = delete;
CDeviceToken(CDeviceToken&&) = default;
inline CDeviceToken(unsigned vid, unsigned pid, const char* vname, const char* pname, TDeviceHandle handle) inline CDeviceToken(unsigned vid, unsigned pid, const char* vname, const char* pname, TDeviceHandle handle)
: m_vendorId(vid), m_productId(pid), m_devHandle(handle), m_connectedDev(NULL) : m_vendorId(vid), m_productId(pid), m_devHandle(handle), m_connectedDev(NULL)
{ {
@ -43,20 +52,12 @@ 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;
} }
inline void _deviceClose()
{
if (m_connectedDev)
m_connectedDev->deviceDisconnected();
m_connectedDev = NULL;
}
inline CDeviceToken operator =(const CDeviceToken& other)
{return CDeviceToken(other);}
inline bool operator ==(const CDeviceToken& rhs) const inline bool operator ==(const CDeviceToken& rhs) const
{return m_devHandle == rhs.m_devHandle;} {return m_devHandle == rhs.m_devHandle;}
inline bool operator <(const CDeviceToken& rhs) const inline bool operator <(const CDeviceToken& rhs) const

View File

@ -7,11 +7,7 @@ class CDolphinSmashAdapter final : public CDeviceBase
{ {
void deviceDisconnected(); void deviceDisconnected();
public: public:
CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev) CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev);
: CDeviceBase(token, hidDev)
{
}
}; };
#endif // CDOLPHINSMASHADAPTER_HPP #endif // CDOLPHINSMASHADAPTER_HPP

View File

@ -49,12 +49,13 @@ unix:!macx:SOURCES += \
$$PWD/src/inputdev/CHIDListenerUdev.cpp $$PWD/src/inputdev/CHIDListenerUdev.cpp
macx:SOURCES += \ macx:SOURCES += \
$$PWD/src/mac/CCGLContext.cpp $$PWD/src/mac/CCGLContext.cpp \
$$PWD/src/inputdev/CHIDDeviceIOKit.cpp \
$$PWD/src/inputdev/CHIDListenerIOKit.cpp
macx:OBJECTIVE_SOURCES += \ macx:OBJECTIVE_SOURCES += \
$$PWD/src/mac/CCGLCocoaView.mm \ $$PWD/src/mac/CCGLCocoaView.mm \
$$PWD/src/inputdev/CHIDDeviceIOKit.mm \
$$PWD/src/inputdev/CHIDListenerIOKit.mm
win32:SOURCES += \ win32:SOURCES += \
$$PWD/src/win/CWGLContext.cpp \ $$PWD/src/win/CWGLContext.cpp \

View File

@ -5,11 +5,18 @@
void CDeviceBase::_deviceDisconnected() void CDeviceBase::_deviceDisconnected()
{ {
m_token->m_connectedDev = NULL; deviceDisconnected();
m_token = NULL; m_token = NULL;
m_hidDev->deviceDisconnected(); m_hidDev->_deviceDisconnected();
m_hidDev = NULL; m_hidDev = NULL;
} }
void CDeviceBase::closeDevice()
{
if (m_token)
m_token->_deviceClose();
}

View File

@ -1,6 +1,13 @@
#include "inputdev/CDolphinSmashAdapter.hpp" #include "inputdev/CDolphinSmashAdapter.hpp"
#include <stdio.h>
CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token, IHIDDevice* hidDev)
: CDeviceBase(token, hidDev)
{
printf("I've been plugged!!\n");
}
void CDolphinSmashAdapter::deviceDisconnected() void CDolphinSmashAdapter::deviceDisconnected()
{ {
printf("I've been unplugged!!\n");
} }

View File

@ -5,6 +5,12 @@
class CHIDDeviceIOKit final : public IHIDDevice class CHIDDeviceIOKit final : public IHIDDevice
{ {
IOHIDDeviceRef m_dev; IOHIDDeviceRef m_dev;
void _deviceDisconnected()
{
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
}
public: public:
CHIDDeviceIOKit(CDeviceToken* token) CHIDDeviceIOKit(CDeviceToken* token)
@ -13,15 +19,12 @@ public:
IOHIDDeviceOpen(m_dev, kIOHIDOptionsTypeNone); IOHIDDeviceOpen(m_dev, kIOHIDOptionsTypeNone);
} }
CHIDDeviceIOKit() ~CHIDDeviceIOKit()
{ {
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone); IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
} }
void deviceDisconnected()
{
IOHIDDeviceClose(m_dev, kIOHIDOptionsTypeNone);
}
}; };
IHIDDevice* IHIDDeviceNew(CDeviceToken* token) IHIDDevice* IHIDDeviceNew(CDeviceToken* token)

View File

@ -34,23 +34,23 @@ class CHIDListenerIOKit final : public IHIDListener
IOReturn, IOReturn,
void*, void*,
IOHIDDeviceRef device) IOHIDDeviceRef device)
{listener->m_finder._removeToken(device);} {
listener->m_finder._removeToken(device);
}
static void applyDevice(IOHIDDeviceRef device, CHIDListenerIOKit* listener) static void applyDevice(IOHIDDeviceRef device, CHIDListenerIOKit* listener)
{ {
auto preCheck = listener->m_finder.m_tokens.find(device); if (listener->m_finder._hasToken(device))
if (preCheck != listener->m_finder.m_tokens.end())
return; return;
CFIndex vid, pid; CFIndex vid, pid;
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberCFIndexType, &vid); CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey)), kCFNumberCFIndexType, &vid);
CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberCFIndexType, &pid); CFNumberGetValue((CFNumberRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey)), kCFNumberCFIndexType, &pid);
CFStringRef manuf = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey)); CFStringRef manuf = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey));
CFStringRef product = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey)); CFStringRef product = (CFStringRef)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
listener->m_finder.m_tokens.insert(std::make_pair(device, listener->m_finder._insertToken(CDeviceToken(vid, pid,
CDeviceToken(vid, pid,
CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8), CFStringGetCStringPtr(manuf, kCFStringEncodingUTF8),
CFStringGetCStringPtr(product, kCFStringEncodingUTF8), CFStringGetCStringPtr(product, kCFStringEncodingUTF8),
device))); device));
} }
public: public:

View File

@ -7,7 +7,7 @@ class CDeviceBase;
class IHIDDevice class IHIDDevice
{ {
friend CDeviceBase; friend CDeviceBase;
virtual void deviceDisconnected()=0; virtual void _deviceDisconnected()=0;
}; };
#endif // IHIDDEVICE_HPP #endif // IHIDDEVICE_HPP

View File

@ -5,6 +5,7 @@
#include <mutex> #include <mutex>
#include "CDeviceToken.hpp" #include "CDeviceToken.hpp"
typedef std::map<TDeviceHandle, CDeviceToken> TDeviceTokens; typedef std::map<TDeviceHandle, CDeviceToken> TDeviceTokens;
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
class CDeviceFinder; class CDeviceFinder;
class IHIDListener class IHIDListener

View File

@ -3,11 +3,30 @@
#include <stdio.h> #include <stdio.h>
#include <boo.hpp> #include <boo.hpp>
class CTestDeviceFinder : public CDeviceFinder
{
CDolphinSmashAdapter* smashAdapter = NULL;
public:
CTestDeviceFinder()
: CDeviceFinder(DEV_DOL_SMASH_ADAPTER)
{}
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)
{
printf("DISCONNECTED %s %s\n", tok.getVendorName().c_str(), tok.getProductName().c_str());
delete smashAdapter;
smashAdapter = NULL;
}
};
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
CDeviceFinder finder(DEV_DOL_SMASH_ADAPTER); CTestDeviceFinder finder;
CDeviceToken& smashToken = finder.getTokens().begin()->second; finder.startScanning();
CDolphinSmashAdapter* smashAdapter = dynamic_cast<CDolphinSmashAdapter*>(smashToken.openAndGetDevice());
IGraphicsContext* ctx = new CGraphicsContext; IGraphicsContext* ctx = new CGraphicsContext;