better generic HID differentiation; smash udev working

This commit is contained in:
Jack Andersen 2015-04-30 13:17:46 -10:00
parent 4b8651b844
commit 1125e20b6e
15 changed files with 257 additions and 125 deletions

View File

@ -6,7 +6,7 @@ namespace boo
const SDeviceSignature BOO_DEVICE_SIGS[] =
{
DEVICE_SIG(CDolphinSmashAdapter, 0x57e, 0x337, true),
DEVICE_SIG(CDolphinSmashAdapter, 0x57e, 0x337),
DEVICE_SIG_SENTINEL()
};

View File

@ -27,14 +27,14 @@ public:
virtual void deviceError(const char* error) {fprintf(stderr, "%s\n", error);}
/* Low-Level API */
bool sendInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length);
size_t receiveInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length);
bool sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length);
virtual void initialCycle() {}
virtual void transferCycle() {}
virtual void finalCycle() {}
/* High-Level API */
bool sendReport(const uint8_t* data, size_t length);
bool sendHIDReport(const uint8_t* data, size_t length);
virtual size_t receiveReport(uint8_t* data, size_t length) {return 0;}
};

View File

@ -44,7 +44,7 @@ private:
return true;
return false;
}
inline void _insertToken(CDeviceToken&& token)
inline bool _insertToken(CDeviceToken&& token)
{
if (SDeviceSignature::DeviceMatchToken(token, m_types)) {
m_tokensLock.lock();
@ -52,7 +52,9 @@ private:
m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
m_tokensLock.unlock();
deviceConnected(inseredTok.first->second);
return true;
}
return false;
}
inline void _removeToken(const std::string& path)
{

View File

@ -10,6 +10,17 @@ namespace boo
class CDeviceToken
{
public:
enum TDeviceType
{
DEVTYPE_NONE = 0,
DEVTYPE_USB = 1,
DEVTYPE_BLUETOOTH = 2,
DEVTYPE_GENERICHID = 3
};
private:
TDeviceType m_devType;
unsigned m_vendorId;
unsigned m_productId;
std::string m_vendorName;
@ -28,10 +39,11 @@ class CDeviceToken
}
public:
CDeviceToken(const CDeviceToken&) = delete;
CDeviceToken(CDeviceToken&&) = default;
inline CDeviceToken(unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
: m_vendorId(vid), m_productId(pid), m_devPath(path), m_connectedDev(NULL)
inline CDeviceToken(enum TDeviceType devType, unsigned vid, unsigned pid, const char* vname, const char* pname, const char* path)
: m_devType(devType), m_vendorId(vid), m_productId(pid), m_devPath(path), m_connectedDev(NULL)
{
if (vname)
m_vendorName = vname;
@ -39,6 +51,7 @@ public:
m_productName = pname;
}
inline TDeviceType getDeviceType() const {return m_devType;}
inline unsigned getVendorId() const {return m_vendorId;}
inline unsigned getProductId() const {return m_productId;}
inline const std::string& getVendorName() const {return m_vendorName;}

View File

@ -52,7 +52,6 @@ class CDolphinSmashAdapter final : public CDeviceBase
uint8_t m_knownControllers;
uint8_t m_rumbleRequest;
uint8_t m_rumbleState;
bool m_didHandshake;
void deviceDisconnected();
void initialCycle();
void transferCycle();

View File

@ -1,9 +1,20 @@
#ifndef CGENERICPAD_HPP
#define CGENERICPAD_HPP
#include "CDeviceBase.hpp"
namespace boo
{
class CGenericPad final : public CDeviceBase
{
public:
CGenericPad(CDeviceToken* token);
~CGenericPad();
void deviceDisconnected();
};
}
#endif // CGENERICPAD_HPP

View File

@ -16,17 +16,16 @@ struct SDeviceSignature
typedef std::function<CDeviceBase*(CDeviceToken*)> TFactoryLambda;
const char* m_name;
unsigned m_vid, m_pid;
bool m_lowLevel;
TFactoryLambda m_factory;
SDeviceSignature() : m_name(NULL) {} /* Sentinel constructor */
SDeviceSignature(const char* name, unsigned vid, unsigned pid, bool lowLevel, TFactoryLambda&& factory)
: m_name(name), m_vid(vid), m_pid(pid), m_lowLevel(lowLevel), m_factory(factory) {}
SDeviceSignature(const char* name, unsigned vid, unsigned pid, TFactoryLambda&& factory)
: m_name(name), m_vid(vid), m_pid(pid), m_factory(factory) {}
static bool DeviceMatchToken(const CDeviceToken& token, const TDeviceSignatureSet& sigSet);
static CDeviceBase* DeviceNew(CDeviceToken& token);
};
#define DEVICE_SIG(name, vid, pid, lowLevel) \
SDeviceSignature(#name, vid, pid, lowLevel, [](CDeviceToken* tok) -> CDeviceBase* {return new name(tok);})
#define DEVICE_SIG(name, vid, pid) \
SDeviceSignature(#name, vid, pid, [](CDeviceToken* tok) -> CDeviceBase* {return new name(tok);})
#define DEVICE_SIG_SENTINEL() SDeviceSignature()
extern const SDeviceSignature BOO_DEVICE_SIGS[];

View File

@ -33,24 +33,24 @@ void CDeviceBase::closeDevice()
m_token->_deviceClose();
}
bool CDeviceBase::sendInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool CDeviceBase::sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
{
if (m_hidDev)
return m_hidDev->_sendInterruptTransfer(pipe, data, length);
return m_hidDev->_sendUSBInterruptTransfer(pipe, data, length);
return false;
}
size_t CDeviceBase::receiveInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t CDeviceBase::receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
{
if (m_hidDev)
return m_hidDev->_receiveInterruptTransfer(pipe, data, length);
return m_hidDev->_receiveUSBInterruptTransfer(pipe, data, length);
return false;
}
bool CDeviceBase::sendReport(const uint8_t* data, size_t length)
bool CDeviceBase::sendHIDReport(const uint8_t* data, size_t length)
{
if (m_hidDev)
return m_hidDev->_sendReport(data, length);
return m_hidDev->_sendHIDReport(data, length);
return false;
}

View File

@ -14,8 +14,7 @@ CDolphinSmashAdapter::CDolphinSmashAdapter(CDeviceToken* token)
m_callback(NULL),
m_knownControllers(0),
m_rumbleRequest(0),
m_rumbleState(0),
m_didHandshake(false)
m_rumbleState(0)
{
}
@ -23,8 +22,6 @@ CDolphinSmashAdapter::~CDolphinSmashAdapter()
{
}
static const uint8_t HANDSHAKE_PAYLOAD[] = {0x13};
static inline EDolphinControllerType parseType(unsigned char status)
{
unsigned char type = status & (DOL_TYPE_NORMAL | DOL_TYPE_WAVEBIRD);
@ -61,77 +58,65 @@ parseState(SDolphinControllerState* stateOut, uint8_t* payload, bool& rumble)
void CDolphinSmashAdapter::transferCycle()
{
if (!m_didHandshake)
uint8_t payload[37];
size_t recvSz = receiveUSBInterruptTransfer(0, payload, sizeof(payload));
if (recvSz != 37 || payload[0] != 0x21)
return;
//printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
if (!m_callback)
return;
/* Parse controller states */
uint8_t* controller = &payload[1];
uint8_t rumbleMask = 0;
for (int i=0 ; i<4 ; i++, controller += 9)
{
if (!sendInterruptTransfer(0, HANDSHAKE_PAYLOAD, sizeof(HANDSHAKE_PAYLOAD)))
return;
//printf("SENT HANDSHAKE %d\n", res);
m_didHandshake = true;
SDolphinControllerState state;
bool rumble = false;
EDolphinControllerType type = parseState(&state, controller, rumble);
if (type && !(m_knownControllers & 1<<i))
{
m_knownControllers |= 1<<i;
m_callback->controllerConnected(i, type);
}
else if (!type && (m_knownControllers & 1<<i))
{
m_knownControllers &= ~(1<<i);
m_callback->controllerDisconnected(i, type);
}
if (m_knownControllers & 1<<i)
m_callback->controllerUpdate(i, type, state);
rumbleMask |= rumble ? 1<<i : 0;
}
else
/* Send rumble message (if needed) */
uint8_t rumbleReq = m_rumbleRequest & rumbleMask;
if (rumbleReq != m_rumbleState)
{
uint8_t payload[37];
size_t recvSz = receiveInterruptTransfer(0, payload, sizeof(payload));
if (recvSz != 37 || payload[0] != 0x21)
return;
//printf("RECEIVED DATA %zu %02X\n", recvSz, payload[0]);
if (!m_callback)
return;
/* Parse controller states */
uint8_t* controller = &payload[1];
uint8_t rumbleMask = 0;
for (int i=0 ; i<4 ; i++, controller += 9)
uint8_t rumbleMessage[5] = {0x11};
for (int i=0 ; i<4 ; ++i)
{
SDolphinControllerState state;
bool rumble = false;
EDolphinControllerType type = parseState(&state, controller, rumble);
if (type && !(m_knownControllers & 1<<i))
{
m_knownControllers |= 1<<i;
m_callback->controllerConnected(i, type);
}
else if (!type && (m_knownControllers & 1<<i))
{
m_knownControllers &= ~(1<<i);
m_callback->controllerDisconnected(i, type);
}
if (m_knownControllers & 1<<i)
m_callback->controllerUpdate(i, type, state);
rumbleMask |= rumble ? 1<<i : 0;
}
/* Send rumble message (if needed) */
uint8_t rumbleReq = m_rumbleRequest & rumbleMask;
if (rumbleReq != m_rumbleState)
{
uint8_t rumbleMessage[5] = {0x11};
for (int i=0 ; i<4 ; ++i)
{
if (rumbleReq & 1<<i)
rumbleMessage[i+1] = 1;
else
rumbleMessage[i+1] = 0;
}
sendInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
m_rumbleState = rumbleReq;
if (rumbleReq & 1<<i)
rumbleMessage[i+1] = 1;
else
rumbleMessage[i+1] = 0;
}
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
m_rumbleState = rumbleReq;
}
}
void CDolphinSmashAdapter::initialCycle()
{
uint8_t handshakePayload[] = {0x13};
sendUSBInterruptTransfer(0, handshakePayload, sizeof(handshakePayload));
}
void CDolphinSmashAdapter::finalCycle()
{
if (m_didHandshake)
{
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
sendInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
}
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
sendUSBInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
}
void CDolphinSmashAdapter::deviceDisconnected()

View File

@ -1 +1,23 @@
#include "inputdev/CGenericPad.hpp"
#include "inputdev/CDeviceToken.hpp"
namespace boo
{
CGenericPad::CGenericPad(CDeviceToken* token)
: CDeviceBase(token)
{
}
CGenericPad::~CGenericPad()
{
}
void CGenericPad::deviceDisconnected()
{
}
}

View File

@ -27,7 +27,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
std::thread* m_thread;
CFRunLoopRef m_runLoop = NULL;
bool _sendInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
{
if (m_usbIntf)
{
@ -37,7 +37,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
return false;
}
size_t _receiveInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
{
if (m_usbIntf)
{
@ -215,7 +215,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
m_runningTransferLoop = false;
}
bool _sendReport(const uint8_t* data, size_t length)
bool _sendHIDReport(const uint8_t* data, size_t length)
{
if (m_runLoop)
{
@ -226,7 +226,7 @@ class CHIDDeviceIOKit final : public IHIDDevice
public:
CHIDDeviceIOKit(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel)
CHIDDeviceIOKit(CDeviceToken& token, CDeviceBase& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
@ -252,9 +252,9 @@ public:
};
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel)
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp)
{
return new CHIDDeviceIOKit(token, devImp, lowLevel);
return new CHIDDeviceIOKit(token, devImp);
}
}

View File

@ -40,7 +40,7 @@ class CHIDDeviceUdev final : public IHIDDevice
std::condition_variable m_initCond;
std::thread* m_thread;
bool _sendInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)
{
if (m_devFd)
{
@ -59,7 +59,7 @@ class CHIDDeviceUdev final : public IHIDDevice
return false;
}
size_t _receiveInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)
{
if (m_devFd)
{
@ -75,15 +75,14 @@ class CHIDDeviceUdev final : public IHIDDevice
return 0;
}
static void _threadProcLL(CHIDDeviceUdev* device)
static void _threadProcUSBLL(CHIDDeviceUdev* device)
{
unsigned i;
std::unique_lock<std::mutex> lk(device->m_initMutex);
udev_device* hidDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
/* Get the HID element's parent (USB interrupt transfer-interface) */
udev_device* usbDev = udev_device_get_parent_with_subsystem_devtype(hidDev, "usb", "usb_device");
const char* dp = udev_device_get_devnode(usbDev);
const char* dp = udev_device_get_devnode(udevDev);
device->m_devFd = open(dp, O_RDWR);
if (device->m_devFd < 0)
{
@ -93,7 +92,7 @@ class CHIDDeviceUdev final : public IHIDDevice
device->m_devImp.deviceError(errStr);
lk.unlock();
device->m_initCond.notify_one();
udev_device_unref(hidDev);
udev_device_unref(udevDev);
return;
}
usb_device_descriptor devDesc = {0};
@ -147,13 +146,46 @@ class CHIDDeviceUdev final : public IHIDDevice
/* Cleanup */
close(device->m_devFd);
device->m_devFd = 0;
udev_device_unref(hidDev);
udev_device_unref(udevDev);
}
static void _threadProcHL(CHIDDeviceUdev* device)
{
static void _threadProcBTLL(CHIDDeviceUdev* device)
{
std::unique_lock<std::mutex> lk(device->m_initMutex);
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
/* Return control to main thread */
device->m_runningTransferLoop = true;
lk.unlock();
device->m_initCond.notify_one();
/* Start transfer loop */
device->m_devImp.initialCycle();
while (device->m_runningTransferLoop)
device->m_devImp.transferCycle();
device->m_devImp.finalCycle();
udev_device_unref(udevDev);
}
static void _threadProcHID(CHIDDeviceUdev* device)
{
std::unique_lock<std::mutex> lk(device->m_initMutex);
udev_device* udevDev = udev_device_new_from_syspath(GetUdev(), device->m_devPath.c_str());
/* Return control to main thread */
device->m_runningTransferLoop = true;
lk.unlock();
device->m_initCond.notify_one();
/* Start transfer loop */
device->m_devImp.initialCycle();
while (device->m_runningTransferLoop)
device->m_devImp.transferCycle();
device->m_devImp.finalCycle();
udev_device_unref(udevDev);
}
void _deviceDisconnected()
@ -161,24 +193,29 @@ class CHIDDeviceUdev final : public IHIDDevice
m_runningTransferLoop = false;
}
bool _sendReport(const uint8_t* data, size_t length)
bool _sendHIDReport(const uint8_t* data, size_t length)
{
return false;
}
public:
CHIDDeviceUdev(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel)
CHIDDeviceUdev(CDeviceToken& token, CDeviceBase& devImp)
: m_token(token),
m_devImp(devImp),
m_devPath(token.getDevicePath())
{
devImp.m_hidDev = this;
std::unique_lock<std::mutex> lk(m_initMutex);
if (lowLevel)
m_thread = new std::thread(_threadProcLL, this);
CDeviceToken::TDeviceType dType = token.getDeviceType();
if (dType == CDeviceToken::DEVTYPE_USB)
m_thread = new std::thread(_threadProcUSBLL, this);
else if (dType == CDeviceToken::DEVTYPE_BLUETOOTH)
m_thread = new std::thread(_threadProcBTLL, this);
else if (dType == CDeviceToken::DEVTYPE_GENERICHID)
m_thread = new std::thread(_threadProcHID, this);
else
m_thread = new std::thread(_threadProcHL, this);
throw std::runtime_error("invalid token supplied to device constructor");
m_initCond.wait(lk);
}
@ -192,9 +229,9 @@ public:
};
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel)
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp)
{
return new CHIDDeviceUdev(token, devImp, lowLevel);
return new CHIDDeviceUdev(token, devImp);
}
}

View File

@ -30,19 +30,33 @@ class CHIDListenerUdev final : public IHIDListener
if (!listener->m_scanningEnabled)
return;
/* Filter to USB/BT */
const char* dt = udev_device_get_devtype(device);
CDeviceToken::TDeviceType type;
if (!strcmp(dt, "usb_device"))
type = CDeviceToken::DEVTYPE_USB;
else if (!strcmp(dt, "bluetooth_device"))
type = CDeviceToken::DEVTYPE_BLUETOOTH;
else
return;
/* Prevent redundant registration */
const char* devPath = udev_device_get_syspath(device);
if (listener->m_finder._hasToken(devPath))
return;
udev_device* devCast =
udev_device_get_parent_with_subsystem_devtype(device, "bluetooth", "bluetooth_device");
if (!devCast)
devCast = udev_device_get_parent_with_subsystem_devtype(device, "usb", "usb_device");
if (!devCast)
return;
int vid = 0, pid = 0;
udev_list_entry* attrs = udev_device_get_properties_list_entry(devCast);
udev_list_entry* attrs = udev_device_get_properties_list_entry(device);
#if 0
udev_list_entry* att = NULL;
udev_list_entry_foreach(att, attrs)
{
const char* name = udev_list_entry_get_name(att);
const char* val = udev_list_entry_get_value(att);
fprintf(stderr, "%s %s\n", name, val);
}
fprintf(stderr, "\n\n");
#endif
udev_list_entry* vide = udev_list_entry_get_by_name(attrs, "ID_VENDOR_ID");
if (vide)
@ -62,7 +76,36 @@ class CHIDListenerUdev final : public IHIDListener
if (producte)
product = udev_list_entry_get_value(producte);
listener->m_finder._insertToken(CDeviceToken(vid, pid, manuf, product, devPath));
if (!listener->m_finder._insertToken(CDeviceToken(type, vid, pid, manuf, product, devPath)))
{
/* Matched-insertion failed; see if generic HID interface is available */
udev_list_entry* devInterfaces = NULL;
if (type == CDeviceToken::DEVTYPE_USB)
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_USB_INTERFACES");
else if (type == CDeviceToken::DEVTYPE_BLUETOOTH)
devInterfaces = udev_list_entry_get_by_name(attrs, "ID_BLUETOOTH_INTERFACES");
if (devInterfaces)
{
const char* interfacesStr = udev_list_entry_get_value(devInterfaces);
if (strstr(interfacesStr, ":030104") || /* HID / GenericDesktop / Joystick */
strstr(interfacesStr, ":030105")) /* HID / GenericDesktop / Gamepad */
{
udev_enumerate* hidEnum = udev_enumerate_new(UDEV_INST);
udev_enumerate_add_match_parent(hidEnum, device);
udev_enumerate_add_match_subsystem(hidEnum, "hid");
udev_enumerate_scan_devices(hidEnum);
udev_list_entry* hidEnt = udev_enumerate_get_list_entry(hidEnum);
if (hidEnt)
{
const char* hidPath = udev_list_entry_get_name(hidEnt);
if (!listener->m_finder._hasToken(hidPath))
listener->m_finder._insertToken(CDeviceToken(CDeviceToken::DEVTYPE_GENERICHID,
vid, pid, manuf, product, hidPath));
}
udev_enumerate_unref(hidEnum);
}
}
}
}
static void deviceDisconnected(CHIDListenerUdev* listener,
@ -87,13 +130,9 @@ class CHIDListenerUdev final : public IHIDListener
{
const char* action = udev_device_get_action(dev);
if (!strcmp(action, "add"))
{
deviceConnected(listener, dev);
}
else if (!strcmp(action, "remove"))
{
deviceDisconnected(listener, dev);
}
udev_device_unref(dev);
}
}
@ -108,7 +147,8 @@ public:
m_udevMon = udev_monitor_new_from_netlink(GetUdev(), "udev");
if (!m_udevMon)
throw std::runtime_error("unable to init udev_monitor");
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "hid", NULL);
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "usb", "usb_device");
udev_monitor_filter_add_match_subsystem_devtype(m_udevMon, "bluetooth", "bluetooth_device");
udev_monitor_filter_update(m_udevMon);
/* Initial HID Device Add */
@ -146,7 +186,10 @@ public:
bool scanNow()
{
udev_enumerate* uenum = udev_enumerate_new(GetUdev());
udev_enumerate_add_match_subsystem(uenum, "hid");
udev_enumerate_add_match_subsystem(uenum, "usb");
udev_enumerate_add_match_property(uenum, "DEVTYPE", "usb_device");
udev_enumerate_add_match_subsystem(uenum, "bluetooth");
udev_enumerate_add_match_property(uenum, "DEVTYPE", "bluetooth_device");
udev_enumerate_scan_devices(uenum);
udev_list_entry* uenumList = udev_enumerate_get_list_entry(uenum);
udev_list_entry* uenumItem;

View File

@ -10,9 +10,9 @@ class IHIDDevice
{
friend class CDeviceBase;
virtual void _deviceDisconnected()=0;
virtual bool _sendInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)=0;
virtual size_t _receiveInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)=0;
virtual bool _sendReport(const uint8_t* data, size_t length)=0;
virtual bool _sendUSBInterruptTransfer(uint8_t pipe, const uint8_t* data, size_t length)=0;
virtual size_t _receiveUSBInterruptTransfer(uint8_t pipe, uint8_t* data, size_t length)=0;
virtual bool _sendHIDReport(const uint8_t* data, size_t length)=0;
public:
inline virtual ~IHIDDevice() {};
};

View File

@ -1,5 +1,6 @@
#include "inputdev/SDeviceSignature.hpp"
#include "inputdev/CDeviceToken.hpp"
#include "inputdev/CGenericPad.hpp"
#include "IHIDDevice.hpp"
namespace boo
@ -10,6 +11,8 @@ extern const SDeviceSignature BOO_DEVICE_SIGS[];
bool SDeviceSignature::DeviceMatchToken(const CDeviceToken& token, const TDeviceSignatureSet& sigSet)
{
if (token.getDeviceType() == CDeviceToken::DEVTYPE_GENERICHID)
return true;
for (const SDeviceSignature* sig : sigSet)
{
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId())
@ -18,11 +21,29 @@ bool SDeviceSignature::DeviceMatchToken(const CDeviceToken& token, const TDevice
return false;
}
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel);
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp);
CDeviceBase* SDeviceSignature::DeviceNew(CDeviceToken& token)
{
CDeviceBase* retval = NULL;
/* Early-return for generic HID devices */
if (token.getDeviceType() == CDeviceToken::DEVTYPE_GENERICHID)
{
retval = new CGenericPad(&token);
if (!retval)
return NULL;
IHIDDevice* newDev = IHIDDeviceNew(token, *retval);
if (!newDev)
{
delete retval;
return NULL;
}
return retval;
}
/* Otherwise perform signature-matching to find the appropriate device-factory */
const SDeviceSignature* foundSig = NULL;
const SDeviceSignature* sigIter = BOO_DEVICE_SIGS;
unsigned targetVid = token.getVendorId();
@ -43,7 +64,7 @@ CDeviceBase* SDeviceSignature::DeviceNew(CDeviceToken& token)
if (!retval)
return NULL;
IHIDDevice* newDev = IHIDDeviceNew(token, *retval, foundSig->m_lowLevel);
IHIDDevice* newDev = IHIDDeviceNew(token, *retval);
if (!newDev)
{
delete retval;