Use consistent code style
Only files that are currently used in logid are changed.
This commit is contained in:
parent
bd080e7ef6
commit
dd75df8c18
|
@ -5,7 +5,7 @@ using namespace logid;
|
|||
using namespace logid::backend;
|
||||
|
||||
Device::Device(std::string path, backend::hidpp::DeviceIndex index) :
|
||||
_hidpp20 (path, index), _path (path), _index (index)
|
||||
_hidpp20 (path, index), _path (std::move(path)), _index (index)
|
||||
{
|
||||
log_printf(DEBUG, "logid::Device created on %s:%d", _path.c_str(), _index);
|
||||
}
|
||||
|
|
|
@ -44,14 +44,16 @@ void DeviceManager::addDevice(std::string path)
|
|||
_devices.emplace(path, device);
|
||||
} else {
|
||||
try {
|
||||
auto device = std::make_shared<Device>(path, hidpp::CordedDevice);
|
||||
auto device = std::make_shared<Device>(path,
|
||||
hidpp::CordedDevice);
|
||||
_devices.emplace(path, device);
|
||||
} catch(hidpp10::Error &e) {
|
||||
if(e.code() != hidpp10::Error::UnknownDevice)
|
||||
throw;
|
||||
else
|
||||
log_printf(WARN, "HID++ 1.0 error while trying to initialize"
|
||||
" %s: %s", path.c_str(), e.what());
|
||||
log_printf(WARN,
|
||||
"HID++ 1.0 error while trying to initialize %s:"
|
||||
"%s", path.c_str(), e.what());
|
||||
} catch(hidpp::Device::InvalidDevice &e) { // Ignore
|
||||
} catch(std::system_error &e) {
|
||||
// This error should have been thrown previously
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef LOGID_DEVICEMONITOR_H
|
||||
#define LOGID_DEVICEMONITOR_H
|
||||
#ifndef LOGID_DEVICEMANAGER_H
|
||||
#define LOGID_DEVICEMANAGER_H
|
||||
|
||||
#include <map>
|
||||
#include <thread>
|
||||
|
@ -29,4 +29,4 @@ namespace logid
|
|||
extern DeviceManager* finder;
|
||||
}
|
||||
|
||||
#endif //LOGID_DEVICEFINDER_H
|
||||
#endif //LOGID_DEVICEMANAGER_H
|
|
@ -1,6 +1,6 @@
|
|||
#include "Error.h"
|
||||
|
||||
const char *logid::backend::TimeoutError::what() noexcept
|
||||
const char *logid::backend::TimeoutError::what() const noexcept
|
||||
{
|
||||
return "Device timed out";
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class TimeoutError: public std::exception
|
|||
{
|
||||
public:
|
||||
TimeoutError() = default;
|
||||
virtual const char* what() noexcept;
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
}}
|
||||
|
||||
|
|
|
@ -8,14 +8,17 @@ Error::Error(uint8_t code) : _code (code)
|
|||
|
||||
const char* Error::what() const noexcept
|
||||
{
|
||||
switch(_code)
|
||||
{
|
||||
case Unknown:
|
||||
return "Unknown";
|
||||
case KeepAliveTimeout:
|
||||
return "Keep-alive timeout";
|
||||
default:
|
||||
return std::string("Reserved error code " + std::to_string(_code))
|
||||
.c_str();
|
||||
switch(_code) {
|
||||
case Unknown:
|
||||
return "Unknown";
|
||||
case KeepAliveTimeout:
|
||||
return "Keep-alive timeout";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Error::code() const noexcept
|
||||
{
|
||||
return _code;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
||||
#define LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
||||
#ifndef LOGID_BACKEND_DJ_ERROR_H
|
||||
#define LOGID_BACKEND_DJ_ERROR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
@ -17,9 +17,9 @@ namespace dj
|
|||
KeepAliveTimeout = 0x01
|
||||
};
|
||||
|
||||
Error(uint8_t code);
|
||||
explicit Error(uint8_t code);
|
||||
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
uint8_t code() const noexcept;
|
||||
|
||||
private:
|
||||
|
@ -27,4 +27,4 @@ namespace dj
|
|||
};
|
||||
}}}
|
||||
|
||||
#endif //LOGID_HIDPP_BACKEND_DJ_ERROR_H
|
||||
#endif //LOGID_BACKEND_DJ_ERROR_H
|
|
@ -12,12 +12,11 @@ InvalidReceiver::InvalidReceiver(Reason reason) : _reason (reason)
|
|||
|
||||
const char* InvalidReceiver::what() const noexcept
|
||||
{
|
||||
switch(_reason)
|
||||
{
|
||||
case NoDJReports:
|
||||
return "No DJ reports";
|
||||
default:
|
||||
return "Invalid receiver";
|
||||
switch(_reason) {
|
||||
case NoDJReports:
|
||||
return "No DJ reports";
|
||||
default:
|
||||
return "Invalid receiver";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,10 +26,10 @@ InvalidReceiver::Reason InvalidReceiver::code() const noexcept
|
|||
}
|
||||
|
||||
Receiver::Receiver(std::string path) :
|
||||
raw_device (std::make_shared<raw::RawDevice>(path)),
|
||||
_hidpp10_device (raw_device, hidpp::DefaultDevice)
|
||||
_raw_device (std::make_shared<raw::RawDevice>(std::move(path))),
|
||||
_hidpp10_device (_raw_device, hidpp::DefaultDevice)
|
||||
{
|
||||
if(!supportsDjReports(raw_device->reportDescriptor()))
|
||||
if(!supportsDjReports(_raw_device->reportDescriptor()))
|
||||
throw InvalidReceiver(InvalidReceiver::NoDJReports);
|
||||
}
|
||||
|
||||
|
@ -39,28 +38,28 @@ void Receiver::enumerateDj()
|
|||
sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{});
|
||||
}
|
||||
|
||||
Receiver::notification_flags Receiver::getHidppNotifications()
|
||||
Receiver::NotificationFlags Receiver::getHidppNotifications()
|
||||
{
|
||||
auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {},
|
||||
hidpp::ReportType::Short);
|
||||
|
||||
notification_flags flags{};
|
||||
flags.device_battery_status = response[0] & (1 << 4);
|
||||
flags.receiver_wireless_notifications = response[1] & (1 << 0);
|
||||
flags.receiver_software_present = response[1] & (1 << 3);
|
||||
NotificationFlags flags{};
|
||||
flags.deviceBatteryStatus = response[0] & (1 << 4);
|
||||
flags.receiverWirelessNotifications = response[1] & (1 << 0);
|
||||
flags.receiverSoftwarePresent = response[1] & (1 << 3);
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void Receiver::enableHidppNotifications(notification_flags flags)
|
||||
void Receiver::enableHidppNotifications(NotificationFlags flags)
|
||||
{
|
||||
std::vector<uint8_t> request(3);
|
||||
|
||||
if(flags.device_battery_status)
|
||||
if(flags.deviceBatteryStatus)
|
||||
request[0] |= (1 << 4);
|
||||
if(flags.receiver_wireless_notifications)
|
||||
if(flags.receiverWirelessNotifications)
|
||||
request[1] |= 1;
|
||||
if(flags.receiver_software_present)
|
||||
if(flags.receiverSoftwarePresent)
|
||||
request[1] |= (1 << 3);
|
||||
|
||||
_hidpp10_device.setRegister(EnableHidppNotifications, request,
|
||||
|
@ -228,14 +227,14 @@ hidpp::DeviceConnectionEvent Receiver::deviceConnectionEvent(
|
|||
|
||||
void Receiver::handleDjEvent(Report& report)
|
||||
{
|
||||
for(auto& handler : dj_event_handlers)
|
||||
for(auto& handler : _dj_event_handlers)
|
||||
if(handler.second->condition(report))
|
||||
handler.second->callback(report);
|
||||
}
|
||||
|
||||
void Receiver::handleHidppEvent(hidpp::Report &report)
|
||||
{
|
||||
for(auto& handler : hidpp_event_handlers)
|
||||
for(auto& handler : _hidpp_event_handlers)
|
||||
if(handler.second->condition(report))
|
||||
handler.second->callback(report);
|
||||
}
|
||||
|
@ -243,39 +242,39 @@ void Receiver::handleHidppEvent(hidpp::Report &report)
|
|||
void Receiver::addDjEventHandler(const std::string& nickname,
|
||||
const std::shared_ptr<EventHandler>& handler)
|
||||
{
|
||||
auto it = dj_event_handlers.find(nickname);
|
||||
assert(it == dj_event_handlers.end());
|
||||
dj_event_handlers.emplace(nickname, handler);
|
||||
auto it = _dj_event_handlers.find(nickname);
|
||||
assert(it == _dj_event_handlers.end());
|
||||
_dj_event_handlers.emplace(nickname, handler);
|
||||
}
|
||||
|
||||
void Receiver::removeDjEventHandler(const std::string &nickname)
|
||||
{
|
||||
dj_event_handlers.erase(nickname);
|
||||
_dj_event_handlers.erase(nickname);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::shared_ptr<EventHandler>>&
|
||||
Receiver::djEventHandlers()
|
||||
{
|
||||
return dj_event_handlers;
|
||||
return _dj_event_handlers;
|
||||
}
|
||||
|
||||
void Receiver::addHidppEventHandler(const std::string& nickname,
|
||||
const std::shared_ptr<hidpp::EventHandler>& handler)
|
||||
{
|
||||
auto it = hidpp_event_handlers.find(nickname);
|
||||
assert(it == hidpp_event_handlers.end());
|
||||
hidpp_event_handlers.emplace(nickname, handler);
|
||||
auto it = _hidpp_event_handlers.find(nickname);
|
||||
assert(it == _hidpp_event_handlers.end());
|
||||
_hidpp_event_handlers.emplace(nickname, handler);
|
||||
}
|
||||
|
||||
void Receiver::removeHidppEventHandler(const std::string &nickname)
|
||||
{
|
||||
hidpp_event_handlers.erase(nickname);
|
||||
_hidpp_event_handlers.erase(nickname);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::shared_ptr<hidpp::EventHandler>>&
|
||||
Receiver::hidppEventHandlers()
|
||||
{
|
||||
return hidpp_event_handlers;
|
||||
return _hidpp_event_handlers;
|
||||
}
|
||||
|
||||
void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
|
||||
|
@ -290,61 +289,61 @@ void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function,
|
|||
|
||||
std::copy(params.begin(), params.end(), request.paramBegin());
|
||||
|
||||
raw_device->sendReportNoResponse(request.rawData());
|
||||
_raw_device->sendReportNoResponse(request.rawData());
|
||||
}
|
||||
|
||||
void Receiver::listen()
|
||||
{
|
||||
if(!raw_device->isListening())
|
||||
std::thread{[=]() { raw_device->listen(); }}.detach();
|
||||
if(!_raw_device->isListening())
|
||||
std::thread{[=]() { _raw_device->listen(); }}.detach();
|
||||
|
||||
if(raw_device->eventHandlers().find("RECV_HIDPP") ==
|
||||
raw_device->eventHandlers().end()) {
|
||||
if(_raw_device->eventHandlers().find("RECV_HIDPP") ==
|
||||
_raw_device->eventHandlers().end()) {
|
||||
// Pass all HID++ events on DefaultDevice to handleHidppEvent
|
||||
std::shared_ptr<RawEventHandler> hidppRawEventHandler =
|
||||
std::make_shared<RawEventHandler>();
|
||||
hidppRawEventHandler->condition = [](std::vector<uint8_t>& report)->bool
|
||||
std::shared_ptr<raw::RawEventHandler> hidpp_handler =
|
||||
std::make_shared<raw::RawEventHandler>();
|
||||
hidpp_handler->condition = [](std::vector<uint8_t>& report)->bool
|
||||
{
|
||||
return (report[hidpp::Offset::Type] == hidpp::Report::Type::Short ||
|
||||
report[hidpp::Offset::Type] == hidpp::Report::Type::Long);
|
||||
};
|
||||
hidppRawEventHandler->callback = [this](std::vector<uint8_t>& report)->void
|
||||
{
|
||||
hidpp_handler->callback = [this](std::vector<uint8_t>& report)
|
||||
->void {
|
||||
hidpp::Report _report(report);
|
||||
this->handleHidppEvent(_report);
|
||||
};
|
||||
raw_device->addEventHandler("RECV_HIDPP", hidppRawEventHandler);
|
||||
_raw_device->addEventHandler("RECV_HIDPP", hidpp_handler);
|
||||
}
|
||||
|
||||
if(raw_device->eventHandlers().find("RECV_DJ") ==
|
||||
raw_device->eventHandlers().end()) {
|
||||
// Pass all DJ events with device index to handleHidppEvent
|
||||
std::shared_ptr<RawEventHandler> djRawEventHandler =
|
||||
std::make_shared<RawEventHandler>();
|
||||
djRawEventHandler->condition = [](std::vector<uint8_t>& report)->bool
|
||||
if(_raw_device->eventHandlers().find("RECV_DJ") ==
|
||||
_raw_device->eventHandlers().end()) {
|
||||
// Pass all DJ events with device index to handleDjEvent
|
||||
std::shared_ptr<raw::RawEventHandler> dj_handler =
|
||||
std::make_shared<raw::RawEventHandler>();
|
||||
dj_handler->condition = [](std::vector<uint8_t>& report)->bool
|
||||
{
|
||||
return (report[Offset::Type] == Report::Type::Short ||
|
||||
report[Offset::Type] == Report::Type::Long);
|
||||
};
|
||||
djRawEventHandler->callback = [this](std::vector<uint8_t>& report)->void
|
||||
dj_handler->callback = [this](std::vector<uint8_t>& report)->void
|
||||
{
|
||||
Report _report(report);
|
||||
this->handleDjEvent(_report);
|
||||
};
|
||||
raw_device->addEventHandler("RECV_DJ", djRawEventHandler);
|
||||
_raw_device->addEventHandler("RECV_DJ", dj_handler);
|
||||
}
|
||||
}
|
||||
|
||||
void Receiver::stopListening()
|
||||
{
|
||||
raw_device->removeEventHandler("RECV_HIDPP");
|
||||
raw_device->removeEventHandler("RECV_DJ");
|
||||
_raw_device->removeEventHandler("RECV_HIDPP");
|
||||
_raw_device->removeEventHandler("RECV_DJ");
|
||||
|
||||
if(raw_device->eventHandlers().empty())
|
||||
raw_device->stopListener();
|
||||
if(_raw_device->eventHandlers().empty())
|
||||
_raw_device->stopListener();
|
||||
}
|
||||
|
||||
std::shared_ptr<raw::RawDevice> Receiver::rawDevice() const
|
||||
{
|
||||
return raw_device;
|
||||
return _raw_device;
|
||||
}
|
|
@ -25,7 +25,7 @@ namespace dj
|
|||
NoDJReports
|
||||
};
|
||||
explicit InvalidReceiver(Reason reason);
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
Reason code() const noexcept;
|
||||
private:
|
||||
Reason _reason;
|
||||
|
@ -73,15 +73,15 @@ namespace dj
|
|||
PairingInfo = 0xb5
|
||||
};
|
||||
|
||||
struct notification_flags
|
||||
struct NotificationFlags
|
||||
{
|
||||
bool device_battery_status;
|
||||
bool receiver_wireless_notifications;
|
||||
bool receiver_software_present;
|
||||
bool deviceBatteryStatus;
|
||||
bool receiverWirelessNotifications;
|
||||
bool receiverSoftwarePresent;
|
||||
};
|
||||
|
||||
notification_flags getHidppNotifications();
|
||||
void enableHidppNotifications(notification_flags flags);
|
||||
NotificationFlags getHidppNotifications();
|
||||
void enableHidppNotifications(NotificationFlags flags);
|
||||
|
||||
void enumerateHidpp();
|
||||
uint8_t getConnectionState(hidpp::DeviceIndex index);
|
||||
|
@ -142,11 +142,11 @@ namespace dj
|
|||
void handleHidppEvent(hidpp::Report& report);
|
||||
|
||||
std::map<std::string, std::shared_ptr<EventHandler>>
|
||||
dj_event_handlers;
|
||||
_dj_event_handlers;
|
||||
std::map<std::string, std::shared_ptr<hidpp::EventHandler>>
|
||||
hidpp_event_handlers;
|
||||
_hidpp_event_handlers;
|
||||
|
||||
std::shared_ptr<raw::RawDevice> raw_device;
|
||||
std::shared_ptr<raw::RawDevice> _raw_device;
|
||||
hidpp10::Device _hidpp10_device;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ ReceiverMonitor::ReceiverMonitor(std::string path) : _receiver (
|
|||
assert(_receiver->djEventHandlers().find("RECVMON") ==
|
||||
_receiver->djEventHandlers().end());
|
||||
|
||||
Receiver::notification_flags notification_flags{
|
||||
Receiver::NotificationFlags notification_flags{
|
||||
true,
|
||||
true,
|
||||
true};
|
||||
|
@ -25,16 +25,15 @@ void ReceiverMonitor::run()
|
|||
_receiver->listen();
|
||||
|
||||
if(_receiver->hidppEventHandlers().find("RECVMON") ==
|
||||
_receiver->hidppEventHandlers().end())
|
||||
{
|
||||
std::shared_ptr<hidpp::EventHandler> eventHandler =
|
||||
_receiver->hidppEventHandlers().end()) {
|
||||
std::shared_ptr<hidpp::EventHandler> event_handler =
|
||||
std::make_shared<hidpp::EventHandler>();
|
||||
eventHandler->condition = [](hidpp::Report &report) -> bool {
|
||||
event_handler->condition = [](hidpp::Report &report) -> bool {
|
||||
return (report.subId() == Receiver::DeviceConnection ||
|
||||
report.subId() == Receiver::DeviceDisconnection);
|
||||
};
|
||||
|
||||
eventHandler->callback = [this](hidpp::Report &report) -> void {
|
||||
event_handler->callback = [this](hidpp::Report &report) -> void {
|
||||
/* Running in a new thread prevents deadlocks since the
|
||||
* receiver may be enumerating.
|
||||
*/
|
||||
|
@ -48,7 +47,7 @@ void ReceiverMonitor::run()
|
|||
}, report}.detach();
|
||||
};
|
||||
|
||||
_receiver->addHidppEventHandler("RECVMON", eventHandler);
|
||||
_receiver->addHidppEventHandler("RECVMON", event_handler);
|
||||
}
|
||||
|
||||
enumerate();
|
||||
|
|
|
@ -28,37 +28,36 @@ static const std::array<uint8_t, 34> DJReportDesc = {
|
|||
|
||||
bool dj::supportsDjReports(std::vector<uint8_t>&& rdesc)
|
||||
{
|
||||
auto it = std::search(rdesc.begin(), rdesc.end(), DJReportDesc.begin(), DJReportDesc.end());
|
||||
auto it = std::search(rdesc.begin(), rdesc.end(),
|
||||
DJReportDesc.begin(), DJReportDesc.end());
|
||||
return it != rdesc.end();
|
||||
}
|
||||
|
||||
Report::Report(std::vector<uint8_t>& data) : _data (data)
|
||||
{
|
||||
switch(data[Offset::Type])
|
||||
{
|
||||
case ReportType::Short:
|
||||
_data.resize(HeaderLength+ShortParamLength);
|
||||
break;
|
||||
case ReportType::Long:
|
||||
_data.resize(HeaderLength+LongParamLength);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
switch(data[Offset::Type]) {
|
||||
case ReportType::Short:
|
||||
_data.resize(HeaderLength+ShortParamLength);
|
||||
break;
|
||||
case ReportType::Long:
|
||||
_data.resize(HeaderLength+LongParamLength);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
Report::Report(Report::Type type, hidpp::DeviceIndex index, uint8_t feature)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case ReportType::Short:
|
||||
_data.resize(HeaderLength+ShortParamLength);
|
||||
break;
|
||||
case ReportType::Long:
|
||||
_data.resize(HeaderLength+LongParamLength);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
switch(type) {
|
||||
case ReportType::Short:
|
||||
_data.resize(HeaderLength+ShortParamLength);
|
||||
break;
|
||||
case ReportType::Long:
|
||||
_data.resize(HeaderLength+LongParamLength);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
|
||||
_data[Offset::Type] = type;
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include "defs.h"
|
||||
#include "../hidpp/defs.h"
|
||||
|
||||
namespace logid::backend::dj
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace dj
|
||||
{
|
||||
namespace Offset
|
||||
{
|
||||
|
@ -33,6 +35,6 @@ namespace logid::backend::dj
|
|||
private:
|
||||
std::vector<uint8_t> _data;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_DJ_REPORT_H
|
||||
|
|
|
@ -13,16 +13,15 @@ using namespace logid::backend::hidpp;
|
|||
|
||||
const char* Device::InvalidDevice::what() const noexcept
|
||||
{
|
||||
switch(_reason)
|
||||
{
|
||||
case NoHIDPPReport:
|
||||
return "Invalid HID++ device";
|
||||
case InvalidRawDevice:
|
||||
return "Invalid raw device";
|
||||
case Asleep:
|
||||
return "Device asleep";
|
||||
default:
|
||||
return "Invalid device";
|
||||
switch(_reason) {
|
||||
case NoHIDPPReport:
|
||||
return "Invalid HID++ device";
|
||||
case InvalidRawDevice:
|
||||
return "Invalid raw device";
|
||||
case Asleep:
|
||||
return "Device asleep";
|
||||
default:
|
||||
return "Invalid device";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,10 +57,25 @@ Device::Device(std::shared_ptr<dj::Receiver> receiver,
|
|||
_init();
|
||||
}
|
||||
|
||||
std::string Device::devicePath() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
DeviceIndex Device::deviceIndex() const
|
||||
{
|
||||
return _index;
|
||||
}
|
||||
|
||||
std::tuple<uint8_t, uint8_t> Device::version() const
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
||||
void Device::_init()
|
||||
{
|
||||
supported_reports = getSupportedReports(_raw_device->reportDescriptor());
|
||||
if(!supported_reports)
|
||||
_supported_reports = getSupportedReports(_raw_device->reportDescriptor());
|
||||
if(!_supported_reports)
|
||||
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
|
||||
|
||||
try {
|
||||
|
@ -101,20 +115,20 @@ Device::~Device()
|
|||
void Device::addEventHandler(const std::string& nickname,
|
||||
const std::shared_ptr<EventHandler>& handler)
|
||||
{
|
||||
auto it = event_handlers.find(nickname);
|
||||
assert(it == event_handlers.end());
|
||||
auto it = _event_handlers.find(nickname);
|
||||
assert(it == _event_handlers.end());
|
||||
|
||||
event_handlers.emplace(nickname, handler);
|
||||
_event_handlers.emplace(nickname, handler);
|
||||
}
|
||||
|
||||
void Device::removeEventHandler(const std::string& nickname)
|
||||
{
|
||||
event_handlers.erase(nickname);
|
||||
_event_handlers.erase(nickname);
|
||||
}
|
||||
|
||||
void Device::handleEvent(Report& report)
|
||||
{
|
||||
for(auto& handler : event_handlers)
|
||||
for(auto& handler : _event_handlers)
|
||||
if(handler.second->condition(report))
|
||||
handler.second->callback(report);
|
||||
}
|
||||
|
@ -123,26 +137,26 @@ Report Device::sendReport(Report& report)
|
|||
{
|
||||
switch(report.type())
|
||||
{
|
||||
case Report::Type::Short:
|
||||
if(!(supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
|
||||
report.setType(Report::Type::Long);
|
||||
break;
|
||||
case Report::Type::Long:
|
||||
/* Report can be truncated, but that isn't a good idea. */
|
||||
assert(supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
|
||||
case Report::Type::Short:
|
||||
if(!(_supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
|
||||
report.setType(Report::Type::Long);
|
||||
break;
|
||||
case Report::Type::Long:
|
||||
/* Report can be truncated, but that isn't a good idea. */
|
||||
assert(_supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
|
||||
}
|
||||
|
||||
auto raw_response = _raw_device->sendReport(report.rawReport());
|
||||
|
||||
Report response(raw_response);
|
||||
|
||||
Report::hidpp10_error hidpp10Error{};
|
||||
if(response.isError10(&hidpp10Error))
|
||||
throw hidpp10::Error(hidpp10Error.error_code);
|
||||
Report::Hidpp10Error hidpp10_error{};
|
||||
if(response.isError10(&hidpp10_error))
|
||||
throw hidpp10::Error(hidpp10_error.error_code);
|
||||
|
||||
Report::hidpp20_error hidpp20Error{};
|
||||
if(response.isError20(&hidpp20Error))
|
||||
throw hidpp10::Error(hidpp20Error.error_code);
|
||||
Report::Hidpp20Error hidpp20_error{};
|
||||
if(response.isError20(&hidpp20_error))
|
||||
throw hidpp10::Error(hidpp20_error.error_code);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
@ -153,20 +167,20 @@ void Device::listen()
|
|||
std::thread{[=]() { _raw_device->listen(); }}.detach();
|
||||
|
||||
// Pass all HID++ events with device index to this device.
|
||||
std::shared_ptr<RawEventHandler> rawEventHandler;
|
||||
rawEventHandler->condition = [this](std::vector<uint8_t>& report)->bool
|
||||
std::shared_ptr<raw::RawEventHandler> handler;
|
||||
handler->condition = [this](std::vector<uint8_t>& report)->bool
|
||||
{
|
||||
return (report[Offset::Type] == Report::Type::Short ||
|
||||
report[Offset::Type] == Report::Type::Long) &&
|
||||
(report[Offset::DeviceIndex] == this->_index);
|
||||
};
|
||||
rawEventHandler->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), rawEventHandler);
|
||||
_raw_device->addEventHandler("DEV_" + std::to_string(_index), handler);
|
||||
}
|
||||
|
||||
void Device::stopListening()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef LOGID_HIDPP_DEVICE_H
|
||||
#define LOGID_HIDPP_DEVICE_H
|
||||
#ifndef LOGID_BACKEND_HIDPP_DEVICE_H
|
||||
#define LOGID_BACKEND_HIDPP_DEVICE_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
@ -44,14 +44,15 @@ namespace hidpp
|
|||
};
|
||||
|
||||
explicit Device(const std::string& path, DeviceIndex index);
|
||||
explicit Device(std::shared_ptr<raw::RawDevice> raw_device, DeviceIndex index);
|
||||
explicit Device(std::shared_ptr<raw::RawDevice> raw_device,
|
||||
DeviceIndex index);
|
||||
explicit Device(std::shared_ptr<dj::Receiver> receiver,
|
||||
hidpp::DeviceConnectionEvent event);
|
||||
~Device();
|
||||
|
||||
std::string devicePath() const { return _path; }
|
||||
DeviceIndex deviceIndex() const { return _index; }
|
||||
std::tuple<uint8_t, uint8_t> version() const { return _version; }
|
||||
std::string devicePath() const;
|
||||
DeviceIndex deviceIndex() const;
|
||||
std::tuple<uint8_t, uint8_t> version() const;
|
||||
|
||||
void listen(); // Runs asynchronously
|
||||
void stopListening();
|
||||
|
@ -70,14 +71,14 @@ namespace hidpp
|
|||
std::shared_ptr<dj::Receiver> _receiver;
|
||||
std::string _path;
|
||||
DeviceIndex _index;
|
||||
uint8_t supported_reports;
|
||||
uint8_t _supported_reports;
|
||||
|
||||
std::tuple<uint8_t, uint8_t> _version;
|
||||
uint16_t _pid;
|
||||
std::string _name;
|
||||
|
||||
std::map<std::string, std::shared_ptr<EventHandler>> event_handlers;
|
||||
std::map<std::string, std::shared_ptr<EventHandler>> _event_handlers;
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif //LOGID_HIDPP_DEVICE_H
|
||||
#endif //LOGID_BACKEND_HIDPP_DEVICE_H
|
|
@ -70,15 +70,19 @@ uint8_t hidpp::getSupportedReports(std::vector<uint8_t>&& rdesc)
|
|||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
auto it = std::search(rdesc.begin(), rdesc.end(), ShortReportDesc.begin(), ShortReportDesc.end());
|
||||
auto it = std::search(rdesc.begin(), rdesc.end(),
|
||||
ShortReportDesc.begin(), ShortReportDesc.end());
|
||||
if(it == rdesc.end())
|
||||
it = std::search(rdesc.begin(), rdesc.end(), ShortReportDesc2.begin(), ShortReportDesc2.end());
|
||||
it = std::search(rdesc.begin(), rdesc.end(),
|
||||
ShortReportDesc2.begin(), ShortReportDesc2.end());
|
||||
if(it != rdesc.end())
|
||||
ret |= HIDPP_REPORT_SHORT_SUPPORTED;
|
||||
|
||||
it = std::search(rdesc.begin(), rdesc.end(), LongReportDesc.begin(), LongReportDesc.end());
|
||||
it = std::search(rdesc.begin(), rdesc.end(),
|
||||
LongReportDesc.begin(), LongReportDesc.end());
|
||||
if(it == rdesc.end())
|
||||
it = std::search(rdesc.begin(), rdesc.end(), LongReportDesc2.begin(), LongReportDesc2.end());
|
||||
it = std::search(rdesc.begin(), rdesc.end(),
|
||||
LongReportDesc2.begin(), LongReportDesc2.end());
|
||||
if(it != rdesc.end())
|
||||
ret |= HIDPP_REPORT_LONG_SUPPORTED;
|
||||
|
||||
|
@ -98,16 +102,15 @@ const char *Report::InvalidReportLength::what() const noexcept
|
|||
Report::Report(Report::Type type, DeviceIndex device_index,
|
||||
uint8_t sub_id, uint8_t address)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
switch(type) {
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
}
|
||||
|
||||
_data[Offset::Type] = type;
|
||||
|
@ -119,25 +122,25 @@ 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)
|
||||
{
|
||||
assert(function <= functionMask);
|
||||
assert(sw_id <= swIdMask);
|
||||
assert(function <= 0x0f);
|
||||
assert(sw_id <= 0x0f);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
switch(type) {
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
}
|
||||
|
||||
_data[Offset::Type] = type;
|
||||
_data[Offset::DeviceIndex] = device_index;
|
||||
_data[Offset::Feature] = feature_index;
|
||||
_data[Offset::Function] = (function & functionMask) << 4 | (sw_id & swIdMask);
|
||||
_data[Offset::Function] = (function & 0x0f) << 4 |
|
||||
(sw_id & 0x0f);
|
||||
}
|
||||
|
||||
Report::Report(const std::vector<uint8_t>& data)
|
||||
|
@ -145,16 +148,15 @@ Report::Report(const std::vector<uint8_t>& data)
|
|||
_data = data;
|
||||
|
||||
// Truncating data is entirely valid here.
|
||||
switch(_data[Offset::Type])
|
||||
{
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
switch(_data[Offset::Type]) {
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,16 +167,15 @@ Report::Type Report::type() const
|
|||
|
||||
void Report::setType(Report::Type type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
switch(type) {
|
||||
case Type::Short:
|
||||
_data.resize(HeaderLength + ShortParamLength);
|
||||
break;
|
||||
case Type::Long:
|
||||
_data.resize(HeaderLength + LongParamLength);
|
||||
break;
|
||||
default:
|
||||
throw InvalidReportID();
|
||||
}
|
||||
|
||||
_data[Offset::Type] = type;
|
||||
|
@ -218,7 +219,7 @@ uint8_t Report::function() const
|
|||
void Report::setFunction(uint8_t function)
|
||||
{
|
||||
_data[Offset::Function] &= 0x0f;
|
||||
_data[Offset::Function] |= (function << 4) & 0x0f;
|
||||
_data[Offset::Function] |= (function & 0x0f) << 4;
|
||||
}
|
||||
|
||||
uint8_t Report::swId() const
|
||||
|
@ -250,7 +251,7 @@ void Report::setParams(const std::vector<uint8_t>& _params)
|
|||
_data[Offset::Parameters + i] = _params[i];
|
||||
}
|
||||
|
||||
bool Report::isError10(Report::hidpp10_error *error)
|
||||
bool Report::isError10(Report::Hidpp10Error *error)
|
||||
{
|
||||
assert(error != nullptr);
|
||||
|
||||
|
@ -265,8 +266,10 @@ bool Report::isError10(Report::hidpp10_error *error)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Report::isError20(Report::hidpp20_error* error)
|
||||
bool Report::isError20(Report::Hidpp20Error* error)
|
||||
{
|
||||
assert(error != nullptr);
|
||||
|
||||
if(_data[Offset::Type] != Type::Long ||
|
||||
_data[Offset::Feature] != hidpp20::ErrorID)
|
||||
return false;
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
#define HIDPP_REPORT_LONG_SUPPORTED 1U<<1U
|
||||
/* Very long reports exist, however they have not been encountered so far */
|
||||
|
||||
namespace logid::backend::hidpp
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace hidpp
|
||||
{
|
||||
uint8_t getSupportedReports(std::vector<uint8_t>&& rdesc);
|
||||
|
||||
|
@ -34,19 +36,17 @@ namespace logid::backend::hidpp
|
|||
{
|
||||
public:
|
||||
InvalidReportID() = default;
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
class InvalidReportLength: public std::exception
|
||||
{
|
||||
public:
|
||||
InvalidReportLength() = default;;
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
static constexpr std::size_t MaxDataLength = 20;
|
||||
static constexpr uint8_t swIdMask = 0x0f;
|
||||
static constexpr uint8_t functionMask = 0x0f;
|
||||
|
||||
Report(Report::Type type, DeviceIndex device_index,
|
||||
uint8_t sub_id,
|
||||
|
@ -85,19 +85,17 @@ namespace logid::backend::hidpp
|
|||
std::vector<uint8_t>::iterator paramEnd() { return _data.end(); }
|
||||
void setParams(const std::vector<uint8_t>& _params);
|
||||
|
||||
struct hidpp10_error
|
||||
struct Hidpp10Error
|
||||
{
|
||||
uint8_t sub_id, address, error_code;
|
||||
};
|
||||
bool isError10(Hidpp10Error* error);
|
||||
|
||||
bool isError10(hidpp10_error* error);
|
||||
|
||||
struct hidpp20_error
|
||||
struct Hidpp20Error
|
||||
{
|
||||
uint8_t feature_index, function, software_id, error_code;
|
||||
};
|
||||
|
||||
bool isError20(hidpp20_error* error);
|
||||
bool isError20(Hidpp20Error* error);
|
||||
|
||||
std::vector<uint8_t> rawReport () const { return _data; }
|
||||
|
||||
|
@ -105,6 +103,6 @@ namespace logid::backend::hidpp
|
|||
private:
|
||||
std::vector<uint8_t> _data;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_HIDPP_REPORT_H
|
|
@ -3,7 +3,9 @@
|
|||
|
||||
#define LOGID_HIDPP_SOFTWARE_ID 0
|
||||
|
||||
namespace logid::backend::hidpp
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace hidpp
|
||||
{
|
||||
namespace ReportType
|
||||
{
|
||||
|
@ -28,6 +30,6 @@ namespace logid::backend::hidpp
|
|||
|
||||
static constexpr std::size_t ShortParamLength = 3;
|
||||
static constexpr std::size_t LongParamLength = 16;
|
||||
}
|
||||
} } }
|
||||
|
||||
#endif //LOGID_HIDPP_DEFS_H
|
|
@ -41,10 +41,11 @@ std::vector<uint8_t> Device::setRegister(uint8_t address,
|
|||
return accessRegister(sub_id, address, params);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address, const std::vector<uint8_t> ¶ms)
|
||||
std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address,
|
||||
const std::vector<uint8_t> ¶ms)
|
||||
{
|
||||
hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ?
|
||||
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
|
||||
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
|
||||
|
||||
hidpp::Report request(type, deviceIndex(), sub_id, address);
|
||||
std::copy(params.begin(), params.end(), request.paramBegin());
|
||||
|
|
|
@ -11,36 +11,35 @@ Error::Error(uint8_t code): _code(code)
|
|||
|
||||
const char* Error::what() const noexcept
|
||||
{
|
||||
switch(_code)
|
||||
{
|
||||
case Success:
|
||||
return "Success";
|
||||
case InvalidSubID:
|
||||
return "Invalid sub ID";
|
||||
case InvalidAddress:
|
||||
return "Invalid address";
|
||||
case InvalidValue:
|
||||
return "Invalid value";
|
||||
case ConnectFail:
|
||||
return "Connection failure";
|
||||
case TooManyDevices:
|
||||
return "Too many devices";
|
||||
case AlreadyExists:
|
||||
return "Already exists";
|
||||
case Busy:
|
||||
return "Busy";
|
||||
case UnknownDevice:
|
||||
return "Unknown device";
|
||||
case ResourceError:
|
||||
return "Resource error";
|
||||
case RequestUnavailable:
|
||||
return "Request unavailable";
|
||||
case InvalidParameterValue:
|
||||
return "Invalid parameter value";
|
||||
case WrongPINCode:
|
||||
return "Wrong PIN code";
|
||||
default:
|
||||
return std::string("Unknown error code " + std::to_string(_code)).c_str();
|
||||
switch(_code) {
|
||||
case Success:
|
||||
return "Success";
|
||||
case InvalidSubID:
|
||||
return "Invalid sub ID";
|
||||
case InvalidAddress:
|
||||
return "Invalid address";
|
||||
case InvalidValue:
|
||||
return "Invalid value";
|
||||
case ConnectFail:
|
||||
return "Connection failure";
|
||||
case TooManyDevices:
|
||||
return "Too many devices";
|
||||
case AlreadyExists:
|
||||
return "Already exists";
|
||||
case Busy:
|
||||
return "Busy";
|
||||
case UnknownDevice:
|
||||
return "Unknown device";
|
||||
case ResourceError:
|
||||
return "Resource error";
|
||||
case RequestUnavailable:
|
||||
return "Request unavailable";
|
||||
case InvalidParameterValue:
|
||||
return "Invalid parameter value";
|
||||
case WrongPINCode:
|
||||
return "Wrong PIN code";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ namespace hidpp10 {
|
|||
WrongPINCode = 0x0C
|
||||
};
|
||||
|
||||
Error(uint8_t code);
|
||||
explicit Error(uint8_t code);
|
||||
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
uint8_t code() const noexcept;
|
||||
|
||||
private:
|
||||
|
|
|
@ -11,32 +11,31 @@ Error::Error(uint8_t code) : _code (code)
|
|||
|
||||
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();
|
||||
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 "Unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace hidpp20 {
|
|||
UnknownDevice = 10
|
||||
};
|
||||
|
||||
Error(uint8_t code);
|
||||
explicit Error(uint8_t code);
|
||||
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
uint8_t code() const noexcept;
|
||||
|
||||
private:
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace hidpp20 {
|
|||
{
|
||||
public:
|
||||
explicit UnsupportedFeature(uint16_t ID) : _f_id (ID) {}
|
||||
virtual const char* what() const noexcept;
|
||||
const char* what() const noexcept override;
|
||||
uint16_t code() const noexcept;
|
||||
private:
|
||||
uint16_t _f_id;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace hidpp20
|
|||
GetDeviceName = 1
|
||||
};
|
||||
|
||||
DeviceName(Device* device);
|
||||
explicit DeviceName(Device* device);
|
||||
|
||||
uint8_t getNameLength();
|
||||
std::string getName();
|
||||
|
@ -33,7 +33,7 @@ namespace hidpp20
|
|||
static const uint16_t ID = FeatureID::DEVICE_NAME;
|
||||
virtual uint16_t getID() { return ID; }
|
||||
|
||||
EssentialDeviceName(hidpp::Device* device);
|
||||
explicit EssentialDeviceName(hidpp::Device* device);
|
||||
|
||||
uint8_t getNameLength();
|
||||
std::string getName();
|
||||
|
|
|
@ -14,7 +14,8 @@ std::vector<uint8_t> _genGetFeatureParams(uint16_t feature_id)
|
|||
return params;
|
||||
}
|
||||
|
||||
feature_info _genGetFeatureInfo(uint16_t feature_id, std::vector<uint8_t> response)
|
||||
feature_info _genGetFeatureInfo(uint16_t feature_id,
|
||||
std::vector<uint8_t> response)
|
||||
{
|
||||
feature_info info{};
|
||||
info.feature_id = response[0];
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace hidpp20
|
|||
Ping = 1
|
||||
};
|
||||
|
||||
Root(Device* device);
|
||||
explicit Root(Device* device);
|
||||
|
||||
feature_info getFeature (uint16_t feature_id);
|
||||
std::tuple<uint8_t, uint8_t> getVersion();
|
||||
|
@ -40,9 +40,9 @@ namespace hidpp20
|
|||
static const uint16_t ID = FeatureID::ROOT;
|
||||
virtual uint16_t getID() { return ID; }
|
||||
|
||||
EssentialRoot(hidpp::Device* device);
|
||||
explicit EssentialRoot(hidpp::Device* device);
|
||||
|
||||
feature_info getFeature (uint16_t feature_id);
|
||||
feature_info getFeature(uint16_t feature_id);
|
||||
std::tuple<uint8_t, uint8_t> getVersion();
|
||||
};
|
||||
}}}
|
||||
|
|
|
@ -13,40 +13,39 @@ using namespace logid::backend::raw;
|
|||
|
||||
DeviceMonitor::DeviceMonitor()
|
||||
{
|
||||
if(-1 == pipe(monitor_pipe))
|
||||
throw std::system_error(errno, std::system_category(), "pipe creation failed");
|
||||
if(-1 == pipe(_pipe))
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"pipe creation failed");
|
||||
|
||||
udev_context = udev_new();
|
||||
if(!udev_context)
|
||||
_udev_context = udev_new();
|
||||
if(!_udev_context)
|
||||
throw std::runtime_error("udev_new failed");
|
||||
}
|
||||
|
||||
DeviceMonitor::~DeviceMonitor()
|
||||
{
|
||||
bool is_running = running.try_lock();
|
||||
if(is_running)
|
||||
running.unlock();
|
||||
else
|
||||
this->stop();
|
||||
this->stop();
|
||||
|
||||
udev_unref(udev_context);
|
||||
udev_unref(_udev_context);
|
||||
|
||||
for(int i : monitor_pipe)
|
||||
for(int i : _pipe)
|
||||
close(i);
|
||||
}
|
||||
|
||||
void DeviceMonitor::run()
|
||||
{
|
||||
int ret;
|
||||
const std::lock_guard<std::mutex> run_lock(running);
|
||||
std::lock_guard<std::mutex> lock(_running);
|
||||
|
||||
struct udev_monitor* monitor = udev_monitor_new_from_netlink(udev_context, "udev");
|
||||
struct udev_monitor* monitor = udev_monitor_new_from_netlink(_udev_context,
|
||||
"udev");
|
||||
if(!monitor)
|
||||
throw std::runtime_error("udev_monitor_new_from_netlink failed");
|
||||
|
||||
ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw", nullptr);
|
||||
ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "hidraw",
|
||||
nullptr);
|
||||
if (0 != ret)
|
||||
throw std::system_error (-ret, std::system_category (),
|
||||
throw std::system_error (-ret, std::system_category(),
|
||||
"udev_monitor_filter_add_match_subsystem_devtype");
|
||||
|
||||
ret = udev_monitor_enable_receiving(monitor);
|
||||
|
@ -57,20 +56,27 @@ void DeviceMonitor::run()
|
|||
this->enumerate();
|
||||
|
||||
int fd = udev_monitor_get_fd(monitor);
|
||||
while (true) {
|
||||
|
||||
_run_monitor = true;
|
||||
while (_run_monitor) {
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(monitor_pipe[0], &fds);
|
||||
FD_SET(_pipe[0], &fds);
|
||||
FD_SET(fd, &fds);
|
||||
if (-1 == select (std::max (monitor_pipe[0], fd)+1, &fds, nullptr, nullptr, nullptr)) {
|
||||
|
||||
if (-1 == select (std::max (_pipe[0], fd)+1, &fds, nullptr,
|
||||
nullptr, nullptr)) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
throw std::system_error (errno, std::system_category(), "udev_monitor select");
|
||||
throw std::system_error (errno, std::system_category(),
|
||||
"udev_monitor select");
|
||||
}
|
||||
|
||||
if (FD_ISSET(fd, &fds)) {
|
||||
struct udev_device *device = udev_monitor_receive_device(monitor);
|
||||
std::string action = udev_device_get_action(device);
|
||||
std::string devnode = udev_device_get_devnode(device);
|
||||
|
||||
if (action == "add")
|
||||
std::thread([this](const std::string name) {
|
||||
this->addDevice(name);
|
||||
|
@ -79,12 +85,13 @@ void DeviceMonitor::run()
|
|||
std::thread([this](const std::string name) {
|
||||
this->removeDevice(name);
|
||||
}, devnode).detach();
|
||||
|
||||
udev_device_unref (device);
|
||||
}
|
||||
if (FD_ISSET(monitor_pipe[0], &fds)) {
|
||||
if (FD_ISSET(_pipe[0], &fds)) {
|
||||
char c;
|
||||
if (-1 == read(monitor_pipe[0], &c, sizeof (char)))
|
||||
throw std::system_error (errno, std::system_category (),
|
||||
if (-1 == read(_pipe[0], &c, sizeof (char)))
|
||||
throw std::system_error (errno, std::system_category(),
|
||||
"read pipe");
|
||||
break;
|
||||
}
|
||||
|
@ -93,13 +100,14 @@ void DeviceMonitor::run()
|
|||
|
||||
void DeviceMonitor::stop()
|
||||
{
|
||||
|
||||
_run_monitor = false;
|
||||
std::lock_guard<std::mutex> lock(_running);
|
||||
}
|
||||
|
||||
void DeviceMonitor::enumerate()
|
||||
{
|
||||
int ret;
|
||||
struct udev_enumerate* udev_enum = udev_enumerate_new(udev_context);
|
||||
struct udev_enumerate* udev_enum = udev_enumerate_new(_udev_context);
|
||||
ret = udev_enumerate_add_match_subsystem(udev_enum, "hidraw");
|
||||
if(0 != ret)
|
||||
throw std::system_error(-ret, std::system_category(),
|
||||
|
@ -112,11 +120,10 @@ void DeviceMonitor::enumerate()
|
|||
|
||||
struct udev_list_entry* udev_enum_entry;
|
||||
udev_list_entry_foreach(udev_enum_entry,
|
||||
udev_enumerate_get_list_entry(udev_enum))
|
||||
{
|
||||
udev_enumerate_get_list_entry(udev_enum)) {
|
||||
const char* name = udev_list_entry_get_name(udev_enum_entry);
|
||||
|
||||
struct udev_device* device = udev_device_new_from_syspath(udev_context,
|
||||
struct udev_device* device = udev_device_new_from_syspath(_udev_context,
|
||||
name);
|
||||
if(!device)
|
||||
throw std::runtime_error("udev_device_new_from_syspath failed");
|
||||
|
|
|
@ -3,13 +3,16 @@
|
|||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <libudev.h>
|
||||
}
|
||||
|
||||
namespace logid::backend::raw
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace raw
|
||||
{
|
||||
class DeviceMonitor
|
||||
{
|
||||
|
@ -23,10 +26,11 @@ namespace logid::backend::raw
|
|||
virtual void addDevice(std::string device) = 0;
|
||||
virtual void removeDevice(std::string device) = 0;
|
||||
private:
|
||||
struct udev* udev_context;
|
||||
int monitor_pipe[2];
|
||||
std::mutex running;
|
||||
struct udev* _udev_context;
|
||||
int _pipe[2];
|
||||
std::atomic<bool> _run_monitor;
|
||||
std::mutex _running;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_RAW_DEVICEMONITOR_H
|
|
@ -7,12 +7,13 @@
|
|||
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
#define MAX_DATA_LENGTH 32
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <cassert>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
@ -25,105 +26,116 @@ using namespace std::chrono;
|
|||
|
||||
bool RawDevice::supportedReport(uint8_t id, uint8_t length)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case hidpp::ReportType::Short:
|
||||
return length == (hidpp::ShortParamLength +
|
||||
hidpp::Report::HeaderLength);
|
||||
case hidpp::ReportType::Long:
|
||||
return length == (hidpp::LongParamLength +
|
||||
hidpp::Report::HeaderLength);
|
||||
case dj::ReportType::Short:
|
||||
return length == (dj::ShortParamLength + dj::HeaderLength);
|
||||
case dj::ReportType::Long:
|
||||
return length == (dj::LongParamLength + dj::HeaderLength);
|
||||
default:
|
||||
return false;
|
||||
switch(id) {
|
||||
case hidpp::ReportType::Short:
|
||||
return length == (hidpp::ShortParamLength +
|
||||
hidpp::Report::HeaderLength);
|
||||
case hidpp::ReportType::Long:
|
||||
return length == (hidpp::LongParamLength +
|
||||
hidpp::Report::HeaderLength);
|
||||
case dj::ReportType::Short:
|
||||
return length == (dj::ShortParamLength + dj::HeaderLength);
|
||||
case dj::ReportType::Long:
|
||||
return length == (dj::LongParamLength + dj::HeaderLength);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
RawDevice::RawDevice(std::string path) : _path (std::move(path)),
|
||||
_continue_listen (false)
|
||||
{
|
||||
int ret;
|
||||
|
||||
fd = ::open(path.c_str(), O_RDWR);
|
||||
if (fd == -1)
|
||||
_fd = ::open(_path.c_str(), O_RDWR);
|
||||
if (_fd == -1)
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"RawDevice open failed");
|
||||
|
||||
hidraw_devinfo devinfo{};
|
||||
if (-1 == ::ioctl(fd, HIDIOCGRAWINFO, &devinfo))
|
||||
{
|
||||
if (-1 == ::ioctl(_fd, HIDIOCGRAWINFO, &devinfo)) {
|
||||
int err = errno;
|
||||
::close(fd);
|
||||
::close(_fd);
|
||||
throw std::system_error(err, std::system_category(),
|
||||
"RawDevice HIDIOCGRAWINFO failed");
|
||||
}
|
||||
vid = devinfo.vendor;
|
||||
pid = devinfo.product;
|
||||
_vid = devinfo.vendor;
|
||||
_pid = devinfo.product;
|
||||
|
||||
char name_buf[256];
|
||||
if (-1 == (ret = ::ioctl(fd, HIDIOCGRAWNAME(sizeof(name_buf)), name_buf)))
|
||||
{
|
||||
if (-1 == (ret = ::ioctl(_fd, HIDIOCGRAWNAME(sizeof(name_buf)), name_buf)
|
||||
)) {
|
||||
int err = errno;
|
||||
::close(fd);
|
||||
::close(_fd);
|
||||
throw std::system_error(err, std::system_category(),
|
||||
"RawDevice HIDIOCGRAWNAME failed");
|
||||
}
|
||||
_name.assign(name_buf, ret - 1);
|
||||
|
||||
hidraw_report_descriptor _rdesc{};
|
||||
if (-1 == ::ioctl(fd, HIDIOCGRDESCSIZE, &_rdesc.size))
|
||||
{
|
||||
if (-1 == ::ioctl(_fd, HIDIOCGRDESCSIZE, &_rdesc.size)) {
|
||||
int err = errno;
|
||||
::close(fd);
|
||||
::close(_fd);
|
||||
throw std::system_error(err, std::system_category(),
|
||||
"RawDevice HIDIOCGRDESCSIZE failed");
|
||||
}
|
||||
if (-1 == ::ioctl(fd, HIDIOCGRDESC, &_rdesc))
|
||||
{
|
||||
if (-1 == ::ioctl(_fd, HIDIOCGRDESC, &_rdesc)) {
|
||||
int err = errno;
|
||||
::close(fd);
|
||||
::close(_fd);
|
||||
throw std::system_error(err, std::system_category(),
|
||||
"RawDevice HIDIOCGRDESC failed");
|
||||
}
|
||||
rdesc = std::vector<uint8_t>(_rdesc.value, _rdesc.value + _rdesc.size);
|
||||
|
||||
if (-1 == ::pipe(dev_pipe))
|
||||
{
|
||||
if (-1 == ::pipe(_pipe)) {
|
||||
int err = errno;
|
||||
close(fd);
|
||||
close(_fd);
|
||||
throw std::system_error(err, std::system_category(),
|
||||
"RawDevice pipe open failed");
|
||||
}
|
||||
|
||||
continue_listen = false;
|
||||
_continue_listen = false;
|
||||
}
|
||||
|
||||
RawDevice::~RawDevice()
|
||||
{
|
||||
if(fd != -1)
|
||||
if(_fd != -1)
|
||||
{
|
||||
::close(fd);
|
||||
::close(dev_pipe[0]);
|
||||
::close(dev_pipe[1]);
|
||||
::close(_fd);
|
||||
::close(_pipe[0]);
|
||||
::close(_pipe[1]);
|
||||
}
|
||||
}
|
||||
std::string RawDevice::hidrawPath() const
|
||||
{
|
||||
return _path;
|
||||
}
|
||||
|
||||
std::string RawDevice::name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
uint16_t RawDevice::vendorId() const
|
||||
{
|
||||
return _vid;
|
||||
}
|
||||
|
||||
uint16_t RawDevice::productId() const
|
||||
{
|
||||
return _pid;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> RawDevice::sendReport(const std::vector<uint8_t>& report)
|
||||
{
|
||||
/* If the listener will stop, handle I/O manually.
|
||||
* 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();
|
||||
write_queue.push(&task);
|
||||
_io_queue.push(&task);
|
||||
return f.get();
|
||||
}
|
||||
else
|
||||
|
@ -135,14 +147,13 @@ void RawDevice::sendReportNoResponse(const std::vector<uint8_t>& report)
|
|||
{
|
||||
/* If the listener will stop, handle I/O manually.
|
||||
* Otherwise, push to queue and wait for result. */
|
||||
if(continue_listen)
|
||||
{
|
||||
if(_continue_listen) {
|
||||
std::packaged_task<std::vector<uint8_t>()> task([this, report]() {
|
||||
this->_sendReport(report);
|
||||
return std::vector<uint8_t>();
|
||||
});
|
||||
auto f = task.get_future();
|
||||
write_queue.push(&task);
|
||||
_io_queue.push(&task);
|
||||
f.get();
|
||||
}
|
||||
else
|
||||
|
@ -153,27 +164,23 @@ std::vector<uint8_t> RawDevice::_respondToReport
|
|||
(const std::vector<uint8_t>& request)
|
||||
{
|
||||
_sendReport(request);
|
||||
while(true)
|
||||
{
|
||||
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])
|
||||
{
|
||||
if(continue_listen)
|
||||
this->handleEvent(response);
|
||||
if(response[1] != request[1]) {
|
||||
if(_continue_listen)
|
||||
this->_handleEvent(response);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(hidpp::ReportType::Short == request[0] ||
|
||||
hidpp::ReportType::Long == request[0])
|
||||
{
|
||||
hidpp::ReportType::Long == request[0]) {
|
||||
if(hidpp::ReportType::Short != response[0] &&
|
||||
hidpp::ReportType::Long != response[0])
|
||||
{
|
||||
if(continue_listen)
|
||||
this->handleEvent(response);
|
||||
hidpp::ReportType::Long != response[0]) {
|
||||
if(_continue_listen)
|
||||
this->_handleEvent(response);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -183,17 +190,13 @@ std::vector<uint8_t> RawDevice::_respondToReport
|
|||
|
||||
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])
|
||||
{
|
||||
} else if(dj::ReportType::Short == request[0] ||
|
||||
dj::ReportType::Long == request[0]) {
|
||||
//Error; leave to device ot handle
|
||||
if(0x7f == response[2])
|
||||
return response;
|
||||
|
@ -201,16 +204,16 @@ std::vector<uint8_t> RawDevice::_respondToReport
|
|||
return response;
|
||||
}
|
||||
|
||||
if(continue_listen)
|
||||
this->handleEvent(response);
|
||||
if(_continue_listen)
|
||||
this->_handleEvent(response);
|
||||
}
|
||||
}
|
||||
|
||||
int RawDevice::_sendReport(const std::vector<uint8_t>& report)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dev_io);
|
||||
std::lock_guard<std::mutex> lock(_dev_io);
|
||||
if(logid::global_verbosity == LogLevel::RAWREPORT) {
|
||||
printf("[RAWREPORT] %s OUT: ", path.c_str());
|
||||
printf("[RAWREPORT] %s OUT: ", _path.c_str());
|
||||
for(auto &i : report)
|
||||
printf("%02x ", i);
|
||||
printf("\n");
|
||||
|
@ -218,11 +221,11 @@ int RawDevice::_sendReport(const std::vector<uint8_t>& report)
|
|||
|
||||
assert(supportedReport(report[0], report.size()));
|
||||
|
||||
int ret = ::write(fd, report.data(), report.size());
|
||||
int ret = ::write(_fd, report.data(), report.size());
|
||||
if(ret == -1) {
|
||||
///TODO: This seems like a hacky solution
|
||||
// Try again before failing
|
||||
ret = ::write(fd, report.data(), report.size());
|
||||
ret = ::write(_fd, report.data(), report.size());
|
||||
if(ret == -1)
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"_sendReport write failed");
|
||||
|
@ -233,7 +236,7 @@ int RawDevice::_sendReport(const std::vector<uint8_t>& report)
|
|||
|
||||
int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLength)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(dev_io);
|
||||
std::lock_guard<std::mutex> lock(_dev_io);
|
||||
int ret;
|
||||
report.resize(maxDataLength);
|
||||
|
||||
|
@ -243,10 +246,10 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
|
|||
fd_set fds;
|
||||
do {
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
FD_SET(dev_pipe[0], &fds);
|
||||
FD_SET(_fd, &fds);
|
||||
FD_SET(_pipe[0], &fds);
|
||||
|
||||
ret = select(std::max(fd, dev_pipe[0]) + 1,
|
||||
ret = select(std::max(_fd, _pipe[0]) + 1,
|
||||
&fds, nullptr, nullptr,
|
||||
(HIDPP_IO_TIMEOUT.count() > 0 ? nullptr : &timeout));
|
||||
} while(ret == -1 && errno == EINTR);
|
||||
|
@ -255,19 +258,17 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
|
|||
throw std::system_error(errno, std::system_category(),
|
||||
"_readReport select failed");
|
||||
|
||||
if(FD_ISSET(fd, &fds))
|
||||
{
|
||||
ret = read(fd, report.data(), report.size());
|
||||
if(FD_ISSET(_fd, &fds)) {
|
||||
ret = read(_fd, report.data(), report.size());
|
||||
if(ret == -1)
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"_readReport read failed");
|
||||
report.resize(ret);
|
||||
}
|
||||
|
||||
if(FD_ISSET(dev_pipe[0], &fds))
|
||||
{
|
||||
if(FD_ISSET(_pipe[0], &fds)) {
|
||||
char c;
|
||||
ret = read(dev_pipe[0], &c, sizeof(char));
|
||||
ret = read(_pipe[0], &c, sizeof(char));
|
||||
if(ret == -1)
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"_readReport read pipe failed");
|
||||
|
@ -277,7 +278,7 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
|
|||
throw backend::TimeoutError();
|
||||
|
||||
if(logid::global_verbosity == LogLevel::RAWREPORT) {
|
||||
printf("[RAWREPORT] %s IN: ", path.c_str());
|
||||
printf("[RAWREPORT] %s IN: ", _path.c_str());
|
||||
for(auto &i : report)
|
||||
printf("%02x ", i);
|
||||
printf("\n");
|
||||
|
@ -289,82 +290,79 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
|
|||
void RawDevice::interruptRead()
|
||||
{
|
||||
char c = 0;
|
||||
if(-1 == write(dev_pipe[1], &c, sizeof(char)))
|
||||
if(-1 == write(_pipe[1], &c, sizeof(char)))
|
||||
throw std::system_error(errno, std::system_category(),
|
||||
"interruptRead write pipe failed");
|
||||
|
||||
// Ensure I/O has halted
|
||||
std::lock_guard<std::mutex> lock(dev_io);
|
||||
std::lock_guard<std::mutex> lock(_dev_io);
|
||||
}
|
||||
|
||||
void RawDevice::listen()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(listening);
|
||||
std::lock_guard<std::mutex> lock(_listening);
|
||||
|
||||
continue_listen = true;
|
||||
while(continue_listen)
|
||||
{
|
||||
while(!write_queue.empty())
|
||||
{
|
||||
auto task = write_queue.front();
|
||||
_continue_listen = true;
|
||||
while(_continue_listen) {
|
||||
while(!_io_queue.empty()) {
|
||||
auto task = _io_queue.front();
|
||||
(*task)();
|
||||
write_queue.pop();
|
||||
_io_queue.pop();
|
||||
}
|
||||
std::vector<uint8_t> report;
|
||||
_readReport(report, MAX_DATA_LENGTH);
|
||||
|
||||
this->handleEvent(report);
|
||||
this->_handleEvent(report);
|
||||
}
|
||||
|
||||
// Listener is stopped, handle I/O queue
|
||||
while(!write_queue.empty())
|
||||
{
|
||||
auto task = write_queue.front();
|
||||
while(!_io_queue.empty()) {
|
||||
auto task = _io_queue.front();
|
||||
(*task)();
|
||||
write_queue.pop();
|
||||
_io_queue.pop();
|
||||
}
|
||||
|
||||
continue_listen = false;
|
||||
_continue_listen = false;
|
||||
}
|
||||
|
||||
void RawDevice::stopListener()
|
||||
{
|
||||
continue_listen = false;
|
||||
_continue_listen = false;
|
||||
interruptRead();
|
||||
}
|
||||
|
||||
void RawDevice::addEventHandler(const std::string& nickname,
|
||||
const std::shared_ptr<RawEventHandler>& handler)
|
||||
const std::shared_ptr<raw::RawEventHandler>& handler)
|
||||
{
|
||||
auto it = event_handlers.find(nickname);
|
||||
assert(it == event_handlers.end());
|
||||
event_handlers.emplace(nickname, handler);
|
||||
auto it = _event_handlers.find(nickname);
|
||||
assert(it == _event_handlers.end());
|
||||
_event_handlers.emplace(nickname, handler);
|
||||
}
|
||||
|
||||
void RawDevice::removeEventHandler(const std::string &nickname)
|
||||
{
|
||||
event_handlers.erase(nickname);
|
||||
_event_handlers.erase(nickname);
|
||||
}
|
||||
|
||||
const std::map<std::string, std::shared_ptr<RawEventHandler>>&
|
||||
const std::map<std::string, std::shared_ptr<raw::RawEventHandler>>&
|
||||
RawDevice::eventHandlers()
|
||||
{
|
||||
return event_handlers;
|
||||
return _event_handlers;
|
||||
}
|
||||
|
||||
void RawDevice::handleEvent(std::vector<uint8_t> &report)
|
||||
void RawDevice::_handleEvent(std::vector<uint8_t> &report)
|
||||
{
|
||||
for(auto& handler : event_handlers)
|
||||
for(auto& handler : _event_handlers)
|
||||
if(handler.second->condition(report))
|
||||
handler.second->callback(report);
|
||||
}
|
||||
|
||||
bool RawDevice::isListening()
|
||||
{
|
||||
bool ret = listening.try_lock();
|
||||
bool ret = _listening.try_lock();
|
||||
|
||||
if(ret)
|
||||
listening.unlock();
|
||||
_listening.unlock();
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <future>
|
||||
#include <set>
|
||||
|
||||
#include "../defs.h"
|
||||
#include "defs.h"
|
||||
#include "../../util/mutex_queue.h"
|
||||
|
||||
#define HIDPP_IO_TIMEOUT std::chrono::seconds(2)
|
||||
|
@ -25,11 +25,11 @@ namespace raw
|
|||
|
||||
explicit RawDevice(std::string path);
|
||||
~RawDevice();
|
||||
std::string hidrawPath() const { return path; }
|
||||
std::string hidrawPath() const;
|
||||
|
||||
std::string name() const { return _name; }
|
||||
uint16_t vendorId() const { return vid; }
|
||||
uint16_t productId() const { return pid; }
|
||||
std::string name() const;
|
||||
uint16_t vendorId() const;
|
||||
uint16_t productId() const;
|
||||
|
||||
std::vector<uint8_t> reportDescriptor() const { return rdesc; }
|
||||
|
||||
|
@ -42,34 +42,35 @@ namespace raw
|
|||
bool isListening();
|
||||
|
||||
void addEventHandler(const std::string& nickname,
|
||||
const std::shared_ptr<backend::RawEventHandler>& handler);
|
||||
const std::shared_ptr<RawEventHandler>& handler);
|
||||
void removeEventHandler(const std::string& nickname);
|
||||
const std::map<std::string, std::shared_ptr<backend::RawEventHandler>>&
|
||||
const std::map<std::string, std::shared_ptr<RawEventHandler>>&
|
||||
eventHandlers();
|
||||
|
||||
private:
|
||||
std::mutex dev_io, listening;
|
||||
std::string path;
|
||||
int fd;
|
||||
int dev_pipe[2];
|
||||
uint16_t vid;
|
||||
uint16_t pid;
|
||||
std::mutex _dev_io, _listening;
|
||||
std::string _path;
|
||||
int _fd;
|
||||
int _pipe[2];
|
||||
uint16_t _vid;
|
||||
uint16_t _pid;
|
||||
std::string _name;
|
||||
std::vector<uint8_t> rdesc;
|
||||
|
||||
std::atomic<bool> continue_listen;
|
||||
std::atomic<bool> _continue_listen;
|
||||
|
||||
std::map<std::string, std::shared_ptr<backend::RawEventHandler>>
|
||||
event_handlers;
|
||||
void handleEvent(std::vector<uint8_t>& report);
|
||||
std::map<std::string, std::shared_ptr<RawEventHandler>>
|
||||
_event_handlers;
|
||||
void _handleEvent(std::vector<uint8_t>& report);
|
||||
|
||||
/* These will only be used internally and processed with a queue */
|
||||
int _sendReport(const std::vector<uint8_t>& report);
|
||||
int _readReport(std::vector<uint8_t>& report, std::size_t maxDataLength);
|
||||
|
||||
std::vector<uint8_t> _respondToReport(const std::vector<uint8_t>& request);
|
||||
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>()>*> _io_queue;
|
||||
};
|
||||
}}}
|
||||
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
#ifndef LOGID_BACKEND_DEFS_H
|
||||
#define LOGID_BACKEND_DEFS_H
|
||||
#ifndef LOGID_BACKEND_RAW_DEFS_H
|
||||
#define LOGID_BACKEND_RAW_DEFS_H
|
||||
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace logid::backend
|
||||
namespace logid {
|
||||
namespace backend {
|
||||
namespace raw
|
||||
{
|
||||
struct RawEventHandler
|
||||
{
|
||||
std::function<bool(std::vector<uint8_t>& )> condition;
|
||||
std::function<void(std::vector<uint8_t>& )> callback;
|
||||
};
|
||||
}
|
||||
}}}
|
||||
|
||||
#endif //LOGID_BACKEND_DEFS_H
|
||||
#endif //LOGID_BACKEND_RAW_DEFS_H
|
|
@ -50,79 +50,71 @@ void logid::reload()
|
|||
}
|
||||
*/
|
||||
|
||||
void read_cli_options(int argc, char** argv)
|
||||
void readCliOptions(int argc, char** argv)
|
||||
{
|
||||
for(int i = 1; i < argc; i++)
|
||||
{
|
||||
for(int i = 1; i < argc; i++) {
|
||||
Option option = Option::None;
|
||||
if(argv[i][0] == '-') // This argument is an option
|
||||
{
|
||||
switch(argv[i][1]) // Set option
|
||||
{
|
||||
case '-': // Full option name
|
||||
{
|
||||
std::string op_str = argv[i];
|
||||
if (op_str == "--verbose") option = Option::Verbose;
|
||||
if (op_str == "--config") option = Option::Config;
|
||||
if (op_str == "--help") option = Option::Help;
|
||||
if (op_str == "--version") option = Option::Version;
|
||||
break;
|
||||
}
|
||||
case 'v': // Verbosity
|
||||
option = Option::Verbose;
|
||||
break;
|
||||
case 'V': //Version
|
||||
if(argv[i][0] == '-') {
|
||||
// This argument is an option
|
||||
switch(argv[i][1]) {
|
||||
case '-': {
|
||||
// Full option name
|
||||
std::string op_str = argv[i];
|
||||
if (op_str == "--verbose") option = Option::Verbose;
|
||||
if (op_str == "--config") option = Option::Config;
|
||||
if (op_str == "--help") option = Option::Help;
|
||||
if (op_str == "--version") option = Option::Version;
|
||||
break;
|
||||
}
|
||||
case 'v': // Verbosity
|
||||
option = Option::Verbose;
|
||||
break;
|
||||
case 'V': //Version
|
||||
option = Option::Version;
|
||||
break;
|
||||
case 'c': // Config file path
|
||||
option = Option::Config;
|
||||
break;
|
||||
case 'h': // Help
|
||||
option = Option::Help;
|
||||
break;
|
||||
default:
|
||||
log_printf(WARN, "%s is not a valid option, ignoring.", argv[1]);
|
||||
case 'c': // Config file path
|
||||
option = Option::Config;
|
||||
break;
|
||||
case 'h': // Help
|
||||
option = Option::Help;
|
||||
break;
|
||||
default:
|
||||
log_printf(WARN, "%s is not a valid option, ignoring.",
|
||||
argv[i]);
|
||||
}
|
||||
switch(option)
|
||||
{
|
||||
case Option::Verbose:
|
||||
{
|
||||
if (++i >= argc)
|
||||
{
|
||||
global_verbosity = DEBUG; // Assume debug verbosity
|
||||
break;
|
||||
}
|
||||
std::string loglevel = argv[i];
|
||||
try { global_verbosity = stringToLogLevel(argv[i]); }
|
||||
catch (std::invalid_argument &e)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
global_verbosity = DEBUG; // Assume debug verbosity
|
||||
i--; // Go back to last argument to continue loop.
|
||||
}
|
||||
else
|
||||
{
|
||||
log_printf(WARN, e.what());
|
||||
printf("Valid verbosity levels are: Debug, Info, Warn/Warning, or Error.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
switch(option) {
|
||||
case Option::Verbose: {
|
||||
if (++i >= argc) {
|
||||
global_verbosity = DEBUG; // Assume debug verbosity
|
||||
break;
|
||||
}
|
||||
case Option::Config:
|
||||
{
|
||||
if (++i >= argc)
|
||||
{
|
||||
log_printf(ERROR, "Config file is not specified.");
|
||||
std::string loglevel = argv[i];
|
||||
try {
|
||||
global_verbosity = stringToLogLevel(argv[i]);
|
||||
} catch (std::invalid_argument &e) {
|
||||
if (argv[i][0] == '-') {
|
||||
global_verbosity = DEBUG; // Assume debug verbosity
|
||||
i--; // Go back to last argument to continue loop.
|
||||
} else {
|
||||
log_printf(WARN, e.what());
|
||||
printf("Valid verbosity levels are: Debug, Info, "
|
||||
"Warn/Warning, or Error.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
config_file = argv[i];
|
||||
break;
|
||||
}
|
||||
case Option::Help:
|
||||
{
|
||||
printf(R"(logid version %s
|
||||
break;
|
||||
}
|
||||
case Option::Config: {
|
||||
if (++i >= argc) {
|
||||
log_printf(ERROR, "Config file is not specified.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
config_file = argv[i];
|
||||
break;
|
||||
}
|
||||
case Option::Help:
|
||||
printf(R"(logid version %s
|
||||
Usage: %s [options]
|
||||
Possible options are:
|
||||
-v,--verbose [level] Set log level to debug/info/warn/error (leave blank for debug)
|
||||
|
@ -130,16 +122,12 @@ Possible options are:
|
|||
-c,--config [file path] Change config file from default at %s
|
||||
-h,--help Print this message.
|
||||
)", LOGIOPS_VERSION, argv[0], DEFAULT_CONFIG_FILE);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
case Option::Version:
|
||||
{
|
||||
printf("%s\n", LOGIOPS_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
case Option::None:
|
||||
break;
|
||||
exit(EXIT_SUCCESS);
|
||||
case Option::Version:
|
||||
printf("%s\n", LOGIOPS_VERSION);
|
||||
exit(EXIT_SUCCESS);
|
||||
case Option::None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +135,7 @@ Possible options are:
|
|||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
read_cli_options(argc, argv);
|
||||
readCliOptions(argc, argv);
|
||||
|
||||
/*
|
||||
// Read config
|
||||
|
@ -168,8 +156,7 @@ int main(int argc, char** argv)
|
|||
// Scan devices, create listeners, handlers, etc.
|
||||
finder = new DeviceManager();
|
||||
|
||||
while(!kill_logid)
|
||||
{
|
||||
while(!kill_logid) {
|
||||
finder_reloading.lock();
|
||||
finder_reloading.unlock();
|
||||
finder->run();
|
||||
|
|
Loading…
Reference in New Issue
Block a user