Use consistent code style

Only files that are currently used in logid are changed.
This commit is contained in:
pixl 2020-06-23 22:35:37 -04:00
parent bd080e7ef6
commit dd75df8c18
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
34 changed files with 560 additions and 537 deletions

View File

@ -5,7 +5,7 @@ using namespace logid;
using namespace logid::backend; using namespace logid::backend;
Device::Device(std::string path, backend::hidpp::DeviceIndex index) : 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); log_printf(DEBUG, "logid::Device created on %s:%d", _path.c_str(), _index);
} }

View File

@ -44,14 +44,16 @@ void DeviceManager::addDevice(std::string path)
_devices.emplace(path, device); _devices.emplace(path, device);
} else { } else {
try { try {
auto device = std::make_shared<Device>(path, hidpp::CordedDevice); auto device = std::make_shared<Device>(path,
hidpp::CordedDevice);
_devices.emplace(path, device); _devices.emplace(path, device);
} catch(hidpp10::Error &e) { } catch(hidpp10::Error &e) {
if(e.code() != hidpp10::Error::UnknownDevice) if(e.code() != hidpp10::Error::UnknownDevice)
throw; throw;
else else
log_printf(WARN, "HID++ 1.0 error while trying to initialize" log_printf(WARN,
" %s: %s", path.c_str(), e.what()); "HID++ 1.0 error while trying to initialize %s:"
"%s", path.c_str(), e.what());
} catch(hidpp::Device::InvalidDevice &e) { // Ignore } catch(hidpp::Device::InvalidDevice &e) { // Ignore
} catch(std::system_error &e) { } catch(std::system_error &e) {
// This error should have been thrown previously // This error should have been thrown previously

View File

@ -1,5 +1,5 @@
#ifndef LOGID_DEVICEMONITOR_H #ifndef LOGID_DEVICEMANAGER_H
#define LOGID_DEVICEMONITOR_H #define LOGID_DEVICEMANAGER_H
#include <map> #include <map>
#include <thread> #include <thread>
@ -29,4 +29,4 @@ namespace logid
extern DeviceManager* finder; extern DeviceManager* finder;
} }
#endif //LOGID_DEVICEFINDER_H #endif //LOGID_DEVICEMANAGER_H

View File

@ -1,6 +1,6 @@
#include "Error.h" #include "Error.h"
const char *logid::backend::TimeoutError::what() noexcept const char *logid::backend::TimeoutError::what() const noexcept
{ {
return "Device timed out"; return "Device timed out";
} }

View File

@ -9,7 +9,7 @@ class TimeoutError: public std::exception
{ {
public: public:
TimeoutError() = default; TimeoutError() = default;
virtual const char* what() noexcept; const char* what() const noexcept override;
}; };
}} }}

View File

@ -8,14 +8,17 @@ Error::Error(uint8_t code) : _code (code)
const char* Error::what() const noexcept const char* Error::what() const noexcept
{ {
switch(_code) switch(_code) {
{
case Unknown: case Unknown:
return "Unknown"; return "Unknown";
case KeepAliveTimeout: case KeepAliveTimeout:
return "Keep-alive timeout"; return "Keep-alive timeout";
default: default:
return std::string("Reserved error code " + std::to_string(_code)) return "Reserved";
.c_str();
} }
} }
uint8_t Error::code() const noexcept
{
return _code;
}

View File

@ -1,5 +1,5 @@
#ifndef LOGID_HIDPP_BACKEND_DJ_ERROR_H #ifndef LOGID_BACKEND_DJ_ERROR_H
#define LOGID_HIDPP_BACKEND_DJ_ERROR_H #define LOGID_BACKEND_DJ_ERROR_H
#include <cstdint> #include <cstdint>
#include <stdexcept> #include <stdexcept>
@ -17,9 +17,9 @@ namespace dj
KeepAliveTimeout = 0x01 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; uint8_t code() const noexcept;
private: private:
@ -27,4 +27,4 @@ namespace dj
}; };
}}} }}}
#endif //LOGID_HIDPP_BACKEND_DJ_ERROR_H #endif //LOGID_BACKEND_DJ_ERROR_H

View File

@ -12,8 +12,7 @@ InvalidReceiver::InvalidReceiver(Reason reason) : _reason (reason)
const char* InvalidReceiver::what() const noexcept const char* InvalidReceiver::what() const noexcept
{ {
switch(_reason) switch(_reason) {
{
case NoDJReports: case NoDJReports:
return "No DJ reports"; return "No DJ reports";
default: default:
@ -27,10 +26,10 @@ InvalidReceiver::Reason InvalidReceiver::code() const noexcept
} }
Receiver::Receiver(std::string path) : Receiver::Receiver(std::string path) :
raw_device (std::make_shared<raw::RawDevice>(path)), _raw_device (std::make_shared<raw::RawDevice>(std::move(path))),
_hidpp10_device (raw_device, hidpp::DefaultDevice) _hidpp10_device (_raw_device, hidpp::DefaultDevice)
{ {
if(!supportsDjReports(raw_device->reportDescriptor())) if(!supportsDjReports(_raw_device->reportDescriptor()))
throw InvalidReceiver(InvalidReceiver::NoDJReports); throw InvalidReceiver(InvalidReceiver::NoDJReports);
} }
@ -39,28 +38,28 @@ void Receiver::enumerateDj()
sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{}); sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{});
} }
Receiver::notification_flags Receiver::getHidppNotifications() Receiver::NotificationFlags Receiver::getHidppNotifications()
{ {
auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {}, auto response = _hidpp10_device.getRegister(EnableHidppNotifications, {},
hidpp::ReportType::Short); hidpp::ReportType::Short);
notification_flags flags{}; NotificationFlags flags{};
flags.device_battery_status = response[0] & (1 << 4); flags.deviceBatteryStatus = response[0] & (1 << 4);
flags.receiver_wireless_notifications = response[1] & (1 << 0); flags.receiverWirelessNotifications = response[1] & (1 << 0);
flags.receiver_software_present = response[1] & (1 << 3); flags.receiverSoftwarePresent = response[1] & (1 << 3);
return flags; return flags;
} }
void Receiver::enableHidppNotifications(notification_flags flags) void Receiver::enableHidppNotifications(NotificationFlags flags)
{ {
std::vector<uint8_t> request(3); std::vector<uint8_t> request(3);
if(flags.device_battery_status) if(flags.deviceBatteryStatus)
request[0] |= (1 << 4); request[0] |= (1 << 4);
if(flags.receiver_wireless_notifications) if(flags.receiverWirelessNotifications)
request[1] |= 1; request[1] |= 1;
if(flags.receiver_software_present) if(flags.receiverSoftwarePresent)
request[1] |= (1 << 3); request[1] |= (1 << 3);
_hidpp10_device.setRegister(EnableHidppNotifications, request, _hidpp10_device.setRegister(EnableHidppNotifications, request,
@ -228,14 +227,14 @@ hidpp::DeviceConnectionEvent Receiver::deviceConnectionEvent(
void Receiver::handleDjEvent(Report& report) void Receiver::handleDjEvent(Report& report)
{ {
for(auto& handler : dj_event_handlers) for(auto& handler : _dj_event_handlers)
if(handler.second->condition(report)) if(handler.second->condition(report))
handler.second->callback(report); handler.second->callback(report);
} }
void Receiver::handleHidppEvent(hidpp::Report &report) void Receiver::handleHidppEvent(hidpp::Report &report)
{ {
for(auto& handler : hidpp_event_handlers) for(auto& handler : _hidpp_event_handlers)
if(handler.second->condition(report)) if(handler.second->condition(report))
handler.second->callback(report); handler.second->callback(report);
} }
@ -243,39 +242,39 @@ void Receiver::handleHidppEvent(hidpp::Report &report)
void Receiver::addDjEventHandler(const std::string& nickname, void Receiver::addDjEventHandler(const std::string& nickname,
const std::shared_ptr<EventHandler>& handler) const std::shared_ptr<EventHandler>& handler)
{ {
auto it = dj_event_handlers.find(nickname); auto it = _dj_event_handlers.find(nickname);
assert(it == dj_event_handlers.end()); assert(it == _dj_event_handlers.end());
dj_event_handlers.emplace(nickname, handler); _dj_event_handlers.emplace(nickname, handler);
} }
void Receiver::removeDjEventHandler(const std::string &nickname) 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>>& const std::map<std::string, std::shared_ptr<EventHandler>>&
Receiver::djEventHandlers() Receiver::djEventHandlers()
{ {
return dj_event_handlers; return _dj_event_handlers;
} }
void Receiver::addHidppEventHandler(const std::string& nickname, void Receiver::addHidppEventHandler(const std::string& nickname,
const std::shared_ptr<hidpp::EventHandler>& handler) const std::shared_ptr<hidpp::EventHandler>& handler)
{ {
auto it = hidpp_event_handlers.find(nickname); auto it = _hidpp_event_handlers.find(nickname);
assert(it == hidpp_event_handlers.end()); assert(it == _hidpp_event_handlers.end());
hidpp_event_handlers.emplace(nickname, handler); _hidpp_event_handlers.emplace(nickname, handler);
} }
void Receiver::removeHidppEventHandler(const std::string &nickname) 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>>& const std::map<std::string, std::shared_ptr<hidpp::EventHandler>>&
Receiver::hidppEventHandlers() Receiver::hidppEventHandlers()
{ {
return hidpp_event_handlers; return _hidpp_event_handlers;
} }
void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function, 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()); std::copy(params.begin(), params.end(), request.paramBegin());
raw_device->sendReportNoResponse(request.rawData()); _raw_device->sendReportNoResponse(request.rawData());
} }
void Receiver::listen() void Receiver::listen()
{ {
if(!raw_device->isListening()) if(!_raw_device->isListening())
std::thread{[=]() { raw_device->listen(); }}.detach(); std::thread{[=]() { _raw_device->listen(); }}.detach();
if(raw_device->eventHandlers().find("RECV_HIDPP") == if(_raw_device->eventHandlers().find("RECV_HIDPP") ==
raw_device->eventHandlers().end()) { _raw_device->eventHandlers().end()) {
// Pass all HID++ events on DefaultDevice to handleHidppEvent // Pass all HID++ events on DefaultDevice to handleHidppEvent
std::shared_ptr<RawEventHandler> hidppRawEventHandler = std::shared_ptr<raw::RawEventHandler> hidpp_handler =
std::make_shared<RawEventHandler>(); std::make_shared<raw::RawEventHandler>();
hidppRawEventHandler->condition = [](std::vector<uint8_t>& report)->bool hidpp_handler->condition = [](std::vector<uint8_t>& report)->bool
{ {
return (report[hidpp::Offset::Type] == hidpp::Report::Type::Short || return (report[hidpp::Offset::Type] == hidpp::Report::Type::Short ||
report[hidpp::Offset::Type] == hidpp::Report::Type::Long); 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); hidpp::Report _report(report);
this->handleHidppEvent(_report); this->handleHidppEvent(_report);
}; };
raw_device->addEventHandler("RECV_HIDPP", hidppRawEventHandler); _raw_device->addEventHandler("RECV_HIDPP", hidpp_handler);
} }
if(raw_device->eventHandlers().find("RECV_DJ") == if(_raw_device->eventHandlers().find("RECV_DJ") ==
raw_device->eventHandlers().end()) { _raw_device->eventHandlers().end()) {
// Pass all DJ events with device index to handleHidppEvent // Pass all DJ events with device index to handleDjEvent
std::shared_ptr<RawEventHandler> djRawEventHandler = std::shared_ptr<raw::RawEventHandler> dj_handler =
std::make_shared<RawEventHandler>(); std::make_shared<raw::RawEventHandler>();
djRawEventHandler->condition = [](std::vector<uint8_t>& report)->bool dj_handler->condition = [](std::vector<uint8_t>& report)->bool
{ {
return (report[Offset::Type] == Report::Type::Short || return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long); 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); Report _report(report);
this->handleDjEvent(_report); this->handleDjEvent(_report);
}; };
raw_device->addEventHandler("RECV_DJ", djRawEventHandler); _raw_device->addEventHandler("RECV_DJ", dj_handler);
} }
} }
void Receiver::stopListening() void Receiver::stopListening()
{ {
raw_device->removeEventHandler("RECV_HIDPP"); _raw_device->removeEventHandler("RECV_HIDPP");
raw_device->removeEventHandler("RECV_DJ"); _raw_device->removeEventHandler("RECV_DJ");
if(raw_device->eventHandlers().empty()) if(_raw_device->eventHandlers().empty())
raw_device->stopListener(); _raw_device->stopListener();
} }
std::shared_ptr<raw::RawDevice> Receiver::rawDevice() const std::shared_ptr<raw::RawDevice> Receiver::rawDevice() const
{ {
return raw_device; return _raw_device;
} }

View File

@ -25,7 +25,7 @@ namespace dj
NoDJReports NoDJReports
}; };
explicit InvalidReceiver(Reason reason); explicit InvalidReceiver(Reason reason);
virtual const char* what() const noexcept; const char* what() const noexcept override;
Reason code() const noexcept; Reason code() const noexcept;
private: private:
Reason _reason; Reason _reason;
@ -73,15 +73,15 @@ namespace dj
PairingInfo = 0xb5 PairingInfo = 0xb5
}; };
struct notification_flags struct NotificationFlags
{ {
bool device_battery_status; bool deviceBatteryStatus;
bool receiver_wireless_notifications; bool receiverWirelessNotifications;
bool receiver_software_present; bool receiverSoftwarePresent;
}; };
notification_flags getHidppNotifications(); NotificationFlags getHidppNotifications();
void enableHidppNotifications(notification_flags flags); void enableHidppNotifications(NotificationFlags flags);
void enumerateHidpp(); void enumerateHidpp();
uint8_t getConnectionState(hidpp::DeviceIndex index); uint8_t getConnectionState(hidpp::DeviceIndex index);
@ -142,11 +142,11 @@ namespace dj
void handleHidppEvent(hidpp::Report& report); void handleHidppEvent(hidpp::Report& report);
std::map<std::string, std::shared_ptr<EventHandler>> std::map<std::string, std::shared_ptr<EventHandler>>
dj_event_handlers; _dj_event_handlers;
std::map<std::string, std::shared_ptr<hidpp::EventHandler>> 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; hidpp10::Device _hidpp10_device;
}; };
} }

View File

@ -13,7 +13,7 @@ ReceiverMonitor::ReceiverMonitor(std::string path) : _receiver (
assert(_receiver->djEventHandlers().find("RECVMON") == assert(_receiver->djEventHandlers().find("RECVMON") ==
_receiver->djEventHandlers().end()); _receiver->djEventHandlers().end());
Receiver::notification_flags notification_flags{ Receiver::NotificationFlags notification_flags{
true, true,
true, true,
true}; true};
@ -25,16 +25,15 @@ void ReceiverMonitor::run()
_receiver->listen(); _receiver->listen();
if(_receiver->hidppEventHandlers().find("RECVMON") == if(_receiver->hidppEventHandlers().find("RECVMON") ==
_receiver->hidppEventHandlers().end()) _receiver->hidppEventHandlers().end()) {
{ std::shared_ptr<hidpp::EventHandler> event_handler =
std::shared_ptr<hidpp::EventHandler> eventHandler =
std::make_shared<hidpp::EventHandler>(); std::make_shared<hidpp::EventHandler>();
eventHandler->condition = [](hidpp::Report &report) -> bool { event_handler->condition = [](hidpp::Report &report) -> bool {
return (report.subId() == Receiver::DeviceConnection || return (report.subId() == Receiver::DeviceConnection ||
report.subId() == Receiver::DeviceDisconnection); 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 /* Running in a new thread prevents deadlocks since the
* receiver may be enumerating. * receiver may be enumerating.
*/ */
@ -48,7 +47,7 @@ void ReceiverMonitor::run()
}, report}.detach(); }, report}.detach();
}; };
_receiver->addHidppEventHandler("RECVMON", eventHandler); _receiver->addHidppEventHandler("RECVMON", event_handler);
} }
enumerate(); enumerate();

View File

@ -28,14 +28,14 @@ static const std::array<uint8_t, 34> DJReportDesc = {
bool dj::supportsDjReports(std::vector<uint8_t>&& rdesc) 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(); return it != rdesc.end();
} }
Report::Report(std::vector<uint8_t>& data) : _data (data) Report::Report(std::vector<uint8_t>& data) : _data (data)
{ {
switch(data[Offset::Type]) switch(data[Offset::Type]) {
{
case ReportType::Short: case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength); _data.resize(HeaderLength+ShortParamLength);
break; break;
@ -49,8 +49,7 @@ Report::Report(std::vector<uint8_t>& data) : _data (data)
Report::Report(Report::Type type, hidpp::DeviceIndex index, uint8_t feature) Report::Report(Report::Type type, hidpp::DeviceIndex index, uint8_t feature)
{ {
switch(type) switch(type) {
{
case ReportType::Short: case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength); _data.resize(HeaderLength+ShortParamLength);
break; break;

View File

@ -6,7 +6,9 @@
#include "defs.h" #include "defs.h"
#include "../hidpp/defs.h" #include "../hidpp/defs.h"
namespace logid::backend::dj namespace logid {
namespace backend {
namespace dj
{ {
namespace Offset namespace Offset
{ {
@ -33,6 +35,6 @@ namespace logid::backend::dj
private: private:
std::vector<uint8_t> _data; std::vector<uint8_t> _data;
}; };
} }}}
#endif //LOGID_BACKEND_DJ_REPORT_H #endif //LOGID_BACKEND_DJ_REPORT_H

View File

@ -13,8 +13,7 @@ using namespace logid::backend::hidpp;
const char* Device::InvalidDevice::what() const noexcept const char* Device::InvalidDevice::what() const noexcept
{ {
switch(_reason) switch(_reason) {
{
case NoHIDPPReport: case NoHIDPPReport:
return "Invalid HID++ device"; return "Invalid HID++ device";
case InvalidRawDevice: case InvalidRawDevice:
@ -58,10 +57,25 @@ Device::Device(std::shared_ptr<dj::Receiver> receiver,
_init(); _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() void Device::_init()
{ {
supported_reports = getSupportedReports(_raw_device->reportDescriptor()); _supported_reports = getSupportedReports(_raw_device->reportDescriptor());
if(!supported_reports) if(!_supported_reports)
throw InvalidDevice(InvalidDevice::NoHIDPPReport); throw InvalidDevice(InvalidDevice::NoHIDPPReport);
try { try {
@ -101,20 +115,20 @@ Device::~Device()
void Device::addEventHandler(const std::string& nickname, void Device::addEventHandler(const std::string& nickname,
const std::shared_ptr<EventHandler>& handler) const std::shared_ptr<EventHandler>& handler)
{ {
auto it = event_handlers.find(nickname); auto it = _event_handlers.find(nickname);
assert(it == event_handlers.end()); assert(it == _event_handlers.end());
event_handlers.emplace(nickname, handler); _event_handlers.emplace(nickname, handler);
} }
void Device::removeEventHandler(const std::string& nickname) void Device::removeEventHandler(const std::string& nickname)
{ {
event_handlers.erase(nickname); _event_handlers.erase(nickname);
} }
void Device::handleEvent(Report& report) void Device::handleEvent(Report& report)
{ {
for(auto& handler : event_handlers) for(auto& handler : _event_handlers)
if(handler.second->condition(report)) if(handler.second->condition(report))
handler.second->callback(report); handler.second->callback(report);
} }
@ -124,25 +138,25 @@ Report Device::sendReport(Report& report)
switch(report.type()) switch(report.type())
{ {
case Report::Type::Short: case Report::Type::Short:
if(!(supported_reports & HIDPP_REPORT_SHORT_SUPPORTED)) if(!(_supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
report.setType(Report::Type::Long); report.setType(Report::Type::Long);
break; break;
case Report::Type::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);
} }
auto raw_response = _raw_device->sendReport(report.rawReport()); auto raw_response = _raw_device->sendReport(report.rawReport());
Report response(raw_response); Report response(raw_response);
Report::hidpp10_error hidpp10Error{}; Report::Hidpp10Error hidpp10_error{};
if(response.isError10(&hidpp10Error)) if(response.isError10(&hidpp10_error))
throw hidpp10::Error(hidpp10Error.error_code); throw hidpp10::Error(hidpp10_error.error_code);
Report::hidpp20_error hidpp20Error{}; Report::Hidpp20Error hidpp20_error{};
if(response.isError20(&hidpp20Error)) if(response.isError20(&hidpp20_error))
throw hidpp10::Error(hidpp20Error.error_code); throw hidpp10::Error(hidpp20_error.error_code);
return response; return response;
} }
@ -153,20 +167,20 @@ void Device::listen()
std::thread{[=]() { _raw_device->listen(); }}.detach(); std::thread{[=]() { _raw_device->listen(); }}.detach();
// Pass all HID++ events with device index to this device. // Pass all HID++ events with device index to this device.
std::shared_ptr<RawEventHandler> rawEventHandler; std::shared_ptr<raw::RawEventHandler> handler;
rawEventHandler->condition = [this](std::vector<uint8_t>& report)->bool handler->condition = [this](std::vector<uint8_t>& report)->bool
{ {
return (report[Offset::Type] == Report::Type::Short || return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) && report[Offset::Type] == Report::Type::Long) &&
(report[Offset::DeviceIndex] == this->_index); (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); Report _report(report);
this->handleEvent(_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() void Device::stopListening()

View File

@ -1,5 +1,5 @@
#ifndef LOGID_HIDPP_DEVICE_H #ifndef LOGID_BACKEND_HIDPP_DEVICE_H
#define LOGID_HIDPP_DEVICE_H #define LOGID_BACKEND_HIDPP_DEVICE_H
#include <string> #include <string>
#include <memory> #include <memory>
@ -44,14 +44,15 @@ namespace hidpp
}; };
explicit Device(const std::string& path, DeviceIndex index); 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, explicit Device(std::shared_ptr<dj::Receiver> receiver,
hidpp::DeviceConnectionEvent event); hidpp::DeviceConnectionEvent event);
~Device(); ~Device();
std::string devicePath() const { return _path; } std::string devicePath() const;
DeviceIndex deviceIndex() const { return _index; } DeviceIndex deviceIndex() const;
std::tuple<uint8_t, uint8_t> version() const { return _version; } std::tuple<uint8_t, uint8_t> version() const;
void listen(); // Runs asynchronously void listen(); // Runs asynchronously
void stopListening(); void stopListening();
@ -70,14 +71,14 @@ namespace hidpp
std::shared_ptr<dj::Receiver> _receiver; std::shared_ptr<dj::Receiver> _receiver;
std::string _path; std::string _path;
DeviceIndex _index; DeviceIndex _index;
uint8_t supported_reports; uint8_t _supported_reports;
std::tuple<uint8_t, uint8_t> _version; std::tuple<uint8_t, uint8_t> _version;
uint16_t _pid; uint16_t _pid;
std::string _name; 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

View File

@ -70,15 +70,19 @@ uint8_t hidpp::getSupportedReports(std::vector<uint8_t>&& rdesc)
{ {
uint8_t ret = 0; 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()) 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()) if(it != rdesc.end())
ret |= HIDPP_REPORT_SHORT_SUPPORTED; 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()) 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()) if(it != rdesc.end())
ret |= HIDPP_REPORT_LONG_SUPPORTED; ret |= HIDPP_REPORT_LONG_SUPPORTED;
@ -98,8 +102,7 @@ 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 sub_id, uint8_t address) uint8_t sub_id, uint8_t address)
{ {
switch(type) switch(type) {
{
case Type::Short: case Type::Short:
_data.resize(HeaderLength + ShortParamLength); _data.resize(HeaderLength + ShortParamLength);
break; break;
@ -119,11 +122,10 @@ Report::Report(Report::Type type, DeviceIndex device_index,
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 <= 0x0f);
assert(sw_id <= swIdMask); assert(sw_id <= 0x0f);
switch(type) switch(type) {
{
case Type::Short: case Type::Short:
_data.resize(HeaderLength + ShortParamLength); _data.resize(HeaderLength + ShortParamLength);
break; break;
@ -137,7 +139,8 @@ Report::Report(Report::Type type, DeviceIndex device_index,
_data[Offset::Type] = type; _data[Offset::Type] = type;
_data[Offset::DeviceIndex] = device_index; _data[Offset::DeviceIndex] = device_index;
_data[Offset::Feature] = feature_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) Report::Report(const std::vector<uint8_t>& data)
@ -145,8 +148,7 @@ Report::Report(const std::vector<uint8_t>& data)
_data = data; _data = data;
// Truncating data is entirely valid here. // Truncating data is entirely valid here.
switch(_data[Offset::Type]) switch(_data[Offset::Type]) {
{
case Type::Short: case Type::Short:
_data.resize(HeaderLength + ShortParamLength); _data.resize(HeaderLength + ShortParamLength);
break; break;
@ -165,8 +167,7 @@ Report::Type Report::type() const
void Report::setType(Report::Type type) void Report::setType(Report::Type type)
{ {
switch(type) switch(type) {
{
case Type::Short: case Type::Short:
_data.resize(HeaderLength + ShortParamLength); _data.resize(HeaderLength + ShortParamLength);
break; break;
@ -218,7 +219,7 @@ uint8_t Report::function() const
void Report::setFunction(uint8_t function) void Report::setFunction(uint8_t function)
{ {
_data[Offset::Function] &= 0x0f; _data[Offset::Function] &= 0x0f;
_data[Offset::Function] |= (function << 4) & 0x0f; _data[Offset::Function] |= (function & 0x0f) << 4;
} }
uint8_t Report::swId() const uint8_t Report::swId() const
@ -250,7 +251,7 @@ void Report::setParams(const std::vector<uint8_t>& _params)
_data[Offset::Parameters + i] = _params[i]; _data[Offset::Parameters + i] = _params[i];
} }
bool Report::isError10(Report::hidpp10_error *error) bool Report::isError10(Report::Hidpp10Error *error)
{ {
assert(error != nullptr); assert(error != nullptr);
@ -265,8 +266,10 @@ bool Report::isError10(Report::hidpp10_error *error)
return true; return true;
} }
bool Report::isError20(Report::hidpp20_error* error) bool Report::isError20(Report::Hidpp20Error* error)
{ {
assert(error != nullptr);
if(_data[Offset::Type] != Type::Long || if(_data[Offset::Type] != Type::Long ||
_data[Offset::Feature] != hidpp20::ErrorID) _data[Offset::Feature] != hidpp20::ErrorID)
return false; return false;

View File

@ -10,7 +10,9 @@
#define HIDPP_REPORT_LONG_SUPPORTED 1U<<1U #define HIDPP_REPORT_LONG_SUPPORTED 1U<<1U
/* Very long reports exist, however they have not been encountered so far */ /* 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); uint8_t getSupportedReports(std::vector<uint8_t>&& rdesc);
@ -34,19 +36,17 @@ namespace logid::backend::hidpp
{ {
public: public:
InvalidReportID() = default; InvalidReportID() = default;
virtual const char* what() const noexcept; const char* what() const noexcept override;
}; };
class InvalidReportLength: public std::exception class InvalidReportLength: public std::exception
{ {
public: public:
InvalidReportLength() = default;; InvalidReportLength() = default;;
virtual const char* what() const noexcept; const char* what() const noexcept override;
}; };
static constexpr std::size_t MaxDataLength = 20; 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, Report(Report::Type type, DeviceIndex device_index,
uint8_t sub_id, uint8_t sub_id,
@ -85,19 +85,17 @@ namespace logid::backend::hidpp
std::vector<uint8_t>::iterator paramEnd() { 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 hidpp10_error struct Hidpp10Error
{ {
uint8_t sub_id, address, error_code; uint8_t sub_id, address, error_code;
}; };
bool isError10(Hidpp10Error* error);
bool isError10(hidpp10_error* error); struct Hidpp20Error
struct hidpp20_error
{ {
uint8_t feature_index, function, software_id, error_code; uint8_t feature_index, function, software_id, error_code;
}; };
bool isError20(Hidpp20Error* error);
bool isError20(hidpp20_error* error);
std::vector<uint8_t> rawReport () const { return _data; } std::vector<uint8_t> rawReport () const { return _data; }
@ -105,6 +103,6 @@ namespace logid::backend::hidpp
private: private:
std::vector<uint8_t> _data; std::vector<uint8_t> _data;
}; };
} }}}
#endif //LOGID_BACKEND_HIDPP_REPORT_H #endif //LOGID_BACKEND_HIDPP_REPORT_H

View File

@ -3,7 +3,9 @@
#define LOGID_HIDPP_SOFTWARE_ID 0 #define LOGID_HIDPP_SOFTWARE_ID 0
namespace logid::backend::hidpp namespace logid {
namespace backend {
namespace hidpp
{ {
namespace ReportType namespace ReportType
{ {
@ -28,6 +30,6 @@ namespace logid::backend::hidpp
static constexpr std::size_t ShortParamLength = 3; static constexpr std::size_t ShortParamLength = 3;
static constexpr std::size_t LongParamLength = 16; static constexpr std::size_t LongParamLength = 16;
} } } }
#endif //LOGID_HIDPP_DEFS_H #endif //LOGID_HIDPP_DEFS_H

View File

@ -41,7 +41,8 @@ std::vector<uint8_t> Device::setRegister(uint8_t address,
return accessRegister(sub_id, address, params); return accessRegister(sub_id, address, params);
} }
std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address, const std::vector<uint8_t> &params) std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address,
const std::vector<uint8_t> &params)
{ {
hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ? hidpp::Report::Type type = params.size() <= hidpp::ShortParamLength ?
hidpp::Report::Type::Short : hidpp::Report::Type::Long; hidpp::Report::Type::Short : hidpp::Report::Type::Long;

View File

@ -11,8 +11,7 @@ Error::Error(uint8_t code): _code(code)
const char* Error::what() const noexcept const char* Error::what() const noexcept
{ {
switch(_code) switch(_code) {
{
case Success: case Success:
return "Success"; return "Success";
case InvalidSubID: case InvalidSubID:
@ -40,7 +39,7 @@ const char* Error::what() const noexcept
case WrongPINCode: case WrongPINCode:
return "Wrong PIN code"; return "Wrong PIN code";
default: default:
return std::string("Unknown error code " + std::to_string(_code)).c_str(); return "Unknown error code";
} }
} }

View File

@ -28,9 +28,9 @@ namespace hidpp10 {
WrongPINCode = 0x0C 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; uint8_t code() const noexcept;
private: private:

View File

@ -11,8 +11,7 @@ Error::Error(uint8_t code) : _code (code)
const char* Error::what() const noexcept const char* Error::what() const noexcept
{ {
switch(_code) switch(_code) {
{
case NoError: case NoError:
return "No error"; return "No error";
case Unknown: case Unknown:
@ -36,7 +35,7 @@ const char* Error::what() const noexcept
case UnknownDevice: case UnknownDevice:
return "Unknown device"; return "Unknown device";
default: default:
return std::string("Unknown error code " + std::to_string(_code)).c_str(); return "Unknown error code";
} }
} }

View File

@ -26,9 +26,9 @@ namespace hidpp20 {
UnknownDevice = 10 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; uint8_t code() const noexcept;
private: private:

View File

@ -11,7 +11,7 @@ namespace hidpp20 {
{ {
public: public:
explicit UnsupportedFeature(uint16_t ID) : _f_id (ID) {} 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; uint16_t code() const noexcept;
private: private:
uint16_t _f_id; uint16_t _f_id;

View File

@ -21,7 +21,7 @@ namespace hidpp20
GetDeviceName = 1 GetDeviceName = 1
}; };
DeviceName(Device* device); explicit DeviceName(Device* device);
uint8_t getNameLength(); uint8_t getNameLength();
std::string getName(); std::string getName();
@ -33,7 +33,7 @@ namespace hidpp20
static const uint16_t ID = FeatureID::DEVICE_NAME; static const uint16_t ID = FeatureID::DEVICE_NAME;
virtual uint16_t getID() { return ID; } virtual uint16_t getID() { return ID; }
EssentialDeviceName(hidpp::Device* device); explicit EssentialDeviceName(hidpp::Device* device);
uint8_t getNameLength(); uint8_t getNameLength();
std::string getName(); std::string getName();

View File

@ -14,7 +14,8 @@ std::vector<uint8_t> _genGetFeatureParams(uint16_t feature_id)
return params; 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{}; feature_info info{};
info.feature_id = response[0]; info.feature_id = response[0];

View File

@ -21,7 +21,7 @@ namespace hidpp20
Ping = 1 Ping = 1
}; };
Root(Device* device); explicit Root(Device* device);
feature_info getFeature (uint16_t feature_id); feature_info getFeature (uint16_t feature_id);
std::tuple<uint8_t, uint8_t> getVersion(); std::tuple<uint8_t, uint8_t> getVersion();
@ -40,7 +40,7 @@ namespace hidpp20
static const uint16_t ID = FeatureID::ROOT; static const uint16_t ID = FeatureID::ROOT;
virtual uint16_t getID() { return ID; } 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(); std::tuple<uint8_t, uint8_t> getVersion();

View File

@ -13,38 +13,37 @@ using namespace logid::backend::raw;
DeviceMonitor::DeviceMonitor() DeviceMonitor::DeviceMonitor()
{ {
if(-1 == pipe(monitor_pipe)) if(-1 == pipe(_pipe))
throw std::system_error(errno, std::system_category(), "pipe creation failed"); throw std::system_error(errno, std::system_category(),
"pipe creation failed");
udev_context = udev_new(); _udev_context = udev_new();
if(!udev_context) if(!_udev_context)
throw std::runtime_error("udev_new failed"); throw std::runtime_error("udev_new failed");
} }
DeviceMonitor::~DeviceMonitor() 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); close(i);
} }
void DeviceMonitor::run() void DeviceMonitor::run()
{ {
int ret; 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) if(!monitor)
throw std::runtime_error("udev_monitor_new_from_netlink failed"); 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) 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"); "udev_monitor_filter_add_match_subsystem_devtype");
@ -57,20 +56,27 @@ void DeviceMonitor::run()
this->enumerate(); this->enumerate();
int fd = udev_monitor_get_fd(monitor); int fd = udev_monitor_get_fd(monitor);
while (true) {
_run_monitor = true;
while (_run_monitor) {
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(monitor_pipe[0], &fds); FD_SET(_pipe[0], &fds);
FD_SET(fd, &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) if (errno == EINTR)
continue; 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)) { if (FD_ISSET(fd, &fds)) {
struct udev_device *device = udev_monitor_receive_device(monitor); struct udev_device *device = udev_monitor_receive_device(monitor);
std::string action = udev_device_get_action(device); std::string action = udev_device_get_action(device);
std::string devnode = udev_device_get_devnode(device); std::string devnode = udev_device_get_devnode(device);
if (action == "add") if (action == "add")
std::thread([this](const std::string name) { std::thread([this](const std::string name) {
this->addDevice(name); this->addDevice(name);
@ -79,11 +85,12 @@ void DeviceMonitor::run()
std::thread([this](const std::string name) { std::thread([this](const std::string name) {
this->removeDevice(name); this->removeDevice(name);
}, devnode).detach(); }, devnode).detach();
udev_device_unref (device); udev_device_unref (device);
} }
if (FD_ISSET(monitor_pipe[0], &fds)) { if (FD_ISSET(_pipe[0], &fds)) {
char c; char c;
if (-1 == read(monitor_pipe[0], &c, sizeof (char))) if (-1 == read(_pipe[0], &c, sizeof (char)))
throw std::system_error (errno, std::system_category(), throw std::system_error (errno, std::system_category(),
"read pipe"); "read pipe");
break; break;
@ -93,13 +100,14 @@ void DeviceMonitor::run()
void DeviceMonitor::stop() void DeviceMonitor::stop()
{ {
_run_monitor = false;
std::lock_guard<std::mutex> lock(_running);
} }
void DeviceMonitor::enumerate() void DeviceMonitor::enumerate()
{ {
int ret; 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"); ret = udev_enumerate_add_match_subsystem(udev_enum, "hidraw");
if(0 != ret) if(0 != ret)
throw std::system_error(-ret, std::system_category(), throw std::system_error(-ret, std::system_category(),
@ -112,11 +120,10 @@ void DeviceMonitor::enumerate()
struct udev_list_entry* udev_enum_entry; struct udev_list_entry* udev_enum_entry;
udev_list_entry_foreach(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); 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); name);
if(!device) if(!device)
throw std::runtime_error("udev_device_new_from_syspath failed"); throw std::runtime_error("udev_device_new_from_syspath failed");

View File

@ -3,13 +3,16 @@
#include <string> #include <string>
#include <mutex> #include <mutex>
#include <atomic>
extern "C" extern "C"
{ {
#include <libudev.h> #include <libudev.h>
} }
namespace logid::backend::raw namespace logid {
namespace backend {
namespace raw
{ {
class DeviceMonitor class DeviceMonitor
{ {
@ -23,10 +26,11 @@ namespace logid::backend::raw
virtual void addDevice(std::string device) = 0; virtual void addDevice(std::string device) = 0;
virtual void removeDevice(std::string device) = 0; virtual void removeDevice(std::string device) = 0;
private: private:
struct udev* udev_context; struct udev* _udev_context;
int monitor_pipe[2]; int _pipe[2];
std::mutex running; std::atomic<bool> _run_monitor;
std::mutex _running;
}; };
} }}}
#endif //LOGID_BACKEND_RAW_DEVICEMONITOR_H #endif //LOGID_BACKEND_RAW_DEVICEMONITOR_H

View File

@ -7,12 +7,13 @@
#include <string> #include <string>
#include <system_error> #include <system_error>
#include <cassert> #include <utility>
#define MAX_DATA_LENGTH 32 #define MAX_DATA_LENGTH 32
extern "C" extern "C"
{ {
#include <cassert>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@ -25,8 +26,7 @@ using namespace std::chrono;
bool RawDevice::supportedReport(uint8_t id, uint8_t length) bool RawDevice::supportedReport(uint8_t id, uint8_t length)
{ {
switch(id) switch(id) {
{
case hidpp::ReportType::Short: case hidpp::ReportType::Short:
return length == (hidpp::ShortParamLength + return length == (hidpp::ShortParamLength +
hidpp::Report::HeaderLength); hidpp::Report::HeaderLength);
@ -40,90 +40,102 @@ bool RawDevice::supportedReport(uint8_t id, uint8_t length)
default: default:
return false; 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; int ret;
fd = ::open(path.c_str(), O_RDWR); _fd = ::open(_path.c_str(), O_RDWR);
if (fd == -1) if (_fd == -1)
throw std::system_error(errno, std::system_category(), throw std::system_error(errno, std::system_category(),
"RawDevice open failed"); "RawDevice open failed");
hidraw_devinfo devinfo{}; hidraw_devinfo devinfo{};
if (-1 == ::ioctl(fd, HIDIOCGRAWINFO, &devinfo)) if (-1 == ::ioctl(_fd, HIDIOCGRAWINFO, &devinfo)) {
{
int err = errno; int err = errno;
::close(fd); ::close(_fd);
throw std::system_error(err, std::system_category(), throw std::system_error(err, std::system_category(),
"RawDevice HIDIOCGRAWINFO failed"); "RawDevice HIDIOCGRAWINFO failed");
} }
vid = devinfo.vendor; _vid = devinfo.vendor;
pid = devinfo.product; _pid = devinfo.product;
char name_buf[256]; 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; int err = errno;
::close(fd); ::close(_fd);
throw std::system_error(err, std::system_category(), throw std::system_error(err, std::system_category(),
"RawDevice HIDIOCGRAWNAME failed"); "RawDevice HIDIOCGRAWNAME failed");
} }
_name.assign(name_buf, ret - 1); _name.assign(name_buf, ret - 1);
hidraw_report_descriptor _rdesc{}; hidraw_report_descriptor _rdesc{};
if (-1 == ::ioctl(fd, HIDIOCGRDESCSIZE, &_rdesc.size)) if (-1 == ::ioctl(_fd, HIDIOCGRDESCSIZE, &_rdesc.size)) {
{
int err = errno; int err = errno;
::close(fd); ::close(_fd);
throw std::system_error(err, std::system_category(), throw std::system_error(err, std::system_category(),
"RawDevice HIDIOCGRDESCSIZE failed"); "RawDevice HIDIOCGRDESCSIZE failed");
} }
if (-1 == ::ioctl(fd, HIDIOCGRDESC, &_rdesc)) if (-1 == ::ioctl(_fd, HIDIOCGRDESC, &_rdesc)) {
{
int err = errno; int err = errno;
::close(fd); ::close(_fd);
throw std::system_error(err, std::system_category(), throw std::system_error(err, std::system_category(),
"RawDevice HIDIOCGRDESC failed"); "RawDevice HIDIOCGRDESC failed");
} }
rdesc = std::vector<uint8_t>(_rdesc.value, _rdesc.value + _rdesc.size); rdesc = std::vector<uint8_t>(_rdesc.value, _rdesc.value + _rdesc.size);
if (-1 == ::pipe(dev_pipe)) if (-1 == ::pipe(_pipe)) {
{
int err = errno; int err = errno;
close(fd); close(_fd);
throw std::system_error(err, std::system_category(), throw std::system_error(err, std::system_category(),
"RawDevice pipe open failed"); "RawDevice pipe open failed");
} }
continue_listen = false; _continue_listen = false;
} }
RawDevice::~RawDevice() RawDevice::~RawDevice()
{ {
if(fd != -1) if(_fd != -1)
{ {
::close(fd); ::close(_fd);
::close(dev_pipe[0]); ::close(_pipe[0]);
::close(dev_pipe[1]); ::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) std::vector<uint8_t> RawDevice::sendReport(const std::vector<uint8_t>& report)
{ {
/* 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]() { std::packaged_task<std::vector<uint8_t>()> task( [this, report]() {
return this->_respondToReport(report); return this->_respondToReport(report);
}); });
auto f = task.get_future(); auto f = task.get_future();
write_queue.push(&task); _io_queue.push(&task);
return f.get(); return f.get();
} }
else else
@ -135,14 +147,13 @@ void RawDevice::sendReportNoResponse(const std::vector<uint8_t>& report)
{ {
/* 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]() { std::packaged_task<std::vector<uint8_t>()> task([this, report]() {
this->_sendReport(report); this->_sendReport(report);
return std::vector<uint8_t>(); return std::vector<uint8_t>();
}); });
auto f = task.get_future(); auto f = task.get_future();
write_queue.push(&task); _io_queue.push(&task);
f.get(); f.get();
} }
else else
@ -153,27 +164,23 @@ std::vector<uint8_t> RawDevice::_respondToReport
(const std::vector<uint8_t>& request) (const std::vector<uint8_t>& request)
{ {
_sendReport(request); _sendReport(request);
while(true) while(true) {
{
std::vector<uint8_t> response; std::vector<uint8_t> response;
_readReport(response, MAX_DATA_LENGTH); _readReport(response, MAX_DATA_LENGTH);
// All reports have the device index at byte 2 // All reports have the device index at byte 2
if(response[1] != request[1]) if(response[1] != request[1]) {
{ if(_continue_listen)
if(continue_listen) this->_handleEvent(response);
this->handleEvent(response);
continue; continue;
} }
if(hidpp::ReportType::Short == request[0] || if(hidpp::ReportType::Short == request[0] ||
hidpp::ReportType::Long == request[0]) hidpp::ReportType::Long == request[0]) {
{
if(hidpp::ReportType::Short != response[0] && if(hidpp::ReportType::Short != response[0] &&
hidpp::ReportType::Long != response[0]) hidpp::ReportType::Long != response[0]) {
{ if(_continue_listen)
if(continue_listen) this->_handleEvent(response);
this->handleEvent(response);
continue; continue;
} }
@ -183,17 +190,13 @@ std::vector<uint8_t> RawDevice::_respondToReport
bool others_match = true; bool others_match = true;
for(int i = 2; i < 4; i++) for(int i = 2; i < 4; i++)
{
if(response[i] != request[i]) if(response[i] != request[i])
others_match = false; others_match = false;
}
if(others_match) if(others_match)
return response; return response;
} } else if(dj::ReportType::Short == request[0] ||
else if(dj::ReportType::Short == request[0] || dj::ReportType::Long == request[0]) {
dj::ReportType::Long == request[0])
{
//Error; leave to device ot handle //Error; leave to device ot handle
if(0x7f == response[2]) if(0x7f == response[2])
return response; return response;
@ -201,16 +204,16 @@ std::vector<uint8_t> RawDevice::_respondToReport
return response; return response;
} }
if(continue_listen) if(_continue_listen)
this->handleEvent(response); this->_handleEvent(response);
} }
} }
int RawDevice::_sendReport(const std::vector<uint8_t>& report) 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) { if(logid::global_verbosity == LogLevel::RAWREPORT) {
printf("[RAWREPORT] %s OUT: ", path.c_str()); printf("[RAWREPORT] %s OUT: ", _path.c_str());
for(auto &i : report) for(auto &i : report)
printf("%02x ", i); printf("%02x ", i);
printf("\n"); printf("\n");
@ -218,11 +221,11 @@ int RawDevice::_sendReport(const std::vector<uint8_t>& report)
assert(supportedReport(report[0], report.size())); 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) { if(ret == -1) {
///TODO: This seems like a hacky solution ///TODO: This seems like a hacky solution
// Try again before failing // Try again before failing
ret = ::write(fd, report.data(), report.size()); ret = ::write(_fd, report.data(), report.size());
if(ret == -1) if(ret == -1)
throw std::system_error(errno, std::system_category(), throw std::system_error(errno, std::system_category(),
"_sendReport write failed"); "_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) 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; int ret;
report.resize(maxDataLength); report.resize(maxDataLength);
@ -243,10 +246,10 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
fd_set fds; fd_set fds;
do { do {
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(fd, &fds); FD_SET(_fd, &fds);
FD_SET(dev_pipe[0], &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, &fds, nullptr, nullptr,
(HIDPP_IO_TIMEOUT.count() > 0 ? nullptr : &timeout)); (HIDPP_IO_TIMEOUT.count() > 0 ? nullptr : &timeout));
} while(ret == -1 && errno == EINTR); } 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(), throw std::system_error(errno, std::system_category(),
"_readReport select failed"); "_readReport select failed");
if(FD_ISSET(fd, &fds)) if(FD_ISSET(_fd, &fds)) {
{ ret = read(_fd, report.data(), report.size());
ret = read(fd, report.data(), report.size());
if(ret == -1) if(ret == -1)
throw std::system_error(errno, std::system_category(), throw std::system_error(errno, std::system_category(),
"_readReport read failed"); "_readReport read failed");
report.resize(ret); report.resize(ret);
} }
if(FD_ISSET(dev_pipe[0], &fds)) if(FD_ISSET(_pipe[0], &fds)) {
{
char c; char c;
ret = read(dev_pipe[0], &c, sizeof(char)); ret = read(_pipe[0], &c, sizeof(char));
if(ret == -1) if(ret == -1)
throw std::system_error(errno, std::system_category(), throw std::system_error(errno, std::system_category(),
"_readReport read pipe failed"); "_readReport read pipe failed");
@ -277,7 +278,7 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
throw backend::TimeoutError(); throw backend::TimeoutError();
if(logid::global_verbosity == LogLevel::RAWREPORT) { if(logid::global_verbosity == LogLevel::RAWREPORT) {
printf("[RAWREPORT] %s IN: ", path.c_str()); printf("[RAWREPORT] %s IN: ", _path.c_str());
for(auto &i : report) for(auto &i : report)
printf("%02x ", i); printf("%02x ", i);
printf("\n"); printf("\n");
@ -289,82 +290,79 @@ int RawDevice::_readReport(std::vector<uint8_t>& report, std::size_t maxDataLeng
void RawDevice::interruptRead() void RawDevice::interruptRead()
{ {
char c = 0; 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(), throw std::system_error(errno, std::system_category(),
"interruptRead write pipe failed"); "interruptRead write pipe failed");
// Ensure I/O has halted // Ensure I/O has halted
std::lock_guard<std::mutex> lock(dev_io); std::lock_guard<std::mutex> lock(_dev_io);
} }
void RawDevice::listen() void RawDevice::listen()
{ {
std::lock_guard<std::mutex> lock(listening); std::lock_guard<std::mutex> lock(_listening);
continue_listen = true; _continue_listen = true;
while(continue_listen) while(_continue_listen) {
{ while(!_io_queue.empty()) {
while(!write_queue.empty()) auto task = _io_queue.front();
{
auto task = write_queue.front();
(*task)(); (*task)();
write_queue.pop(); _io_queue.pop();
} }
std::vector<uint8_t> report; std::vector<uint8_t> report;
_readReport(report, MAX_DATA_LENGTH); _readReport(report, MAX_DATA_LENGTH);
this->handleEvent(report); this->_handleEvent(report);
} }
// Listener is stopped, handle I/O queue // Listener is stopped, handle I/O queue
while(!write_queue.empty()) while(!_io_queue.empty()) {
{ auto task = _io_queue.front();
auto task = write_queue.front();
(*task)(); (*task)();
write_queue.pop(); _io_queue.pop();
} }
continue_listen = false; _continue_listen = false;
} }
void RawDevice::stopListener() void RawDevice::stopListener()
{ {
continue_listen = false; _continue_listen = false;
interruptRead(); interruptRead();
} }
void RawDevice::addEventHandler(const std::string& nickname, 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); auto it = _event_handlers.find(nickname);
assert(it == event_handlers.end()); assert(it == _event_handlers.end());
event_handlers.emplace(nickname, handler); _event_handlers.emplace(nickname, handler);
} }
void RawDevice::removeEventHandler(const std::string &nickname) 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() 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)) if(handler.second->condition(report))
handler.second->callback(report); handler.second->callback(report);
} }
bool RawDevice::isListening() bool RawDevice::isListening()
{ {
bool ret = listening.try_lock(); bool ret = _listening.try_lock();
if(ret) if(ret)
listening.unlock(); _listening.unlock();
return !ret; return !ret;
} }

View File

@ -9,7 +9,7 @@
#include <future> #include <future>
#include <set> #include <set>
#include "../defs.h" #include "defs.h"
#include "../../util/mutex_queue.h" #include "../../util/mutex_queue.h"
#define HIDPP_IO_TIMEOUT std::chrono::seconds(2) #define HIDPP_IO_TIMEOUT std::chrono::seconds(2)
@ -25,11 +25,11 @@ namespace raw
explicit RawDevice(std::string path); explicit RawDevice(std::string path);
~RawDevice(); ~RawDevice();
std::string hidrawPath() const { return path; } std::string hidrawPath() const;
std::string name() const { return _name; } std::string name() const;
uint16_t vendorId() const { return vid; } uint16_t vendorId() const;
uint16_t productId() const { return pid; } uint16_t productId() const;
std::vector<uint8_t> reportDescriptor() const { return rdesc; } std::vector<uint8_t> reportDescriptor() const { return rdesc; }
@ -42,34 +42,35 @@ namespace raw
bool isListening(); bool isListening();
void addEventHandler(const std::string& nickname, 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); 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(); eventHandlers();
private: private:
std::mutex dev_io, listening; std::mutex _dev_io, _listening;
std::string path; std::string _path;
int fd; int _fd;
int dev_pipe[2]; int _pipe[2];
uint16_t vid; uint16_t _vid;
uint16_t pid; uint16_t _pid;
std::string _name; std::string _name;
std::vector<uint8_t> rdesc; std::vector<uint8_t> rdesc;
std::atomic<bool> continue_listen; std::atomic<bool> _continue_listen;
std::map<std::string, std::shared_ptr<backend::RawEventHandler>> std::map<std::string, std::shared_ptr<RawEventHandler>>
event_handlers; _event_handlers;
void handleEvent(std::vector<uint8_t>& report); void _handleEvent(std::vector<uint8_t>& report);
/* These will only be used internally and processed with a queue */ /* These will only be used internally and processed with a queue */
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); 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;
}; };
}}} }}}

View File

@ -1,15 +1,19 @@
#ifndef LOGID_BACKEND_DEFS_H #ifndef LOGID_BACKEND_RAW_DEFS_H
#define LOGID_BACKEND_DEFS_H #define LOGID_BACKEND_RAW_DEFS_H
#include <functional> #include <functional>
#include <cstdint>
#include <vector>
namespace logid::backend namespace logid {
namespace backend {
namespace raw
{ {
struct RawEventHandler struct RawEventHandler
{ {
std::function<bool(std::vector<uint8_t>& )> condition; std::function<bool(std::vector<uint8_t>& )> condition;
std::function<void(std::vector<uint8_t>& )> callback; std::function<void(std::vector<uint8_t>& )> callback;
}; };
} }}}
#endif //LOGID_BACKEND_DEFS_H #endif //LOGID_BACKEND_RAW_DEFS_H

View File

@ -50,17 +50,15 @@ 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; Option option = Option::None;
if(argv[i][0] == '-') // This argument is an option if(argv[i][0] == '-') {
{ // This argument is an option
switch(argv[i][1]) // Set option switch(argv[i][1]) {
{ case '-': {
case '-': // Full option name // Full option name
{
std::string op_str = argv[i]; std::string op_str = argv[i];
if (op_str == "--verbose") option = Option::Verbose; if (op_str == "--verbose") option = Option::Verbose;
if (op_str == "--config") option = Option::Config; if (op_str == "--config") option = Option::Config;
@ -81,39 +79,34 @@ void read_cli_options(int argc, char** argv)
option = Option::Help; option = Option::Help;
break; break;
default: default:
log_printf(WARN, "%s is not a valid option, ignoring.", argv[1]); log_printf(WARN, "%s is not a valid option, ignoring.",
argv[i]);
} }
switch(option)
{ switch(option) {
case Option::Verbose: case Option::Verbose: {
{ if (++i >= argc) {
if (++i >= argc)
{
global_verbosity = DEBUG; // Assume debug verbosity global_verbosity = DEBUG; // Assume debug verbosity
break; break;
} }
std::string loglevel = argv[i]; std::string loglevel = argv[i];
try { global_verbosity = stringToLogLevel(argv[i]); } try {
catch (std::invalid_argument &e) global_verbosity = stringToLogLevel(argv[i]);
{ } catch (std::invalid_argument &e) {
if (argv[i][0] == '-') if (argv[i][0] == '-') {
{
global_verbosity = DEBUG; // Assume debug verbosity global_verbosity = DEBUG; // Assume debug verbosity
i--; // Go back to last argument to continue loop. i--; // Go back to last argument to continue loop.
} } else {
else
{
log_printf(WARN, e.what()); log_printf(WARN, e.what());
printf("Valid verbosity levels are: Debug, Info, Warn/Warning, or Error.\n"); printf("Valid verbosity levels are: Debug, Info, "
"Warn/Warning, or Error.\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
break; break;
} }
case Option::Config: case Option::Config: {
{ if (++i >= argc) {
if (++i >= argc)
{
log_printf(ERROR, "Config file is not specified."); log_printf(ERROR, "Config file is not specified.");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -121,7 +114,6 @@ void read_cli_options(int argc, char** argv)
break; break;
} }
case Option::Help: case Option::Help:
{
printf(R"(logid version %s printf(R"(logid version %s
Usage: %s [options] Usage: %s [options]
Possible options are: Possible options are:
@ -130,14 +122,10 @@ Possible options are:
-c,--config [file path] Change config file from default at %s -c,--config [file path] Change config file from default at %s
-h,--help Print this message. -h,--help Print this message.
)", LOGIOPS_VERSION, argv[0], DEFAULT_CONFIG_FILE); )", LOGIOPS_VERSION, argv[0], DEFAULT_CONFIG_FILE);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
}
case Option::Version: case Option::Version:
{
printf("%s\n", LOGIOPS_VERSION); printf("%s\n", LOGIOPS_VERSION);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
}
case Option::None: case Option::None:
break; break;
} }
@ -147,7 +135,7 @@ Possible options are:
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
read_cli_options(argc, argv); readCliOptions(argc, argv);
/* /*
// Read config // Read config
@ -168,8 +156,7 @@ int main(int argc, char** argv)
// Scan devices, create listeners, handlers, etc. // Scan devices, create listeners, handlers, etc.
finder = new DeviceManager(); finder = new DeviceManager();
while(!kill_logid) while(!kill_logid) {
{
finder_reloading.lock(); finder_reloading.lock();
finder_reloading.unlock(); finder_reloading.unlock();
finder->run(); finder->run();