mirror of https://github.com/AxioDL/boo.git
much better input-device class registration
This commit is contained in:
parent
d4b1211c24
commit
4b8651b844
|
@ -0,0 +1,13 @@
|
|||
#include "inputdev/SDeviceSignature.hpp"
|
||||
#include "inputdev/CDolphinSmashAdapter.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
const SDeviceSignature BOO_DEVICE_SIGS[] =
|
||||
{
|
||||
DEVICE_SIG(CDolphinSmashAdapter, 0x57e, 0x337, true),
|
||||
DEVICE_SIG_SENTINEL()
|
||||
};
|
||||
|
||||
}
|
|
@ -11,11 +11,12 @@ namespace boo {typedef CCGLContext CGraphicsContext;}
|
|||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#include "x11/CGLXContext.hpp"
|
||||
namespace boo {typedef boo::CGLXContext CGraphicsContext;}
|
||||
namespace boo {typedef CGLXContext CGraphicsContext;}
|
||||
|
||||
#endif
|
||||
|
||||
#include "IGraphicsContext.hpp"
|
||||
#include "inputdev/CDeviceFinder.hpp"
|
||||
#include "inputdev/CDolphinSmashAdapter.hpp"
|
||||
|
||||
#endif // BOO_HPP
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
@ -23,16 +24,18 @@ public:
|
|||
virtual ~CDeviceBase();
|
||||
void closeDevice();
|
||||
virtual void deviceDisconnected()=0;
|
||||
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);
|
||||
virtual void transferCycle() {};
|
||||
virtual void finalCycle() {};
|
||||
virtual void initialCycle() {}
|
||||
virtual void transferCycle() {}
|
||||
virtual void finalCycle() {}
|
||||
|
||||
/* High-Level API */
|
||||
bool sendReport(const uint8_t* data, size_t length);
|
||||
virtual size_t receiveReport(uint8_t* data, size_t length) {};
|
||||
virtual size_t receiveReport(uint8_t* data, size_t length) {return 0;}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include <stdexcept>
|
||||
#include "CDeviceToken.hpp"
|
||||
#include "IHIDListener.hpp"
|
||||
#include "DeviceClasses.hpp"
|
||||
#include "SDeviceSignature.hpp"
|
||||
#include <string.h>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
@ -24,7 +25,7 @@ public:
|
|||
private:
|
||||
|
||||
/* Types this finder is interested in (immutable) */
|
||||
EDeviceMask m_types;
|
||||
SDeviceSignature::TDeviceSignatureSet m_types;
|
||||
|
||||
/* Platform-specific USB event registration
|
||||
* (for auto-scanning, NULL if not registered) */
|
||||
|
@ -45,9 +46,10 @@ private:
|
|||
}
|
||||
inline void _insertToken(CDeviceToken&& token)
|
||||
{
|
||||
if (BooDeviceMatchToken(token, m_types)) {
|
||||
if (SDeviceSignature::DeviceMatchToken(token, m_types)) {
|
||||
m_tokensLock.lock();
|
||||
TInsertedDeviceToken inseredTok = m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
|
||||
TInsertedDeviceToken inseredTok =
|
||||
m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
|
||||
m_tokensLock.unlock();
|
||||
deviceConnected(inseredTok.first->second);
|
||||
}
|
||||
|
@ -81,12 +83,22 @@ public:
|
|||
};
|
||||
|
||||
/* Application must specify its interested device-types */
|
||||
CDeviceFinder(EDeviceMask types)
|
||||
: m_types(types), m_listener(NULL)
|
||||
CDeviceFinder(std::vector<const char*> types)
|
||||
: m_listener(NULL)
|
||||
{
|
||||
if (skDevFinder)
|
||||
throw std::runtime_error("only one instance of CDeviceFinder may be constructed");
|
||||
skDevFinder = this;
|
||||
for (const char* typeName : types)
|
||||
{
|
||||
const SDeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
||||
while (sigIter->m_name)
|
||||
{
|
||||
if (!strcmp(sigIter->m_name, typeName))
|
||||
m_types.push_back(sigIter);
|
||||
++sigIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
~CDeviceFinder()
|
||||
{
|
||||
|
@ -97,7 +109,7 @@ public:
|
|||
}
|
||||
|
||||
/* Get interested device-type mask */
|
||||
inline EDeviceMask getTypes() const {return m_types;}
|
||||
inline const SDeviceSignature::TDeviceSignatureSet& getTypes() const {return m_types;}
|
||||
|
||||
/* Iterable set of tokens */
|
||||
inline CDeviceTokensHandle getTokens() {return CDeviceTokensHandle(*this);}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <string>
|
||||
#include "CDeviceBase.hpp"
|
||||
#include "DeviceClasses.hpp"
|
||||
#include "SDeviceSignature.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
@ -48,7 +48,7 @@ public:
|
|||
inline CDeviceBase* openAndGetDevice()
|
||||
{
|
||||
if (!m_connectedDev)
|
||||
m_connectedDev = BooDeviceNew(*this);
|
||||
m_connectedDev = SDeviceSignature::DeviceNew(*this);
|
||||
return m_connectedDev;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class CDolphinSmashAdapter final : public CDeviceBase
|
|||
uint8_t m_rumbleState;
|
||||
bool m_didHandshake;
|
||||
void deviceDisconnected();
|
||||
void initialCycle();
|
||||
void transferCycle();
|
||||
void finalCycle();
|
||||
public:
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef CDEVICECLASSES_HPP
|
||||
#define CDEVICECLASSES_HPP
|
||||
|
||||
#include "CDolphinSmashAdapter.hpp"
|
||||
#include "CRevolutionPad.hpp"
|
||||
#include "CCafeProPad.hpp"
|
||||
#include "CDualshockPad.hpp"
|
||||
#include "CGenericPad.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
#define VID_NINTENDO 0x57e
|
||||
#define PID_SMASH_ADAPTER 0x337
|
||||
|
||||
enum EDeviceMask
|
||||
{
|
||||
DEV_NONE = 0,
|
||||
DEV_DOL_SMASH_ADAPTER = 1<<0,
|
||||
DEV_RVL_PAD = 1<<1,
|
||||
DEV_CAFE_PRO_PAD = 1<<2,
|
||||
DEV_DUALSHOCK_PAD = 1<<3,
|
||||
DEV_GENERIC_PAD = 1<<4,
|
||||
DEV_ALL = 0xff
|
||||
};
|
||||
|
||||
bool BooDeviceMatchToken(const CDeviceToken& token, EDeviceMask mask);
|
||||
CDeviceBase* BooDeviceNew(CDeviceToken& token);
|
||||
|
||||
}
|
||||
|
||||
#endif // CDEVICECLASSES_HPP
|
|
@ -15,7 +15,7 @@ class CDeviceFinder;
|
|||
class IHIDListener
|
||||
{
|
||||
public:
|
||||
virtual ~IHIDListener() {};
|
||||
virtual ~IHIDListener() {}
|
||||
|
||||
/* Automatic device scanning */
|
||||
virtual bool startScanning()=0;
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef SDeviceSignature_HPP
|
||||
#define SDeviceSignature_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
class CDeviceToken;
|
||||
class CDeviceBase;
|
||||
|
||||
struct SDeviceSignature
|
||||
{
|
||||
typedef std::vector<const SDeviceSignature*> TDeviceSignatureSet;
|
||||
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) {}
|
||||
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_SENTINEL() SDeviceSignature()
|
||||
|
||||
extern const SDeviceSignature BOO_DEVICE_SIGS[];
|
||||
|
||||
}
|
||||
|
||||
#endif // SDeviceSignature_HPP
|
||||
|
|
@ -15,9 +15,9 @@ HEADERS += \
|
|||
$$PWD/include/inputdev/CDeviceFinder.hpp \
|
||||
$$PWD/include/inputdev/CDeviceToken.hpp \
|
||||
$$PWD/include/inputdev/CDeviceBase.hpp \
|
||||
$$PWD/include/inputdev/DeviceClasses.hpp \
|
||||
$$PWD/include/inputdev/IHIDListener.hpp \
|
||||
$$PWD/src/inputdev/IHIDDevice.hpp
|
||||
$$PWD/src/inputdev/IHIDDevice.hpp \
|
||||
$$PWD/include/inputdev/SDeviceSignature.hpp
|
||||
|
||||
unix:!macx:HEADERS += \
|
||||
$$PWD/include/x11/CGLXContext.hpp
|
||||
|
@ -29,6 +29,7 @@ win32:HEADERS += \
|
|||
$$PWD/include/win/CWGLContext.hpp
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/InputDeviceClasses.cpp \
|
||||
$$PWD/src/CSurface.cpp \
|
||||
$$PWD/src/CRetraceWaiter.cpp \
|
||||
$$PWD/src/CInputRelay.cpp \
|
||||
|
@ -39,9 +40,9 @@ SOURCES += \
|
|||
$$PWD/src/inputdev/CDualshockPad.cpp \
|
||||
$$PWD/src/inputdev/CGenericPad.cpp \
|
||||
$$PWD/src/inputdev/CDeviceBase.cpp \
|
||||
$$PWD/src/inputdev/DeviceClasses.cpp \
|
||||
$$PWD/src/inputdev/CHIDListenerUdev.cpp \
|
||||
$$PWD/src/inputdev/CHIDDeviceUdev.cpp
|
||||
$$PWD/src/inputdev/CHIDDeviceUdev.cpp \
|
||||
$$PWD/src/inputdev/SDeviceSignature.cpp
|
||||
|
||||
unix:!macx:SOURCES += \
|
||||
$$PWD/src/x11/CGLXContext.cpp
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
CONFIG -= Qt
|
||||
#QMAKE_CXXFLAGS -= -std=c++0x
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
CONFIG += c++11
|
||||
QMAKE_CXXFLAGS += -stdlib=libc++
|
||||
LIBS += -std=c++11 -stdlib=libc++ -lc++abi
|
||||
|
||||
#unix:!macx:CONFIG += link_pkgconfig
|
||||
#unix:!macx:PKGCONFIG += x11
|
||||
|
|
|
@ -118,7 +118,12 @@ void CDolphinSmashAdapter::transferCycle()
|
|||
m_rumbleState = rumbleReq;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void CDolphinSmashAdapter::initialCycle()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDolphinSmashAdapter::finalCycle()
|
||||
{
|
||||
|
@ -127,7 +132,7 @@ void CDolphinSmashAdapter::finalCycle()
|
|||
uint8_t rumbleMessage[5] = {0x11, 0, 0, 0, 0};
|
||||
sendInterruptTransfer(0, rumbleMessage, sizeof(rumbleMessage));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void CDolphinSmashAdapter::deviceDisconnected()
|
||||
{
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#define MAX_REPORT_SIZE 65536
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
class CHIDDeviceIOKit final : public IHIDDevice
|
||||
{
|
||||
CDeviceToken& m_token;
|
||||
|
@ -253,3 +256,5 @@ IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLeve
|
|||
{
|
||||
return new CHIDDeviceIOKit(token, devImp, lowLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
namespace boo
|
||||
{
|
||||
|
||||
udev* BooGetUdev();
|
||||
udev* GetUdev();
|
||||
|
||||
#define MAX_REPORT_SIZE 65536
|
||||
|
||||
|
@ -52,7 +52,7 @@ class CHIDDeviceUdev final : public IHIDDevice
|
|||
(void*)data
|
||||
};
|
||||
int ret = ioctl(m_devFd, USBDEVFS_BULK, &xfer);
|
||||
if (ret != length)
|
||||
if (ret != (int)length)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -79,12 +79,23 @@ class CHIDDeviceUdev final : public IHIDDevice
|
|||
{
|
||||
unsigned i;
|
||||
std::unique_lock<std::mutex> lk(device->m_initMutex);
|
||||
udev_device* hidDev = udev_device_new_from_syspath(BooGetUdev(), device->m_devPath.c_str());
|
||||
udev_device* hidDev = 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);
|
||||
device->m_devFd = open(dp, O_RDONLY);
|
||||
device->m_devFd = open(dp, O_RDWR);
|
||||
if (device->m_devFd < 0)
|
||||
{
|
||||
char errStr[256];
|
||||
snprintf(errStr, 256, "Unable to open %s@%s: %s\n",
|
||||
device->m_token.getProductName().c_str(), dp, strerror(errno));
|
||||
device->m_devImp.deviceError(errStr);
|
||||
lk.unlock();
|
||||
device->m_initCond.notify_one();
|
||||
udev_device_unref(hidDev);
|
||||
return;
|
||||
}
|
||||
usb_device_descriptor devDesc = {0};
|
||||
read(device->m_devFd, &devDesc, 1);
|
||||
read(device->m_devFd, &devDesc.bDescriptorType, devDesc.bLength-1);
|
||||
|
@ -128,13 +139,14 @@ class CHIDDeviceUdev final : public IHIDDevice
|
|||
device->m_initCond.notify_one();
|
||||
|
||||
/* Start transfer loop */
|
||||
device->m_devImp.initialCycle();
|
||||
while (device->m_runningTransferLoop)
|
||||
device->m_devImp.transferCycle();
|
||||
device->m_devImp.finalCycle();
|
||||
|
||||
/* Cleanup */
|
||||
close(device->m_devFd);
|
||||
device->m_devFd = NULL;
|
||||
device->m_devFd = 0;
|
||||
udev_device_unref(hidDev);
|
||||
|
||||
}
|
||||
|
@ -173,7 +185,7 @@ public:
|
|||
~CHIDDeviceUdev()
|
||||
{
|
||||
m_runningTransferLoop = false;
|
||||
m_thread->detach();
|
||||
m_thread->join();
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include <IOKit/usb/IOUSBLib.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
/*
|
||||
* Reference: http://oroboro.com/usb-serial-number-osx/
|
||||
*/
|
||||
|
@ -286,3 +289,4 @@ IHIDListener* IHIDListenerNew(CDeviceFinder& finder)
|
|||
return new CHIDListenerIOKit(finder);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace boo
|
|||
{
|
||||
|
||||
static udev* UDEV_INST = NULL;
|
||||
udev* BooGetUdev()
|
||||
udev* GetUdev()
|
||||
{
|
||||
if (!UDEV_INST)
|
||||
UDEV_INST = udev_new();
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
{
|
||||
|
||||
/* Setup hotplug events */
|
||||
m_udevMon = udev_monitor_new_from_netlink(BooGetUdev(), "udev");
|
||||
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);
|
||||
|
@ -145,7 +145,7 @@ public:
|
|||
/* Manual device scanning */
|
||||
bool scanNow()
|
||||
{
|
||||
udev_enumerate* uenum = udev_enumerate_new(BooGetUdev());
|
||||
udev_enumerate* uenum = udev_enumerate_new(GetUdev());
|
||||
udev_enumerate_add_match_subsystem(uenum, "hid");
|
||||
udev_enumerate_scan_devices(uenum);
|
||||
udev_list_entry* uenumList = udev_enumerate_get_list_entry(uenum);
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#include "inputdev/DeviceClasses.hpp"
|
||||
#include "inputdev/CDeviceToken.hpp"
|
||||
#include "IHIDDevice.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
bool BooDeviceMatchToken(const CDeviceToken& token, EDeviceMask mask)
|
||||
{
|
||||
if (mask & DEV_DOL_SMASH_ADAPTER &&
|
||||
token.getVendorId() == VID_NINTENDO && token.getProductId() == PID_SMASH_ADAPTER)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel);
|
||||
CDeviceBase* BooDeviceNew(CDeviceToken& token)
|
||||
{
|
||||
|
||||
CDeviceBase* retval = NULL;
|
||||
bool lowLevel = false;
|
||||
|
||||
if (token.getVendorId() == VID_NINTENDO && token.getProductId() == PID_SMASH_ADAPTER)
|
||||
{
|
||||
retval = new CDolphinSmashAdapter(&token);
|
||||
lowLevel = true;
|
||||
}
|
||||
|
||||
if (!retval)
|
||||
return NULL;
|
||||
|
||||
IHIDDevice* newDev = IHIDDeviceNew(token, *retval, lowLevel);
|
||||
if (!newDev)
|
||||
{
|
||||
delete retval;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
#include "inputdev/SDeviceSignature.hpp"
|
||||
#include "inputdev/CDeviceToken.hpp"
|
||||
#include "IHIDDevice.hpp"
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
extern const SDeviceSignature BOO_DEVICE_SIGS[];
|
||||
|
||||
|
||||
bool SDeviceSignature::DeviceMatchToken(const CDeviceToken& token, const TDeviceSignatureSet& sigSet)
|
||||
{
|
||||
for (const SDeviceSignature* sig : sigSet)
|
||||
{
|
||||
if (sig->m_vid == token.getVendorId() && sig->m_pid == token.getProductId())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IHIDDevice* IHIDDeviceNew(CDeviceToken& token, CDeviceBase& devImp, bool lowLevel);
|
||||
CDeviceBase* SDeviceSignature::DeviceNew(CDeviceToken& token)
|
||||
{
|
||||
|
||||
CDeviceBase* retval = NULL;
|
||||
const SDeviceSignature* foundSig = NULL;
|
||||
const SDeviceSignature* sigIter = BOO_DEVICE_SIGS;
|
||||
unsigned targetVid = token.getVendorId();
|
||||
unsigned targetPid = token.getProductId();
|
||||
while (sigIter->m_name)
|
||||
{
|
||||
if (sigIter->m_vid == targetVid && sigIter->m_pid == targetPid)
|
||||
{
|
||||
foundSig = sigIter;
|
||||
break;
|
||||
}
|
||||
++sigIter;
|
||||
}
|
||||
if (!foundSig)
|
||||
return NULL;
|
||||
|
||||
retval = foundSig->m_factory(&token);
|
||||
if (!retval)
|
||||
return NULL;
|
||||
|
||||
IHIDDevice* newDev = IHIDDeviceNew(token, *retval, foundSig->m_lowLevel);
|
||||
if (!newDev)
|
||||
{
|
||||
delete retval;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -33,7 +33,7 @@ class CTestDeviceFinder : public CDeviceFinder
|
|||
CDolphinSmashAdapterCallback m_cb;
|
||||
public:
|
||||
CTestDeviceFinder()
|
||||
: CDeviceFinder(DEV_DOL_SMASH_ADAPTER)
|
||||
: CDeviceFinder({"CDolphinSmashAdapter"})
|
||||
{}
|
||||
void deviceConnected(CDeviceToken& tok)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue