2015-04-19 20:16:50 +00:00
|
|
|
#ifndef CDEVICEFINDER_HPP
|
|
|
|
#define CDEVICEFINDER_HPP
|
|
|
|
|
2015-04-21 04:02:43 +00:00
|
|
|
#include <set>
|
|
|
|
#include <mutex>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include "CDeviceToken.hpp"
|
|
|
|
#include "IHIDListener.hpp"
|
|
|
|
#include "DeviceClasses.hpp"
|
|
|
|
|
|
|
|
static class CDeviceFinder* skDevFinder = NULL;
|
|
|
|
|
|
|
|
class CDeviceFinder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
friend class CHIDListenerIOKit;
|
|
|
|
friend class CHIDListenerUdev;
|
|
|
|
friend class CHIDListenerWin32;
|
|
|
|
static inline CDeviceFinder* instance() {return skDevFinder;}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
/* Types this finder is interested in (immutable) */
|
|
|
|
EDeviceMask m_types;
|
|
|
|
|
|
|
|
/* Platform-specific USB event registration
|
|
|
|
* (for auto-scanning, NULL if not registered) */
|
|
|
|
IHIDListener* m_listener;
|
|
|
|
|
|
|
|
/* Set of presently-connected device tokens */
|
|
|
|
TDeviceTokens m_tokens;
|
|
|
|
std::mutex m_tokensLock;
|
|
|
|
|
|
|
|
/* Friend methods for platform-listener to find/insert/remove
|
|
|
|
* tokens with type-filtering */
|
2015-04-24 00:24:15 +00:00
|
|
|
inline bool _hasToken(const std::string& path)
|
2015-04-21 04:02:43 +00:00
|
|
|
{
|
2015-04-24 00:24:15 +00:00
|
|
|
auto preCheck = m_tokens.find(path);
|
2015-04-21 04:02:43 +00:00
|
|
|
if (preCheck != m_tokens.end())
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
inline void _insertToken(CDeviceToken&& token)
|
|
|
|
{
|
|
|
|
if (BooDeviceMatchToken(token, m_types)) {
|
|
|
|
m_tokensLock.lock();
|
2015-04-24 00:24:15 +00:00
|
|
|
TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
|
2015-04-21 04:02:43 +00:00
|
|
|
m_tokensLock.unlock();
|
2015-04-22 21:48:23 +00:00
|
|
|
deviceConnected(inseredTok.first->second);
|
2015-04-21 04:02:43 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-24 00:24:15 +00:00
|
|
|
inline void _removeToken(const std::string& path)
|
2015-04-21 04:02:43 +00:00
|
|
|
{
|
2015-04-24 00:24:15 +00:00
|
|
|
auto preCheck = m_tokens.find(path);
|
2015-04-21 04:02:43 +00:00
|
|
|
if (preCheck != m_tokens.end())
|
|
|
|
{
|
|
|
|
CDeviceToken& tok = preCheck->second;
|
2015-04-23 00:46:32 +00:00
|
|
|
CDeviceBase* dev = tok.m_connectedDev;
|
2015-04-21 04:02:43 +00:00
|
|
|
tok._deviceClose();
|
2015-04-23 00:46:32 +00:00
|
|
|
deviceDisconnected(tok, dev);
|
2015-04-21 04:02:43 +00:00
|
|
|
m_tokensLock.lock();
|
|
|
|
m_tokens.erase(preCheck);
|
|
|
|
m_tokensLock.unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
class CDeviceTokensHandle
|
|
|
|
{
|
|
|
|
CDeviceFinder& m_finder;
|
|
|
|
public:
|
|
|
|
inline CDeviceTokensHandle(CDeviceFinder& finder) : m_finder(finder)
|
|
|
|
{m_finder.m_tokensLock.lock();}
|
|
|
|
inline ~CDeviceTokensHandle() {m_finder.m_tokensLock.unlock();}
|
|
|
|
inline TDeviceTokens::iterator begin() {return m_finder.m_tokens.begin();}
|
|
|
|
inline TDeviceTokens::iterator end() {return m_finder.m_tokens.end();}
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Application must specify its interested device-types */
|
2015-04-22 21:48:23 +00:00
|
|
|
CDeviceFinder(EDeviceMask types)
|
2015-04-21 04:02:43 +00:00
|
|
|
: m_types(types), m_listener(NULL)
|
|
|
|
{
|
|
|
|
if (skDevFinder)
|
|
|
|
throw std::runtime_error("only one instance of CDeviceFinder may be constructed");
|
|
|
|
skDevFinder = this;
|
|
|
|
}
|
|
|
|
~CDeviceFinder()
|
|
|
|
{
|
|
|
|
if (m_listener)
|
|
|
|
m_listener->stopScanning();
|
|
|
|
delete m_listener;
|
|
|
|
skDevFinder = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get interested device-type mask */
|
|
|
|
inline EDeviceMask getTypes() const {return m_types;}
|
|
|
|
|
|
|
|
/* Iterable set of tokens */
|
|
|
|
inline CDeviceTokensHandle getTokens() {return CDeviceTokensHandle(*this);}
|
|
|
|
|
|
|
|
/* Automatic device scanning */
|
|
|
|
inline bool startScanning()
|
|
|
|
{
|
|
|
|
if (!m_listener)
|
|
|
|
m_listener = IHIDListenerNew(*this);
|
|
|
|
if (m_listener)
|
|
|
|
return m_listener->startScanning();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
inline bool stopScanning()
|
|
|
|
{
|
|
|
|
if (!m_listener)
|
|
|
|
m_listener = IHIDListenerNew(*this);
|
|
|
|
if (m_listener)
|
|
|
|
return m_listener->stopScanning();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Manual device scanning */
|
|
|
|
inline bool scanNow()
|
|
|
|
{
|
|
|
|
if (!m_listener)
|
|
|
|
m_listener = IHIDListenerNew(*this);
|
|
|
|
if (m_listener)
|
|
|
|
return m_listener->scanNow();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-04-22 21:48:23 +00:00
|
|
|
virtual void deviceConnected(CDeviceToken&) {}
|
2015-04-23 00:46:32 +00:00
|
|
|
virtual void deviceDisconnected(CDeviceToken&, CDeviceBase*) {}
|
2015-04-22 21:48:23 +00:00
|
|
|
|
2015-04-21 04:02:43 +00:00
|
|
|
};
|
2015-04-19 20:16:50 +00:00
|
|
|
|
|
|
|
#endif // CDEVICEFINDER_HPP
|