Implement RemapButton feature

Many changes were made here, too many to list here.
This commit is contained in:
pixl
2020-07-05 02:55:46 -04:00
parent 0b87d3c664
commit 5bf5dc75b5
21 changed files with 765 additions and 104 deletions

View File

@@ -92,6 +92,7 @@ std::tuple<uint8_t, uint8_t> Device::version() const
void Device::_init()
{
_listening = false;
_supported_reports = getSupportedReports(_raw_device->reportDescriptor());
if(!_supported_reports)
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
@@ -127,7 +128,8 @@ void Device::_init()
Device::~Device()
{
_raw_device->removeEventHandler("DEV_" + std::to_string(_index));
if(_listening)
_raw_device->removeEventHandler("DEV_" + std::to_string(_index));
}
void Device::addEventHandler(const std::string& nickname,
@@ -144,6 +146,12 @@ void Device::removeEventHandler(const std::string& nickname)
_event_handlers.erase(nickname);
}
const std::map<std::string, std::shared_ptr<EventHandler>>&
Device::eventHandlers()
{
return _event_handlers;
}
void Device::handleEvent(Report& report)
{
for(auto& handler : _event_handlers)
@@ -192,31 +200,33 @@ uint16_t Device::pid() const
void Device::listen()
{
if(!_raw_device->isListening())
///TODO: Kill RawDevice?
thread::spawn({[raw=this->_raw_device]() {
raw->listen();
}});
// Pass all HID++ events with device index to this device.
std::shared_ptr<raw::RawEventHandler> handler;
handler->condition = [this](std::vector<uint8_t>& report)->bool
{
auto handler = std::make_shared<raw::RawEventHandler>();
handler->condition = [index=this->_index](std::vector<uint8_t>& report)
->bool {
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) &&
(report[Offset::DeviceIndex] == this->_index);
(report[Offset::DeviceIndex] == index);
};
handler->callback = [this](std::vector<uint8_t>& report)->void
{
handler->callback = [this](std::vector<uint8_t>& report)->void {
Report _report(report);
this->handleEvent(_report);
};
_raw_device->addEventHandler("DEV_" + std::to_string(_index), handler);
_listening = true;
}
void Device::stopListening()
{
_raw_device->removeEventHandler("DEV_" + std::to_string(_index));
if(_listening)
_raw_device->removeEventHandler("DEV_" + std::to_string(_index));
_listening = false;
if(!_raw_device->eventHandlers().empty())
_raw_device->stopListener();

View File

@@ -55,7 +55,7 @@ namespace hidpp
Asleep
};
InvalidDevice(Reason reason) : _reason (reason) {}
virtual const char *what() const noexcept;
virtual const char* what() const noexcept;
virtual Reason code() const noexcept;
private:
Reason _reason;
@@ -81,6 +81,8 @@ namespace hidpp
void addEventHandler(const std::string& nickname,
const std::shared_ptr<EventHandler>& handler);
void removeEventHandler(const std::string& nickname);
const std::map<std::string, std::shared_ptr<EventHandler>>&
eventHandlers();
Report sendReport(Report& report);
@@ -98,6 +100,8 @@ namespace hidpp
uint16_t _pid;
std::string _name;
std::atomic<bool> _listening;
std::map<std::string, std::shared_ptr<EventHandler>> _event_handlers;
};
} } }

View File

@@ -21,6 +21,8 @@
#define LOGID_HIDPP_SOFTWARE_ID 0
#include <cstdint>
namespace logid {
namespace backend {
namespace hidpp

View File

@@ -63,3 +63,8 @@ Feature::Feature(Device* dev, uint16_t _id) : _device (dev)
throw UnsupportedFeature(_id);
}
}
uint8_t Feature::featureIndex()
{
return _index;
}

View File

@@ -40,7 +40,7 @@ namespace hidpp20 {
public:
static const uint16_t ID;
virtual uint16_t getID() = 0;
uint8_t featureIndex();
protected:
explicit Feature(Device* dev, uint16_t _id);
std::vector<uint8_t> callFunction(uint8_t function_id,

View File

@@ -16,6 +16,7 @@
*
*/
#include <cassert>
#include "../Error.h"
#include "ReprogControls.h"
using namespace logid::backend::hidpp20;
@@ -30,7 +31,7 @@ x::x(Device* dev, uint16_t _id) : base(dev, _id) \
#define MAKE_REPROG(x, dev) \
try { \
return x(dev); \
return std::make_shared<x>(dev); \
} catch(UnsupportedFeature &e) {\
}
@@ -41,7 +42,7 @@ DEFINE_REPROG(ReprogControlsV2_2, ReprogControlsV2);
DEFINE_REPROG(ReprogControlsV3, ReprogControlsV2_2);
DEFINE_REPROG(ReprogControlsV4, ReprogControlsV3);
ReprogControls ReprogControls::autoVersion(Device *dev)
std::shared_ptr<ReprogControls> ReprogControls::autoVersion(Device *dev)
{
MAKE_REPROG(ReprogControlsV4, dev);
MAKE_REPROG(ReprogControlsV3, dev);
@@ -49,7 +50,7 @@ ReprogControls ReprogControls::autoVersion(Device *dev)
MAKE_REPROG(ReprogControlsV2, dev);
// If base version cannot be made, throw error
return ReprogControls(dev);
return std::make_shared<ReprogControls>(dev);
}
uint8_t ReprogControls::getControlCount()
@@ -78,29 +79,43 @@ ReprogControls::ControlInfo ReprogControls::getControlInfo(uint8_t index)
return info;
}
ReprogControls::ControlInfo ReprogControls::getControlIdInfo(uint16_t cid)
{
if(_cids.empty()) {
for(uint8_t i = 0; i < getControlCount(); i++) {
auto info = getControlInfo(i);
_cids.emplace(info.controlID, info);
}
}
auto it = _cids.find(cid);
if(it == _cids.end())
throw Error(Error::InvalidArgument);
else
return it->second;
}
ReprogControls::ControlInfo ReprogControls::getControlReporting(uint16_t cid)
{
std::vector<uint8_t> params(2);
ControlInfo info{};
params[0] = (cid >> 8) & 0xff;
params[1] = cid & 0xff;
auto response = callFunction(GetControlReporting, params);
// Emulate this function, only Reprog controls v4 supports this
auto info = getControlIdInfo(cid);
info.controlID = response[1];
info.controlID |= response[0] << 8;
info.flags = response[2];
return info;
ControlInfo report{};
report.controlID = cid;
report.flags = 0;
if(info.flags & TemporaryDivertable)
report.flags |= TemporaryDiverted;
if(info.flags & PersisentlyDivertable)
report.flags |= PersistentlyDiverted;
if(info.additionalFlags & RawXY)
report.flags |= RawXYDiverted;
return report;
}
void ReprogControls::setControlReporting(uint8_t cid, ControlInfo info)
{
std::vector<uint8_t> params(5);
params[0] = (cid >> 8) & 0xff;
params[1] = cid & 0xff;
params[2] = info.flags;
params[3] = (info.controlID >> 8) & 0xff;
params[4] = info.controlID & 0xff;
callFunction(SetControlReporting, params);
// This function does not exist pre-v4 and cannot be emulated, ignore.
}
std::set<uint16_t> ReprogControls::divertedButtonEvent(
@@ -131,3 +146,28 @@ ReprogControls::Move ReprogControls::divertedRawXYEvent(const hidpp::Report
move.y |= report.paramBegin()[2] << 8;
return move;
}
ReprogControls::ControlInfo ReprogControlsV4::getControlReporting(uint16_t cid)
{
std::vector<uint8_t> params(2);
ControlInfo info{};
params[0] = (cid >> 8) & 0xff;
params[1] = cid & 0xff;
auto response = callFunction(GetControlReporting, params);
info.controlID = response[1];
info.controlID |= response[0] << 8;
info.flags = response[2];
return info;
}
void ReprogControlsV4::setControlReporting(uint8_t cid, ControlInfo info)
{
std::vector<uint8_t> params(5);
params[0] = (cid >> 8) & 0xff;
params[1] = cid & 0xff;
params[2] = info.flags;
params[3] = (info.controlID >> 8) & 0xff;
params[4] = info.controlID & 0xff;
callFunction(SetControlReporting, params);
}

View File

@@ -18,6 +18,8 @@
#ifndef LOGID_BACKEND_HIDPP20_FEATURE_REPROGCONTROLS_H
#define LOGID_BACKEND_HIDPP20_FEATURE_REPROGCONTROLS_H
#include <map>
#include "../feature_defs.h"
#include "../Feature.h"
@@ -28,27 +30,17 @@ namespace hidpp20
class ReprogControls : public Feature
{
public:
static const uint16_t ID = FeatureID::REPROG_CONTROLS;
virtual uint16_t getID() { return ID; }
virtual bool supportsRawXY() { return false; }
enum Function {
GetControlCount = 0,
GetControlInfo = 1,
GetControlReporting = 2,
SetControlReporting = 3
};
enum Event {
DivertedButtonEvent = 0,
DivertedRawXYEvent = 1
};
explicit ReprogControls(Device* dev);
virtual uint8_t getControlCount();
struct ControlInfo
{
uint16_t controlID;
@@ -68,24 +60,41 @@ namespace hidpp20
FnToggle = 1<<3,
ReprogHint = 1<<4,
TemporaryDivertable = 1<<5,
PerisentlyDiverable = 1<<6,
PersisentlyDivertable = 1<<6,
Virtual = 1<<7
};
enum ControlInfoAdditionalFlags: uint8_t {
RawXY = 1<<0
};
virtual ControlInfo getControlInfo(uint8_t index);
enum ControlReportingFlags: uint8_t {
TemporaryDiverted = 1<<0,
ChangeTemporaryDivert = 1<<1,
PersistentDiverted = 1<<2,
PersistentlyDiverted = 1<<2,
ChangePersistentDivert = 1<<3,
RawXYDiverted = 1<<4,
ChangeRawXYDivert = 1<<5
};
struct Move
{
int16_t x;
int16_t y;
};
static const uint16_t ID = FeatureID::REPROG_CONTROLS;
virtual uint16_t getID() { return ID; }
virtual bool supportsRawXY() { return false; }
explicit ReprogControls(Device* dev);
virtual uint8_t getControlCount();
virtual ControlInfo getControlInfo(uint8_t cid);
virtual ControlInfo getControlIdInfo(uint16_t cid);
// Onlu controlId and flags will be set
virtual ControlInfo getControlReporting(uint16_t cid);
@@ -95,24 +104,19 @@ namespace hidpp20
static std::set<uint16_t> divertedButtonEvent(const hidpp::Report&
report);
struct Move
{
int16_t x;
int16_t y;
};
static Move divertedRawXYEvent(const hidpp::Report& report);
static ReprogControls autoVersion(Device *dev);
static std::shared_ptr<ReprogControls> autoVersion(Device *dev);
protected:
ReprogControls(Device* dev, uint16_t _id);
std::map<uint16_t, ControlInfo> _cids;
};
class ReprogControlsV2 : public ReprogControls
{
public:
static const uint16_t ID = FeatureID::REPROG_CONTROLS_V2;
uint16_t getID() override { return ID; }
virtual uint16_t getID() { return ID; }
explicit ReprogControlsV2(Device* dev);
protected:
@@ -123,7 +127,7 @@ namespace hidpp20
{
public:
static const uint16_t ID = FeatureID::REPROG_CONTROLS_V2_2;
uint16_t getID() override { return ID; }
virtual uint16_t getID() { return ID; }
explicit ReprogControlsV2_2(Device* dev);
protected:
@@ -134,7 +138,7 @@ namespace hidpp20
{
public:
static const uint16_t ID = FeatureID::REPROG_CONTROLS_V3;
uint16_t getID() override { return ID; }
virtual uint16_t getID() { return ID; }
explicit ReprogControlsV3(Device* dev);
protected:
@@ -145,10 +149,14 @@ namespace hidpp20
{
public:
static const uint16_t ID = FeatureID::REPROG_CONTROLS_V4;
uint16_t getID() override { return ID; }
virtual uint16_t getID() { return ID; }
bool supportsRawXY() override { return true; }
ControlInfo getControlReporting(uint16_t cid) override;
void setControlReporting(uint8_t cid, ControlInfo info) override;
explicit ReprogControlsV4(Device* dev);
protected:
ReprogControlsV4(Device* dev, uint16_t _id);

View File

@@ -354,6 +354,7 @@ void RawDevice::addEventHandler(const std::string& nickname,
{
auto it = _event_handlers.find(nickname);
assert(it == _event_handlers.end());
assert(handler);
_event_handlers.emplace(nickname, handler);
}