IOKit input refactor

This commit is contained in:
Jack Andersen
2017-05-07 11:24:00 -10:00
parent 12bbf540fd
commit 62443b59e7
18 changed files with 798 additions and 220 deletions

View File

@@ -4,39 +4,50 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "../System.hpp"
#include <memory>
namespace boo
{
class DeviceToken;
class IHIDDevice;
class DeviceBase
enum class HIDReportType
{
Input,
Output,
Feature
};
class DeviceBase : public std::enable_shared_from_this<DeviceBase>
{
friend class DeviceToken;
friend class HIDDeviceIOKit;
friend class HIDDeviceUdev;
friend class HIDDeviceWinUSB;
friend struct DeviceSignature;
class DeviceToken* m_token;
class IHIDDevice* m_hidDev;
std::unique_ptr<IHIDDevice> m_hidDev;
void _deviceDisconnected();
public:
DeviceBase(DeviceToken* token);
virtual ~DeviceBase();
void closeDevice();
/* Callbacks */
virtual void deviceDisconnected()=0;
virtual void deviceError(const char* error, ...);
/* Low-Level API */
bool sendUSBInterruptTransfer(const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length);
virtual void initialCycle() {}
virtual void transferCycle() {}
virtual void finalCycle() {}
virtual size_t getInputBufferSize() const { return 0; }
/* Low-Level API */
bool sendUSBInterruptTransfer(const uint8_t* data, size_t length);
size_t receiveUSBInterruptTransfer(uint8_t* data, size_t length);
/* High-Level API */
bool sendHIDReport(const uint8_t* data, size_t length, uint16_t message=0);
virtual size_t receiveReport(uint8_t* data, size_t length, uint16_t message=0);
bool sendHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message=0);
size_t receiveHIDReport(uint8_t* data, size_t length, HIDReportType tp, uint32_t message=0); // Prefer callback version
virtual void receivedHIDReport(const uint8_t* /*data*/, size_t /*length*/, HIDReportType /*tp*/, uint32_t /*message*/) {}
};
}

View File

@@ -52,15 +52,15 @@ private:
return true;
return false;
}
inline bool _insertToken(DeviceToken&& token)
inline bool _insertToken(std::unique_ptr<DeviceToken>&& token)
{
if (DeviceSignature::DeviceMatchToken(token, m_types))
if (DeviceSignature::DeviceMatchToken(*token, m_types))
{
m_tokensLock.lock();
TInsertedDeviceToken inseredTok =
m_tokens.insert(std::make_pair(token.getDevicePath(), std::move(token)));
m_tokens.insert(std::make_pair(token->getDevicePath(), std::move(token)));
m_tokensLock.unlock();
deviceConnected(inseredTok.first->second);
deviceConnected(*inseredTok.first->second);
return true;
}
return false;
@@ -70,10 +70,10 @@ private:
auto preCheck = m_tokens.find(path);
if (preCheck != m_tokens.end())
{
DeviceToken& tok = preCheck->second;
DeviceBase* dev = tok.m_connectedDev;
DeviceToken& tok = *preCheck->second;
std::shared_ptr<DeviceBase> dev = tok.m_connectedDev;
tok._deviceClose();
deviceDisconnected(tok, dev);
deviceDisconnected(tok, dev.get());
m_tokensLock.lock();
m_tokens.erase(preCheck);
m_tokensLock.unlock();

View File

@@ -8,26 +8,38 @@
namespace boo
{
enum class DeviceType
{
None = 0,
USB = 1,
Bluetooth = 2,
HID = 3
};
class DeviceToken;
class DeviceBase;
struct DeviceSignature
{
typedef std::vector<const DeviceSignature*> TDeviceSignatureSet;
typedef std::function<DeviceBase*(DeviceToken*)> TFactoryLambda;
typedef std::function<std::shared_ptr<DeviceBase>(DeviceToken*)> TFactoryLambda;
const char* m_name;
std::type_index m_typeIdx;
unsigned m_vid, m_pid;
TFactoryLambda m_factory;
DeviceType m_type;
DeviceSignature() : m_name(NULL), m_typeIdx(typeid(DeviceSignature)) {} /* Sentinel constructor */
DeviceSignature(const char* name, std::type_index&& typeIdx, unsigned vid, unsigned pid, TFactoryLambda&& factory)
: m_name(name), m_typeIdx(typeIdx), m_vid(vid), m_pid(pid), m_factory(factory) {}
DeviceSignature(const char* name, std::type_index&& typeIdx, unsigned vid, unsigned pid,
TFactoryLambda&& factory, DeviceType type=DeviceType::None)
: m_name(name), m_typeIdx(typeIdx), m_vid(vid), m_pid(pid),
m_factory(factory), m_type(type) {}
static bool DeviceMatchToken(const DeviceToken& token, const TDeviceSignatureSet& sigSet);
static DeviceBase* DeviceNew(DeviceToken& token);
static std::shared_ptr<DeviceBase> DeviceNew(DeviceToken& token);
};
#define DEVICE_SIG(name, vid, pid) \
DeviceSignature(#name, typeid(name), vid, pid, [](DeviceToken* tok) -> DeviceBase* {return new name(tok);})
#define DEVICE_SIG(name, vid, pid, type) \
DeviceSignature(#name, typeid(name), vid, pid,\
[](DeviceToken* tok) -> std::shared_ptr<DeviceBase> {return std::make_shared<name>(tok);}, type)
#define DEVICE_SIG_SENTINEL() DeviceSignature()
extern const DeviceSignature BOO_DEVICE_SIGS[];

View File

@@ -10,16 +10,7 @@ namespace boo
class DeviceToken
{
public:
enum class DeviceType
{
None = 0,
USB = 1,
Bluetooth = 2,
GenericHID = 3
};
private:
friend struct DeviceSignature;
DeviceType m_devType;
unsigned m_vendorId;
unsigned m_productId;
@@ -28,7 +19,7 @@ private:
std::string m_devPath;
friend class DeviceBase;
DeviceBase* m_connectedDev;
std::shared_ptr<DeviceBase> m_connectedDev;
friend class DeviceFinder;
inline void _deviceClose()
@@ -70,7 +61,7 @@ public:
inline const std::string& getProductName() const {return m_productName;}
inline const std::string& getDevicePath() const {return m_devPath;}
inline bool isDeviceOpen() const {return (m_connectedDev != NULL);}
inline DeviceBase* openAndGetDevice()
inline std::shared_ptr<DeviceBase> openAndGetDevice()
{
if (!m_connectedDev)
m_connectedDev = DeviceSignature::DeviceNew(*this);

View File

@@ -3,6 +3,7 @@
#include <stdint.h>
#include "DeviceBase.hpp"
#include "../System.hpp"
namespace boo
{

View File

@@ -1,8 +1,40 @@
#ifndef CDUALSHOCKPAD_HPP
#define CDUALSHOCKPAD_HPP
#include <stdint.h>
#include <type_traits>
#include "DeviceBase.hpp"
#ifndef ENABLE_BITWISE_ENUM
#define ENABLE_BITWISE_ENUM(type)\
constexpr type operator|(type a, type b)\
{\
using T = std::underlying_type_t<type>;\
return type(static_cast<T>(a) | static_cast<T>(b));\
}\
constexpr type operator&(type a, type b)\
{\
using T = std::underlying_type_t<type>;\
return type(static_cast<T>(a) & static_cast<T>(b));\
}\
inline type& operator|=(type& a, const type& b)\
{\
using T = std::underlying_type_t<type>;\
a = type(static_cast<T>(a) | static_cast<T>(b));\
return a;\
}\
inline type& operator&=(type& a, const type& b)\
{\
using T = std::underlying_type_t<type>;\
a = type(static_cast<T>(a) & static_cast<T>(b));\
return a;\
}\
inline type operator~(const type& key)\
{\
using T = std::underlying_type_t<type>;\
return type(~static_cast<T>(key));\
}
#endif
namespace boo
{
@@ -134,6 +166,7 @@ class DualshockPad final : public DeviceBase
void initialCycle();
void transferCycle();
void finalCycle();
void receivedHIDReport(const uint8_t* data, size_t length, HIDReportType tp, uint32_t message);
public:
DualshockPad(DeviceToken* token);
~DualshockPad();
@@ -179,8 +212,10 @@ public:
void setRawLED(int led)
{
m_report.leds = led;
sendHIDReport(m_report.buf, sizeof(m_report), 0x0201);
sendHIDReport(m_report.buf, sizeof(m_report), HIDReportType::Output, 0x0201);
}
size_t getInputBufferSize() const { return 49; }
};
}

View File

@@ -8,7 +8,7 @@
namespace boo
{
typedef std::unordered_map<std::string, DeviceToken> TDeviceTokens;
typedef std::unordered_map<std::string, std::unique_ptr<DeviceToken>> TDeviceTokens;
typedef std::pair<TDeviceTokens::iterator, bool> TInsertedDeviceToken;
class DeviceFinder;