Implement receiver HID++ connect/disconnect events
Many changes were made here but that was the biggest one. There's currently a bug where std::system_error: Broken pipe is thrown after launching the daemon with a receiver connector. A workaround for this bug is to simply shake the mouse while starting the daemon. I will investigate this soon.
This commit is contained in:
44
src/logid/backend/hidpp20/EssentialFeature.cpp
Normal file
44
src/logid/backend/hidpp20/EssentialFeature.cpp
Normal file
@@ -0,0 +1,44 @@
|
||||
#include <cassert>
|
||||
#include "EssentialFeature.h"
|
||||
#include "feature_defs.h"
|
||||
#include "features/Root.h"
|
||||
|
||||
using namespace logid::backend::hidpp20;
|
||||
|
||||
std::vector<uint8_t> EssentialFeature::callFunction(uint8_t function_id,
|
||||
std::vector<uint8_t>& params)
|
||||
{
|
||||
hidpp::Report::Type type;
|
||||
|
||||
assert(params.size() <= hidpp::LongParamLength);
|
||||
if(params.size() <= hidpp::ShortParamLength)
|
||||
type = hidpp::Report::Type::Short;
|
||||
else if(params.size() <= hidpp::LongParamLength)
|
||||
type = hidpp::Report::Type::Long;
|
||||
|
||||
hidpp::Report request(type, _device->deviceIndex(), _index, function_id,
|
||||
LOGID_HIDPP_SOFTWARE_ID);
|
||||
std::copy(params.begin(), params.end(), request.paramBegin());
|
||||
|
||||
auto response = _device->sendReport(request);
|
||||
return std::vector<uint8_t>(response.paramBegin(), response.paramEnd());
|
||||
}
|
||||
|
||||
EssentialFeature::EssentialFeature(hidpp::Device* dev, uint16_t _id) :
|
||||
_device (dev)
|
||||
{
|
||||
_index = hidpp20::FeatureID::ROOT;
|
||||
|
||||
if(_id)
|
||||
{
|
||||
std::vector<uint8_t> getFunc_req(2);
|
||||
getFunc_req[0] = (_id >> 8) & 0xff;
|
||||
getFunc_req[1] = _id & 0xff;
|
||||
auto getFunc_resp = this->callFunction(Root::GetFeature, getFunc_req);
|
||||
_index = getFunc_resp[0];
|
||||
|
||||
// 0 if not found
|
||||
if(!_index)
|
||||
throw UnsupportedFeature(_id);
|
||||
}
|
||||
}
|
32
src/logid/backend/hidpp20/EssentialFeature.h
Normal file
32
src/logid/backend/hidpp20/EssentialFeature.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef LOGID_HIDPP20_ESSENTIAL_FEATURE_H
|
||||
#define LOGID_HIDPP20_ESSENTIAL_FEATURE_H
|
||||
|
||||
// WARNING: UNSAFE
|
||||
|
||||
/* This class is only meant to provide essential HID++ 2.0 features to the
|
||||
* hidpp::Device class. No version checks are provided here
|
||||
*/
|
||||
|
||||
#include "Device.h"
|
||||
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace hidpp20
|
||||
{
|
||||
class EssentialFeature
|
||||
{
|
||||
public:
|
||||
static const uint16_t ID;
|
||||
virtual uint16_t getID() = 0;
|
||||
|
||||
protected:
|
||||
EssentialFeature(hidpp::Device* dev, uint16_t _id);
|
||||
std::vector<uint8_t> callFunction(uint8_t function_id,
|
||||
std::vector<uint8_t>& params);
|
||||
private:
|
||||
hidpp::Device* _device;
|
||||
uint8_t _index;
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif //LOGID_HIDPP20_ESSENTIAL_FEATURE_H
|
68
src/logid/backend/hidpp20/features/DeviceName.cpp
Normal file
68
src/logid/backend/hidpp20/features/DeviceName.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <cmath>
|
||||
#include "DeviceName.h"
|
||||
|
||||
using namespace logid::backend;
|
||||
using namespace logid::backend::hidpp20;
|
||||
|
||||
DeviceName::DeviceName(Device* dev) : Feature(dev, ID)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t DeviceName::getNameLength()
|
||||
{
|
||||
std::vector<uint8_t> params(0);
|
||||
|
||||
auto response = this->callFunction(Function::GetLength, params);
|
||||
return response[0];
|
||||
}
|
||||
|
||||
std::string _getName(uint8_t length,
|
||||
const std::function<std::vector<uint8_t>(std::vector<uint8_t>)>& fcall)
|
||||
{
|
||||
uint8_t function_calls = length/hidpp::LongParamLength;
|
||||
if(length % hidpp::LongParamLength)
|
||||
function_calls++;
|
||||
std::vector<uint8_t> params(1);
|
||||
std::string name;
|
||||
|
||||
for(uint8_t i = 0; i < function_calls; i++) {
|
||||
params[0] = i*hidpp::LongParamLength;
|
||||
auto name_section = fcall(params);
|
||||
for(std::size_t j = 0; j < hidpp::LongParamLength; j++) {
|
||||
if(params[0] + j >= length)
|
||||
return name;
|
||||
name += name_section[j];
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string DeviceName::getName()
|
||||
{
|
||||
return _getName(getNameLength(), [this]
|
||||
(std::vector<uint8_t> params)->std::vector<uint8_t> {
|
||||
return this->callFunction(Function::GetDeviceName, params);
|
||||
});
|
||||
}
|
||||
|
||||
EssentialDeviceName::EssentialDeviceName(hidpp::Device* dev) :
|
||||
EssentialFeature(dev, ID)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t EssentialDeviceName::getNameLength()
|
||||
{
|
||||
std::vector<uint8_t> params(0);
|
||||
|
||||
auto response = this->callFunction(DeviceName::Function::GetLength, params);
|
||||
return response[0];
|
||||
}
|
||||
|
||||
std::string EssentialDeviceName::getName()
|
||||
{
|
||||
return _getName(getNameLength(), [this]
|
||||
(std::vector<uint8_t> params)->std::vector<uint8_t> {
|
||||
return this->callFunction(DeviceName::Function::GetDeviceName, params);
|
||||
});
|
||||
}
|
43
src/logid/backend/hidpp20/features/DeviceName.h
Normal file
43
src/logid/backend/hidpp20/features/DeviceName.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef LOGID_BACKEND_HIDPP20_FEATURE_DEVICENAME_H
|
||||
#define LOGID_BACKEND_HIDPP20_FEATURE_DEVICENAME_H
|
||||
|
||||
#include "../Feature.h"
|
||||
#include "../feature_defs.h"
|
||||
#include "../EssentialFeature.h"
|
||||
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace hidpp20
|
||||
{
|
||||
class DeviceName : public Feature
|
||||
{
|
||||
public:
|
||||
static const uint16_t ID = FeatureID::DEVICE_NAME;
|
||||
virtual uint16_t getID() { return ID; }
|
||||
|
||||
enum Function : uint8_t
|
||||
{
|
||||
GetLength = 0,
|
||||
GetDeviceName = 1
|
||||
};
|
||||
|
||||
DeviceName(Device* device);
|
||||
|
||||
uint8_t getNameLength();
|
||||
std::string getName();
|
||||
};
|
||||
|
||||
class EssentialDeviceName : public EssentialFeature
|
||||
{
|
||||
public:
|
||||
static const uint16_t ID = FeatureID::DEVICE_NAME;
|
||||
virtual uint16_t getID() { return ID; }
|
||||
|
||||
EssentialDeviceName(hidpp::Device* device);
|
||||
|
||||
uint8_t getNameLength();
|
||||
std::string getName();
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_HIDPP20_FEATURE_DEVICENAME_H
|
@@ -6,31 +6,59 @@ Root::Root(Device* dev) : Feature(dev, ID)
|
||||
{
|
||||
}
|
||||
|
||||
feature_info Root::getFeature(uint16_t feature_id)
|
||||
std::vector<uint8_t> _genGetFeatureParams(uint16_t feature_id)
|
||||
{
|
||||
feature_info info{};
|
||||
std::vector<uint8_t> params(2);
|
||||
params[0] = feature_id & 0xff;
|
||||
params[1] = (feature_id >> 8) & 0xff;
|
||||
return params;
|
||||
}
|
||||
|
||||
auto response = this->callFunction(Function::GetFeature, params);
|
||||
|
||||
feature_info _genGetFeatureInfo(uint16_t feature_id, std::vector<uint8_t> response)
|
||||
{
|
||||
feature_info info{};
|
||||
info.feature_id = response[0];
|
||||
|
||||
if(!info.feature_id)
|
||||
throw UnsupportedFeature(feature_id);
|
||||
|
||||
info.hidden = response[1] & FeatureFlag::Hidden;
|
||||
info.obsolete = response[1] & FeatureFlag::Obsolete;
|
||||
info.internal = response[1] & FeatureFlag::Internal;
|
||||
info.hidden = response[1] & Root::FeatureFlag::Hidden;
|
||||
info.obsolete = response[1] & Root::FeatureFlag::Obsolete;
|
||||
info.internal = response[1] & Root::FeatureFlag::Internal;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
feature_info Root::getFeature(uint16_t feature_id)
|
||||
{
|
||||
auto params = _genGetFeatureParams(feature_id);
|
||||
auto response = this->callFunction(Function::GetFeature, params);
|
||||
return _genGetFeatureInfo(feature_id, response);
|
||||
}
|
||||
|
||||
std::tuple<uint8_t, uint8_t> Root::getVersion()
|
||||
{
|
||||
std::vector<uint8_t> params(0);
|
||||
auto response = this->callFunction(Function::Ping, params);
|
||||
|
||||
return std::make_tuple(response[0], response[1]);
|
||||
}
|
||||
|
||||
EssentialRoot::EssentialRoot(hidpp::Device* dev) : EssentialFeature(dev, ID)
|
||||
{
|
||||
}
|
||||
|
||||
feature_info EssentialRoot::getFeature(uint16_t feature_id)
|
||||
{
|
||||
auto params = _genGetFeatureParams(feature_id);
|
||||
auto response = this->callFunction(Root::Function::GetFeature, params);
|
||||
return _genGetFeatureInfo(feature_id, response);
|
||||
}
|
||||
|
||||
std::tuple<uint8_t, uint8_t> EssentialRoot::getVersion()
|
||||
{
|
||||
std::vector<uint8_t> params(0);
|
||||
auto response = this->callFunction(Root::Function::Ping, params);
|
||||
|
||||
return std::make_tuple(response[0], response[1]);
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
#define LOGID_BACKEND_HIDPP20_FEATURE_ROOT_H
|
||||
|
||||
#include "../Feature.h"
|
||||
#include "../EssentialFeature.h"
|
||||
#include "../feature_defs.h"
|
||||
|
||||
namespace logid {
|
||||
@@ -24,7 +25,7 @@ namespace hidpp20
|
||||
|
||||
feature_info getFeature (uint16_t feature_id);
|
||||
std::tuple<uint8_t, uint8_t> getVersion();
|
||||
private:
|
||||
|
||||
enum FeatureFlag : uint8_t
|
||||
{
|
||||
Obsolete = 1<<7,
|
||||
@@ -32,6 +33,18 @@ namespace hidpp20
|
||||
Internal = 1<<5
|
||||
};
|
||||
};
|
||||
|
||||
class EssentialRoot : public EssentialFeature
|
||||
{
|
||||
public:
|
||||
static const uint16_t ID = FeatureID::ROOT;
|
||||
virtual uint16_t getID() { return ID; }
|
||||
|
||||
EssentialRoot(hidpp::Device* device);
|
||||
|
||||
feature_info getFeature (uint16_t feature_id);
|
||||
std::tuple<uint8_t, uint8_t> getVersion();
|
||||
};
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_HIDPP20_FEATURE_ROOT_H
|
Reference in New Issue
Block a user