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:
parent
14d07c220e
commit
c21a923ab2
|
@ -17,6 +17,10 @@ add_executable(logid
|
||||||
backend/raw/RawDevice.cpp
|
backend/raw/RawDevice.cpp
|
||||||
backend/hidpp/Device.cpp
|
backend/hidpp/Device.cpp
|
||||||
backend/hidpp/Report.cpp
|
backend/hidpp/Report.cpp
|
||||||
|
backend/hidpp20/Device.cpp
|
||||||
|
backend/hidpp20/Error.cpp
|
||||||
|
backend/hidpp20/Feature.cpp
|
||||||
|
backend/hidpp20/features/Root.cpp
|
||||||
backend/dj/Report.cpp
|
backend/dj/Report.cpp
|
||||||
util/mutex_queue.h)
|
util/mutex_queue.h)
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,9 @@ void DeviceMonitor::addDevice(std::string path)
|
||||||
auto device = std::make_shared<backend::hidpp::Device>(path, hidpp::DeviceIndex::WirelessDevice1);
|
auto device = std::make_shared<backend::hidpp::Device>(path, hidpp::DeviceIndex::WirelessDevice1);
|
||||||
log_printf(DEBUG, "Detected HID++ device at %s", path.c_str());
|
log_printf(DEBUG, "Detected HID++ device at %s", path.c_str());
|
||||||
|
|
||||||
|
auto version = device->version();
|
||||||
|
log_printf(DEBUG, "HID++ version: %d.%d", std::get<0>(version), std::get<1>(version));
|
||||||
|
|
||||||
auto eventHandler = std::make_shared<backend::hidpp::EventHandler>();
|
auto eventHandler = std::make_shared<backend::hidpp::EventHandler>();
|
||||||
eventHandler->condition = [device](backend::hidpp::Report& report)->bool
|
eventHandler->condition = [device](backend::hidpp::Report& report)->bool
|
||||||
{
|
{
|
||||||
|
|
20
src/logid/backend/dj/defs.h
Normal file
20
src/logid/backend/dj/defs.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef LOGID_BACKEND_DJ_DEFS_H
|
||||||
|
#define LOGID_BACKEND_DJ_DEFS_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace logid {
|
||||||
|
namespace backend {
|
||||||
|
namespace dj
|
||||||
|
{
|
||||||
|
namespace ReportType
|
||||||
|
{
|
||||||
|
enum ReportType : uint8_t
|
||||||
|
{
|
||||||
|
Short = 0x20,
|
||||||
|
Long = 0x21
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}}}
|
||||||
|
|
||||||
|
#endif //LOGID_BACKEND_DJ_DEFS_H
|
|
@ -1,6 +1,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "Device.h"
|
#include "Device.h"
|
||||||
#include "Report.h"
|
#include "Report.h"
|
||||||
|
#include "../hidpp20/features/Root.h"
|
||||||
|
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
using namespace logid::backend::hidpp;
|
using namespace logid::backend::hidpp;
|
||||||
|
@ -29,12 +30,20 @@ Device::Device(const std::string& path, DeviceIndex index):
|
||||||
if(!supported_reports)
|
if(!supported_reports)
|
||||||
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
|
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
|
||||||
|
|
||||||
|
Report versionRequest(Report::Type::Short, index, hidpp20::FeatureID::ROOT,
|
||||||
|
hidpp20::Root::Ping, LOGID_HIDPP_SOFTWARE_ID);
|
||||||
|
|
||||||
|
///TODO: Catch error
|
||||||
|
auto versionResponse = sendReport(versionRequest);
|
||||||
|
auto versionResponse_params = versionResponse.paramBegin();
|
||||||
|
_version = std::make_tuple(versionResponse_params[0], versionResponse_params[1]);
|
||||||
|
|
||||||
// Pass all HID++ events with device index to this device.
|
// Pass all HID++ events with device index to this device.
|
||||||
RawEventHandler rawEventHandler;
|
RawEventHandler rawEventHandler;
|
||||||
rawEventHandler.condition = [index](std::vector<uint8_t>& report)->bool
|
rawEventHandler.condition = [index](std::vector<uint8_t>& report)->bool
|
||||||
{
|
{
|
||||||
return (report[Offset::Type] == Report::Short ||
|
return (report[Offset::Type] == Report::Type::Short ||
|
||||||
report[Offset::Type] == Report::Long) && (report[Offset::DeviceIndex] == index);
|
report[Offset::Type] == Report::Type::Long) && (report[Offset::DeviceIndex] == index);
|
||||||
};
|
};
|
||||||
rawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
rawEventHandler.callback = [this](std::vector<uint8_t>& report)->void
|
||||||
{
|
{
|
||||||
|
@ -69,11 +78,11 @@ Report Device::sendReport(Report& report)
|
||||||
{
|
{
|
||||||
switch(report.type())
|
switch(report.type())
|
||||||
{
|
{
|
||||||
case Report::Short:
|
case Report::Type::Short:
|
||||||
if(!(supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
|
if(!(supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
|
||||||
report.setType(Report::Long);
|
report.setType(Report::Type::Long);
|
||||||
break;
|
break;
|
||||||
case Report::Long:
|
case Report::Type::Long:
|
||||||
/* Report can be truncated, but that isn't a good idea. */
|
/* Report can be truncated, but that isn't a good idea. */
|
||||||
assert(supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
|
assert(supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace hidpp
|
||||||
|
|
||||||
std::string devicePath() const { return path; }
|
std::string devicePath() const { return path; }
|
||||||
DeviceIndex deviceIndex() const { return index; }
|
DeviceIndex deviceIndex() const { return index; }
|
||||||
|
std::tuple<uint8_t, uint8_t> version() const { return _version; }
|
||||||
|
|
||||||
void listen(); // Runs asynchronously
|
void listen(); // Runs asynchronously
|
||||||
void stopListening();
|
void stopListening();
|
||||||
|
@ -56,6 +57,8 @@ namespace hidpp
|
||||||
DeviceIndex index;
|
DeviceIndex index;
|
||||||
uint8_t supported_reports;
|
uint8_t supported_reports;
|
||||||
|
|
||||||
|
std::tuple<uint8_t, uint8_t> _version;
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<EventHandler>> event_handlers;
|
std::map<std::string, std::shared_ptr<EventHandler>> event_handlers;
|
||||||
};
|
};
|
||||||
} } }
|
} } }
|
||||||
|
|
|
@ -96,15 +96,15 @@ const char *Report::InvalidReportLength::what() const noexcept
|
||||||
Report::Report(Report::Type type, DeviceIndex device_index,
|
Report::Report(Report::Type type, DeviceIndex device_index,
|
||||||
uint8_t feature_index, uint8_t function, uint8_t sw_id)
|
uint8_t feature_index, uint8_t function, uint8_t sw_id)
|
||||||
{
|
{
|
||||||
assert(!(function & functionMask));
|
assert(function <= functionMask);
|
||||||
assert(!(sw_id & swIdMask));
|
assert(sw_id <= swIdMask);
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case Short:
|
case Type::Short:
|
||||||
_data.resize(HeaderLength + ShortParamLength);
|
_data.resize(HeaderLength + ShortParamLength);
|
||||||
break;
|
break;
|
||||||
case Long:
|
case Type::Long:
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -123,10 +123,10 @@ Report::Report(const std::vector<uint8_t>& data)
|
||||||
|
|
||||||
switch(_data[Offset::Type])
|
switch(_data[Offset::Type])
|
||||||
{
|
{
|
||||||
case Short:
|
case Type::Short:
|
||||||
_data.resize(HeaderLength + ShortParamLength);
|
_data.resize(HeaderLength + ShortParamLength);
|
||||||
break;
|
break;
|
||||||
case Long:
|
case Type::Long:
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -138,10 +138,10 @@ void Report::setType(Report::Type type)
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case Short:
|
case Type::Short:
|
||||||
_data.resize(HeaderLength + ShortParamLength);
|
_data.resize(HeaderLength + ShortParamLength);
|
||||||
break;
|
break;
|
||||||
case Long:
|
case Type::Long:
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -158,3 +158,10 @@ void Report::setParams(const std::vector<uint8_t>& _params)
|
||||||
for(std::size_t i = 0; i < _params.size(); i++)
|
for(std::size_t i = 0; i < _params.size(); i++)
|
||||||
_data[Offset::Parameters + i] = _params[i];
|
_data[Offset::Parameters + i] = _params[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Report::isError20(Report::hidpp20_error* error)
|
||||||
|
{
|
||||||
|
if(_data[Offset::Type] != Type::Long ||
|
||||||
|
_data[Offset::Feature] != 0xff)
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -26,11 +26,7 @@ namespace logid::backend::hidpp
|
||||||
class Report
|
class Report
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type: uint8_t
|
typedef ReportType::ReportType Type;
|
||||||
{
|
|
||||||
Short = 0x10,
|
|
||||||
Long = 0x11
|
|
||||||
};
|
|
||||||
|
|
||||||
class InvalidReportID: public std::exception
|
class InvalidReportID: public std::exception
|
||||||
{
|
{
|
||||||
|
@ -50,19 +46,26 @@ namespace logid::backend::hidpp
|
||||||
static constexpr uint8_t swIdMask = 0x0f;
|
static constexpr uint8_t swIdMask = 0x0f;
|
||||||
static constexpr uint8_t functionMask = 0x0f;
|
static constexpr uint8_t functionMask = 0x0f;
|
||||||
|
|
||||||
Report(Type type, DeviceIndex device_index,
|
Report(Report::Type type, DeviceIndex device_index,
|
||||||
uint8_t feature_index,
|
uint8_t feature_index,
|
||||||
uint8_t function,
|
uint8_t function,
|
||||||
uint8_t sw_id);
|
uint8_t sw_id);
|
||||||
explicit Report(const std::vector<uint8_t>& data);
|
explicit Report(const std::vector<uint8_t>& data);
|
||||||
|
|
||||||
Type type() const { return static_cast<Type>(_data[Offset::Type]); };
|
Report::Type type() const { return static_cast<Report::Type>(_data[Offset::Type]); };
|
||||||
void setType(Report::Type type);
|
void setType(Report::Type type);
|
||||||
|
|
||||||
std::vector<uint8_t>::const_iterator paramBegin() const { return _data.begin() + Offset::Parameters; }
|
std::vector<uint8_t>::iterator paramBegin() { return _data.begin() + Offset::Parameters; }
|
||||||
std::vector<uint8_t>::const_iterator paramEnd() const { return _data.end(); }
|
std::vector<uint8_t>::iterator paramEnd() { return _data.end(); }
|
||||||
void setParams(const std::vector<uint8_t>& _params);
|
void setParams(const std::vector<uint8_t>& _params);
|
||||||
|
|
||||||
|
struct hidpp20_error
|
||||||
|
{
|
||||||
|
uint8_t feature_index, function, software_id, error_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isError20(hidpp20_error* error);
|
||||||
|
|
||||||
logid::backend::hidpp::DeviceIndex deviceIndex()
|
logid::backend::hidpp::DeviceIndex deviceIndex()
|
||||||
{
|
{
|
||||||
return static_cast<DeviceIndex>(_data[Offset::DeviceIndex]);
|
return static_cast<DeviceIndex>(_data[Offset::DeviceIndex]);
|
||||||
|
|
|
@ -5,6 +5,15 @@
|
||||||
|
|
||||||
namespace logid::backend::hidpp
|
namespace logid::backend::hidpp
|
||||||
{
|
{
|
||||||
|
namespace ReportType
|
||||||
|
{
|
||||||
|
enum ReportType : uint8_t
|
||||||
|
{
|
||||||
|
Short = 0x10,
|
||||||
|
Long = 0x11
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
enum DeviceIndex: uint8_t
|
enum DeviceIndex: uint8_t
|
||||||
{
|
{
|
||||||
DefaultDevice = 0,
|
DefaultDevice = 0,
|
||||||
|
|
25
src/logid/backend/hidpp20/Device.cpp
Normal file
25
src/logid/backend/hidpp20/Device.cpp
Normal 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());
|
||||||
|
}
|
19
src/logid/backend/hidpp20/Device.h
Normal file
19
src/logid/backend/hidpp20/Device.h
Normal 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
|
46
src/logid/backend/hidpp20/Error.cpp
Normal file
46
src/logid/backend/hidpp20/Error.cpp
Normal 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;
|
||||||
|
}
|
39
src/logid/backend/hidpp20/Error.h
Normal file
39
src/logid/backend/hidpp20/Error.h
Normal 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
|
28
src/logid/backend/hidpp20/Feature.cpp
Normal file
28
src/logid/backend/hidpp20/Feature.cpp
Normal 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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
37
src/logid/backend/hidpp20/Feature.h
Normal file
37
src/logid/backend/hidpp20/Feature.h
Normal 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
|
|
@ -6,6 +6,15 @@
|
||||||
namespace logid {
|
namespace logid {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace hidpp20 {
|
namespace hidpp20 {
|
||||||
|
struct feature_info {
|
||||||
|
uint16_t feature_id;
|
||||||
|
bool obsolete;
|
||||||
|
bool internal;
|
||||||
|
bool hidden;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace FeatureID
|
||||||
|
{
|
||||||
enum FeatureID : uint16_t
|
enum FeatureID : uint16_t
|
||||||
{
|
{
|
||||||
ROOT = 0x0000,
|
ROOT = 0x0000,
|
||||||
|
@ -97,6 +106,8 @@ namespace hidpp20 {
|
||||||
EQUALIZER = 0x8310,
|
EQUALIZER = 0x8310,
|
||||||
HEADSET_OUT = 0x8320
|
HEADSET_OUT = 0x8320
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
#endif //LOGID_BACKEND_HIDPP20_FEATUREDEFS
|
#endif //LOGID_BACKEND_HIDPP20_FEATUREDEFS
|
25
src/logid/backend/hidpp20/features/Root.cpp
Normal file
25
src/logid/backend/hidpp20/features/Root.cpp
Normal 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;
|
||||||
|
}
|
37
src/logid/backend/hidpp20/features/Root.h
Normal file
37
src/logid/backend/hidpp20/features/Root.h
Normal 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
|
|
@ -1,5 +1,7 @@
|
||||||
#include "RawDevice.h"
|
#include "RawDevice.h"
|
||||||
#include "../Error.h"
|
#include "../Error.h"
|
||||||
|
#include "../hidpp/defs.h"
|
||||||
|
#include "../dj/defs.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
@ -16,9 +18,16 @@ extern "C"
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace logid::backend::raw;
|
using namespace logid::backend::raw;
|
||||||
|
using namespace logid::backend;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
RawDevice::RawDevice(std::string path) : path (path)
|
bool RawDevice::supportedReportID(uint8_t id)
|
||||||
|
{
|
||||||
|
return (hidpp::ReportType::Short == id) || (hidpp::ReportType::Long == id) ||
|
||||||
|
(dj::ReportType::Short == id) || (dj::ReportType::Long == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
RawDevice::RawDevice(std::string path) : path (path), continue_listen (false)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -80,24 +89,81 @@ RawDevice::~RawDevice()
|
||||||
|
|
||||||
std::vector<uint8_t> RawDevice::sendReport(const std::vector<uint8_t>& report)
|
std::vector<uint8_t> RawDevice::sendReport(const std::vector<uint8_t>& report)
|
||||||
{
|
{
|
||||||
std::packaged_task<std::vector<uint8_t>()> task(
|
assert(supportedReportID(report[0]));
|
||||||
[=]() {
|
|
||||||
_sendReport(report);
|
|
||||||
std::vector<uint8_t> response;
|
|
||||||
_readReport(response, MAX_DATA_LENGTH);
|
|
||||||
return response;
|
|
||||||
});
|
|
||||||
|
|
||||||
/* If the listener will stop, handle I/O manually.
|
/* If the listener will stop, handle I/O manually.
|
||||||
* Otherwise, push to queue and wait for result. */
|
* Otherwise, push to queue and wait for result. */
|
||||||
if(continue_listen)
|
if(continue_listen)
|
||||||
{
|
{
|
||||||
|
std::packaged_task<std::vector<uint8_t>()> task( [this, report]() {
|
||||||
|
return this->_respondToReport(report);
|
||||||
|
});
|
||||||
auto f = task.get_future();
|
auto f = task.get_future();
|
||||||
write_queue.push(&task);
|
write_queue.push(&task);
|
||||||
return f.get();
|
return f.get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return task.get_future().get();
|
return _respondToReport(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> RawDevice::_respondToReport
|
||||||
|
(const std::vector<uint8_t>& request)
|
||||||
|
{
|
||||||
|
_sendReport(request);
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> response;
|
||||||
|
_readReport(response, MAX_DATA_LENGTH);
|
||||||
|
|
||||||
|
// All reports have the device index at byte 2
|
||||||
|
if(response[1] != request[1])
|
||||||
|
{
|
||||||
|
std::thread([this](std::vector<uint8_t> report) {
|
||||||
|
this->handleEvent(report);
|
||||||
|
}, request).detach();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hidpp::ReportType::Short == request[0] ||
|
||||||
|
hidpp::ReportType::Long == request[0])
|
||||||
|
{
|
||||||
|
if(hidpp::ReportType::Short != response[0] &&
|
||||||
|
hidpp::ReportType::Long != response[0])
|
||||||
|
{
|
||||||
|
std::thread([this](std::vector<uint8_t> report) {
|
||||||
|
this->handleEvent(report);
|
||||||
|
}, request).detach();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error; leave to device to handle
|
||||||
|
if(response[2] == 0x8f || response[2] == 0xff)
|
||||||
|
return response;
|
||||||
|
|
||||||
|
bool others_match = true;
|
||||||
|
for(int i = 2; i < 4; i++)
|
||||||
|
{
|
||||||
|
if(response[i] != request[i])
|
||||||
|
others_match = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(others_match)
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else if(dj::ReportType::Short == request[0] ||
|
||||||
|
dj::ReportType::Long == request[0])
|
||||||
|
{
|
||||||
|
//Error; leave to device ot handle
|
||||||
|
if(0x7f == response[2])
|
||||||
|
return response;
|
||||||
|
else if(response[2] == request[2])
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::thread([this](std::vector<uint8_t> report) {
|
||||||
|
this->handleEvent(report);
|
||||||
|
}, request).detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int RawDevice::_sendReport(const std::vector<uint8_t>& report)
|
int RawDevice::_sendReport(const std::vector<uint8_t>& report)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "../defs.h"
|
#include "../defs.h"
|
||||||
#include "../../util/mutex_queue.h"
|
#include "../../util/mutex_queue.h"
|
||||||
|
@ -20,12 +21,13 @@ namespace raw
|
||||||
class RawDevice
|
class RawDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static bool supportedReportID(uint8_t id);
|
||||||
|
|
||||||
RawDevice(std::string path);
|
RawDevice(std::string path);
|
||||||
~RawDevice();
|
~RawDevice();
|
||||||
std::string hidrawPath() const { return path; }
|
std::string hidrawPath() const { return path; }
|
||||||
std::vector<uint8_t> reportDescriptor() const { return rdesc; }
|
std::vector<uint8_t> reportDescriptor() const { return rdesc; }
|
||||||
|
|
||||||
/// TODO: Process reports in a queue.
|
|
||||||
std::vector<uint8_t> sendReport(const std::vector<uint8_t>& report);
|
std::vector<uint8_t> sendReport(const std::vector<uint8_t>& report);
|
||||||
void interruptRead();
|
void interruptRead();
|
||||||
|
|
||||||
|
@ -55,6 +57,8 @@ namespace raw
|
||||||
int _sendReport(const std::vector<uint8_t>& report);
|
int _sendReport(const std::vector<uint8_t>& report);
|
||||||
int _readReport(std::vector<uint8_t>& report, std::size_t maxDataLength);
|
int _readReport(std::vector<uint8_t>& report, std::size_t maxDataLength);
|
||||||
|
|
||||||
|
std::vector<uint8_t> _respondToReport(const std::vector<uint8_t>& request);
|
||||||
|
|
||||||
mutex_queue<std::packaged_task<std::vector<uint8_t>()>*> write_queue;
|
mutex_queue<std::packaged_task<std::vector<uint8_t>()>*> write_queue;
|
||||||
};
|
};
|
||||||
}}}
|
}}}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user