Print version number of device 1 on each raw dev.

Only works on HID++ >=2.0 so far. Also solves a race condition where
the wrong response can be sent to a request.
This commit is contained in:
pixl
2020-06-18 01:34:25 -04:00
parent 14d07c220e
commit c21a923ab2
19 changed files with 518 additions and 123 deletions

View File

@@ -0,0 +1,25 @@
#include <cassert>
#include "Device.h"
#include "../hidpp/defs.h"
using namespace logid::backend::hidpp20;
std::vector<uint8_t> Device::callFunction(uint8_t feature_index,
uint8_t function, 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, deviceIndex(), feature_index, function,
LOGID_HIDPP_SOFTWARE_ID);
std::copy(params.begin(), params.end(), request.paramBegin());
auto response = this->sendReport(request);
return std::vector<uint8_t>(response.paramBegin(), response.paramEnd());
}

View File

@@ -0,0 +1,19 @@
#ifndef LOGID_HIDPP20_DEVICE_H
#define LOGID_HIDPP20_DEVICE_H
#include "../hidpp/Device.h"
#include <cstdint>
namespace logid {
namespace backend {
namespace hidpp20 {
class Device : public hidpp::Device
{
public:
std::vector<uint8_t> callFunction(uint8_t feature_index,
uint8_t function,
std::vector<uint8_t>& params);
};
}}}
#endif //LOGID_HIDPP20_DEVICE_H

View File

@@ -0,0 +1,46 @@
#include <cassert>
#include <cstring>
#include "Error.h"
using namespace logid::backend::hidpp20;
Error::Error(uint8_t code) : _code (code)
{
assert(_code != NoError);
}
const char* Error::what() const noexcept
{
switch(_code)
{
case NoError:
return "No error";
case Unknown:
return "Unknown";
case InvalidArgument:
return "Invalid argument";
case OutOfRange:
return "Out of range";
case HardwareError:
return "Hardware error";
case LogitechInternal:
return "Logitech internal feature";
case InvalidFeatureIndex:
return "Invalid feature index";
case InvalidFunctionID:
return "Invalid function ID";
case Busy:
return "Busy";
case Unsupported:
return "Unsupported";
case UnknownDevice:
return "Unknown device";
default:
return std::string("Unknown error code " + std::to_string(_code)).c_str();
}
}
uint8_t Error::code() const noexcept
{
return _code;
}

View File

@@ -0,0 +1,39 @@
#ifndef LOGID_BACKEND_HIDPP20_ERROR_H
#define LOGID_BACKEND_HIDPP20_ERROR_H
#include <stdexcept>
#include <cstdint>
namespace logid {
namespace backend {
namespace hidpp20 {
static constexpr uint8_t ErrorID = 0xFF;
class Error: public std::exception
{
public:
enum ErrorCode: uint8_t {
NoError = 0,
Unknown = 1,
InvalidArgument = 2,
OutOfRange = 3,
HardwareError = 4,
LogitechInternal = 5,
InvalidFeatureIndex = 6,
InvalidFunctionID = 7,
Busy = 8,
Unsupported = 9,
UnknownDevice = 10
};
Error(uint8_t code);
virtual const char* what() const noexcept;
uint8_t code() const noexcept;
private:
uint8_t _code;
};
}}}
#endif //LOGID_BACKEND_HIDPP20_ERROR_H

View File

@@ -0,0 +1,28 @@
#include "Feature.h"
using namespace logid::backend::hidpp20;
const char* Feature::UnsupportedFeature::what() const noexcept
{
return "Unsupported feature";
}
uint16_t Feature::UnsupportedFeature::code() const noexcept
{
return _f_id;
}
std::vector<uint8_t> Feature::callFunction(uint8_t function_id, std::vector<uint8_t>& params)
{
return _device->callFunction(_index, function_id, params);
}
Feature::Feature(Device* dev, uint16_t _id) : _device (dev), _index (0xff)
{
///TODO: Set index
}
Feature::Feature(Device* dev, uint8_t _index) : _device (dev), _index (_index)
{
}

View File

@@ -0,0 +1,37 @@
#ifndef LOGID_HIDPP20_FEATURE_H
#define LOGID_HIDPP20_FEATURE_H
#include <cstdint>
#include "Device.h"
namespace logid {
namespace backend {
namespace hidpp20 {
class Feature
{
class UnsupportedFeature : public std::exception
{
public:
explicit UnsupportedFeature(uint16_t ID) : _f_id (ID) {}
virtual const char* what() const noexcept;
uint16_t code() const noexcept;
private:
uint16_t _f_id;
};
public:
static const uint16_t ID;
virtual uint16_t getID() = 0;
protected:
explicit Feature(Device* dev, uint16_t _id);
explicit Feature(Device* dev, uint8_t _index);
std::vector<uint8_t> callFunction(uint8_t function_id,
std::vector<uint8_t>& params);
private:
Device* _device;
uint8_t _index;
};
}}}
#endif //LOGID_HIDPP20_FEATURE_H

View File

@@ -6,97 +6,108 @@
namespace logid {
namespace backend {
namespace hidpp20 {
enum FeatureID : uint16_t
{
ROOT = 0x0000,
FEATURE_SET = 0x0001,
FEATURE_INFO = 0x0002,
FW_VERSION = 0x0003,
DEVICE_NAME = 0x0005,
DEVICE_GROUPS = 0x0006,
DEVICE_FRIENDLY_NAME = 0x0007,
RESET = 0x0020,
CRYPTO_IDENTIFIER = 0x0021,
DFUCONTROL = 0x00c0,
DFUCONTROL_V2 = 0x00c1,
DFUCONTROL_V3 = 0x00c2,
DFU = 0xd000,
BATTERY_STATUS = 0x1000,
BATTERY_VOLTAGE = 0x1001,
CHARGING_CONTROL = 0x1010,
LED_CONTROL = 0x1300,
GENERIC_TEST = 0x1800,
DEVICE_RESET = 0x1802,
OOB_STATE = 0x1805,
CONFIGURABLE_DEVICE_PROPERTIES = 0x1806,
CHANGE_HOST = 0x1814,
HOSTS_INFO = 0x1815,
BACKLIGHT = 0x1981,
BACKLIGHT_V2 = 0x1982,
BACKLIGHT_V3 = 0x1983,
PRESENTER_CONTROL = 0x1a00,
SENSOR_3D = 0x1a01,
REPROG_CONTROLS = 0x1b00,
REPROG_CONTROLS_V2 = 0x1b01,
REPROG_CONTROLS_V2_2 = 0x1b02,
REPROG_CONTROLS_V3 = 0x1b03,
REPROG_CONTROLS_V4 = 0x1b04,
PERSISTENT_REMAPPABLE_ACTION = 0x1bc0,
WIRELESS_DEVICE_STATUS = 0x1d4b,
ENABLE_HIDDEN_FEATURE = 0x1e00,
FIRMWARE_PROPERTIES = 0x1f1f,
ADC_MEASUREMENT = 0x1f20,
LEFT_RIGHT_SWAP = 0x2001,
SWAP_BUTTON = 0x2005,
POINTER_AXES_ORIENTATION = 0x2006,
VERTICAL_SCROLLING = 0x2100,
SMART_SHIFT = 0x2110,
HIRES_SCROLLING = 0x2120,
HIRES_SCROLLING_V2 = 0x2121, // Referred to as Hi-res wheel in cvuchener/hidpp, seems to be V2?
LORES_SCROLLING = 0x2130,
MOUSE_POINTER = 0x2200, // Possibly predecessor to 0x2201?
ADJUSTABLE_DPI = 0x2201,
ANGLE_SNAPPING = 0x2230,
SURFACE_TUNING = 0x2240,
HYBRID_TRACKING = 0x2400,
FN_INVERSION = 0x40a0,
FN_INVERSION_V2 = 0x40a2, // Is 0x40a1 skipped?
FN_INVERSION_V3 = 0x40a3,
ENCRYPTION = 0x4100,
LOCK_KEY_STATE = 0x4220,
SOLAR_DASHBOARD = 0x4301,
KEYBOARD_LAYOUT = 0x4520,
KEYBOARD_DISABLE = 0x4521,
DISABLE_KEYS = 0x4522,
MULTIPLATFORM = 0x4530, // Dual platform only?
MULTIPLATFORM_V2 = 0x4531,
KEYBOARD_LAYOUT_V2 = 0x4540,
CROWN = 0x4600,
TOUCHPAD_FW = 0x6010,
TOUCHPAD_SW = 0x6011,
TOUCHPAD_FW_WIN8 = 0x6012,
TOUCHMOUSE_RAW = 0x6100,
// TOUCHMOUSE_6120 = 0x6120, (Keeping this commented out until a better name is found)
GESTURE = 0x6500,
GESTURE_V2 = 0x6501,
G_KEY = 0x8010,
M_KEY = 0x8020,
// MR = 0x8030, (Keeping this commented out until a better name is found)
BRIGHTNESS_CONTROL = 0x8040,
REPORT_RATE = 0x8060,
RGB_EFFECTS = 0x8070,
RGB_EFFECTS_V2 = 0x8071,
PER_KEY_LIGHTING = 0x8080,
PER_KEY_LIGHTING_V2 = 0x8081,
MODE_STATUS = 0x8100,
MOUSE_BUTTON_SPY = 0x8110,
LATENCY_MONITORING = 0x8111,
GAMING_ATTACHMENTS = 0x8120,
FORCE_FEEDBACK = 0x8123,
SIDETONE = 0x8300,
EQUALIZER = 0x8310,
HEADSET_OUT = 0x8320
struct feature_info {
uint16_t feature_id;
bool obsolete;
bool internal;
bool hidden;
};
namespace FeatureID
{
enum FeatureID : uint16_t
{
ROOT = 0x0000,
FEATURE_SET = 0x0001,
FEATURE_INFO = 0x0002,
FW_VERSION = 0x0003,
DEVICE_NAME = 0x0005,
DEVICE_GROUPS = 0x0006,
DEVICE_FRIENDLY_NAME = 0x0007,
RESET = 0x0020,
CRYPTO_IDENTIFIER = 0x0021,
DFUCONTROL = 0x00c0,
DFUCONTROL_V2 = 0x00c1,
DFUCONTROL_V3 = 0x00c2,
DFU = 0xd000,
BATTERY_STATUS = 0x1000,
BATTERY_VOLTAGE = 0x1001,
CHARGING_CONTROL = 0x1010,
LED_CONTROL = 0x1300,
GENERIC_TEST = 0x1800,
DEVICE_RESET = 0x1802,
OOB_STATE = 0x1805,
CONFIGURABLE_DEVICE_PROPERTIES = 0x1806,
CHANGE_HOST = 0x1814,
HOSTS_INFO = 0x1815,
BACKLIGHT = 0x1981,
BACKLIGHT_V2 = 0x1982,
BACKLIGHT_V3 = 0x1983,
PRESENTER_CONTROL = 0x1a00,
SENSOR_3D = 0x1a01,
REPROG_CONTROLS = 0x1b00,
REPROG_CONTROLS_V2 = 0x1b01,
REPROG_CONTROLS_V2_2 = 0x1b02,
REPROG_CONTROLS_V3 = 0x1b03,
REPROG_CONTROLS_V4 = 0x1b04,
PERSISTENT_REMAPPABLE_ACTION = 0x1bc0,
WIRELESS_DEVICE_STATUS = 0x1d4b,
ENABLE_HIDDEN_FEATURE = 0x1e00,
FIRMWARE_PROPERTIES = 0x1f1f,
ADC_MEASUREMENT = 0x1f20,
LEFT_RIGHT_SWAP = 0x2001,
SWAP_BUTTON = 0x2005,
POINTER_AXES_ORIENTATION = 0x2006,
VERTICAL_SCROLLING = 0x2100,
SMART_SHIFT = 0x2110,
HIRES_SCROLLING = 0x2120,
HIRES_SCROLLING_V2 = 0x2121, // Referred to as Hi-res wheel in cvuchener/hidpp, seems to be V2?
LORES_SCROLLING = 0x2130,
MOUSE_POINTER = 0x2200, // Possibly predecessor to 0x2201?
ADJUSTABLE_DPI = 0x2201,
ANGLE_SNAPPING = 0x2230,
SURFACE_TUNING = 0x2240,
HYBRID_TRACKING = 0x2400,
FN_INVERSION = 0x40a0,
FN_INVERSION_V2 = 0x40a2, // Is 0x40a1 skipped?
FN_INVERSION_V3 = 0x40a3,
ENCRYPTION = 0x4100,
LOCK_KEY_STATE = 0x4220,
SOLAR_DASHBOARD = 0x4301,
KEYBOARD_LAYOUT = 0x4520,
KEYBOARD_DISABLE = 0x4521,
DISABLE_KEYS = 0x4522,
MULTIPLATFORM = 0x4530, // Dual platform only?
MULTIPLATFORM_V2 = 0x4531,
KEYBOARD_LAYOUT_V2 = 0x4540,
CROWN = 0x4600,
TOUCHPAD_FW = 0x6010,
TOUCHPAD_SW = 0x6011,
TOUCHPAD_FW_WIN8 = 0x6012,
TOUCHMOUSE_RAW = 0x6100,
// TOUCHMOUSE_6120 = 0x6120, (Keeping this commented out until a better name is found)
GESTURE = 0x6500,
GESTURE_V2 = 0x6501,
G_KEY = 0x8010,
M_KEY = 0x8020,
// MR = 0x8030, (Keeping this commented out until a better name is found)
BRIGHTNESS_CONTROL = 0x8040,
REPORT_RATE = 0x8060,
RGB_EFFECTS = 0x8070,
RGB_EFFECTS_V2 = 0x8071,
PER_KEY_LIGHTING = 0x8080,
PER_KEY_LIGHTING_V2 = 0x8081,
MODE_STATUS = 0x8100,
MOUSE_BUTTON_SPY = 0x8110,
LATENCY_MONITORING = 0x8111,
GAMING_ATTACHMENTS = 0x8120,
FORCE_FEEDBACK = 0x8123,
SIDETONE = 0x8300,
EQUALIZER = 0x8310,
HEADSET_OUT = 0x8320
};
}
}}}
#endif //LOGID_BACKEND_HIDPP20_FEATUREDEFS

View File

@@ -0,0 +1,25 @@
#include "Root.h"
using namespace logid::backend::hidpp20;
Root::Root(Device* dev) : Feature(dev, ID)
{
}
feature_info Root::getFeature(uint16_t feature_id)
{
feature_info info;
std::vector<uint8_t> params(2);
params[0] = feature_id & 0xff;
params[1] = (feature_id >> 8) & 0xff;
auto response = this->callFunction(Function::Ping, params);
info.feature_id = response[0];
info.hidden = response[1] & FeatureFlag::Hidden;
info.obsolete = response[1] & FeatureFlag::Obsolete;
info.internal = response[1] & FeatureFlag::Internal;
return info;
}

View File

@@ -0,0 +1,37 @@
#ifndef LOGID_BACKEND_HIDPP20_FEATURE_ROOT_H
#define LOGID_BACKEND_HIDPP20_FEATURE_ROOT_H
#include "../Feature.h"
#include "../feature_defs.h"
namespace logid {
namespace backend {
namespace hidpp20
{
class Root : public Feature
{
public:
static const uint16_t ID = FeatureID::ROOT;
virtual uint16_t getID() { return ID; }
enum Function : uint8_t
{
GetFeature = 0,
Ping = 1
};
Root(Device* device);
feature_info getFeature (uint16_t feature_id);
void ping();
private:
enum FeatureFlag : uint8_t
{
Obsolete = 1<<7,
Hidden = 1<<6,
Internal = 1<<5
};
};
}}}
#endif //LOGID_BACKEND_HIDPP20_FEATURE_ROOT_H