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;
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -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 "Reserved";
|
||||||
return std::string("Reserved error code " + std::to_string(_code))
|
|
||||||
.c_str();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Error::code() const noexcept
|
||||||
|
{
|
||||||
|
return _code;
|
||||||
}
|
}
|
|
@ -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
|
|
@ -12,12 +12,11 @@ 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:
|
return "Invalid receiver";
|
||||||
return "Invalid receiver";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -28,37 +28,36 @@ 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;
|
case ReportType::Long:
|
||||||
case ReportType::Long:
|
_data.resize(HeaderLength+LongParamLength);
|
||||||
_data.resize(HeaderLength+LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
assert(false);
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
case ReportType::Long:
|
||||||
case ReportType::Long:
|
_data.resize(HeaderLength+LongParamLength);
|
||||||
_data.resize(HeaderLength+LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
assert(false);
|
||||||
assert(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_data[Offset::Type] = type;
|
_data[Offset::Type] = type;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -13,16 +13,15 @@ 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:
|
return "Invalid raw device";
|
||||||
return "Invalid raw device";
|
case Asleep:
|
||||||
case Asleep:
|
return "Device asleep";
|
||||||
return "Device asleep";
|
default:
|
||||||
default:
|
return "Invalid device";
|
||||||
return "Invalid device";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -123,26 +137,26 @@ 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()
|
||||||
|
|
|
@ -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
|
|
@ -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,16 +102,15 @@ const char *Report::InvalidReportLength::what() const noexcept
|
||||||
Report::Report(Report::Type type, DeviceIndex device_index,
|
Report::Report(Report::Type type, DeviceIndex device_index,
|
||||||
uint8_t 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;
|
case Type::Long:
|
||||||
case Type::Long:
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw InvalidReportID();
|
||||||
throw InvalidReportID();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_data[Offset::Type] = type;
|
_data[Offset::Type] = type;
|
||||||
|
@ -119,25 +122,25 @@ 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;
|
case Type::Long:
|
||||||
case Type::Long:
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw InvalidReportID();
|
||||||
throw InvalidReportID();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_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,16 +148,15 @@ 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;
|
case Type::Long:
|
||||||
case Type::Long:
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw InvalidReportID();
|
||||||
throw InvalidReportID();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,16 +167,15 @@ 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;
|
case Type::Long:
|
||||||
case Type::Long:
|
_data.resize(HeaderLength + LongParamLength);
|
||||||
_data.resize(HeaderLength + LongParamLength);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw InvalidReportID();
|
||||||
throw InvalidReportID();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_data[Offset::Type] = type;
|
_data[Offset::Type] = type;
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -41,10 +41,11 @@ 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> ¶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 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);
|
hidpp::Report request(type, deviceIndex(), sub_id, address);
|
||||||
std::copy(params.begin(), params.end(), request.paramBegin());
|
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
|
const char* Error::what() const noexcept
|
||||||
{
|
{
|
||||||
switch(_code)
|
switch(_code) {
|
||||||
{
|
case Success:
|
||||||
case Success:
|
return "Success";
|
||||||
return "Success";
|
case InvalidSubID:
|
||||||
case InvalidSubID:
|
return "Invalid sub ID";
|
||||||
return "Invalid sub ID";
|
case InvalidAddress:
|
||||||
case InvalidAddress:
|
return "Invalid address";
|
||||||
return "Invalid address";
|
case InvalidValue:
|
||||||
case InvalidValue:
|
return "Invalid value";
|
||||||
return "Invalid value";
|
case ConnectFail:
|
||||||
case ConnectFail:
|
return "Connection failure";
|
||||||
return "Connection failure";
|
case TooManyDevices:
|
||||||
case TooManyDevices:
|
return "Too many devices";
|
||||||
return "Too many devices";
|
case AlreadyExists:
|
||||||
case AlreadyExists:
|
return "Already exists";
|
||||||
return "Already exists";
|
case Busy:
|
||||||
case Busy:
|
return "Busy";
|
||||||
return "Busy";
|
case UnknownDevice:
|
||||||
case UnknownDevice:
|
return "Unknown device";
|
||||||
return "Unknown device";
|
case ResourceError:
|
||||||
case ResourceError:
|
return "Resource error";
|
||||||
return "Resource error";
|
case RequestUnavailable:
|
||||||
case RequestUnavailable:
|
return "Request unavailable";
|
||||||
return "Request unavailable";
|
case InvalidParameterValue:
|
||||||
case InvalidParameterValue:
|
return "Invalid parameter value";
|
||||||
return "Invalid parameter value";
|
case WrongPINCode:
|
||||||
case WrongPINCode:
|
return "Wrong PIN code";
|
||||||
return "Wrong PIN code";
|
default:
|
||||||
default:
|
return "Unknown error code";
|
||||||
return std::string("Unknown error code " + std::to_string(_code)).c_str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -11,32 +11,31 @@ 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:
|
return "Unknown";
|
||||||
return "Unknown";
|
case InvalidArgument:
|
||||||
case InvalidArgument:
|
return "Invalid argument";
|
||||||
return "Invalid argument";
|
case OutOfRange:
|
||||||
case OutOfRange:
|
return "Out of range";
|
||||||
return "Out of range";
|
case HardwareError:
|
||||||
case HardwareError:
|
return "Hardware error";
|
||||||
return "Hardware error";
|
case LogitechInternal:
|
||||||
case LogitechInternal:
|
return "Logitech internal feature";
|
||||||
return "Logitech internal feature";
|
case InvalidFeatureIndex:
|
||||||
case InvalidFeatureIndex:
|
return "Invalid feature index";
|
||||||
return "Invalid feature index";
|
case InvalidFunctionID:
|
||||||
case InvalidFunctionID:
|
return "Invalid function ID";
|
||||||
return "Invalid function ID";
|
case Busy:
|
||||||
case Busy:
|
return "Busy";
|
||||||
return "Busy";
|
case Unsupported:
|
||||||
case Unsupported:
|
return "Unsupported";
|
||||||
return "Unsupported";
|
case UnknownDevice:
|
||||||
case UnknownDevice:
|
return "Unknown device";
|
||||||
return "Unknown device";
|
default:
|
||||||
default:
|
return "Unknown error code";
|
||||||
return std::string("Unknown error code " + std::to_string(_code)).c_str();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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,9 +40,9 @@ 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();
|
||||||
};
|
};
|
||||||
}}}
|
}}}
|
||||||
|
|
|
@ -13,40 +13,39 @@ 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();
|
this->stop();
|
||||||
if(is_running)
|
|
||||||
running.unlock();
|
|
||||||
else
|
|
||||||
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");
|
||||||
|
|
||||||
ret = udev_monitor_enable_receiving(monitor);
|
ret = udev_monitor_enable_receiving(monitor);
|
||||||
|
@ -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,12 +85,13 @@ 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");
|
||||||
|
|
|
@ -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
|
|
@ -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,105 +26,116 @@ 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);
|
case hidpp::ReportType::Long:
|
||||||
case hidpp::ReportType::Long:
|
return length == (hidpp::LongParamLength +
|
||||||
return length == (hidpp::LongParamLength +
|
hidpp::Report::HeaderLength);
|
||||||
hidpp::Report::HeaderLength);
|
case dj::ReportType::Short:
|
||||||
case dj::ReportType::Short:
|
return length == (dj::ShortParamLength + dj::HeaderLength);
|
||||||
return length == (dj::ShortParamLength + dj::HeaderLength);
|
case dj::ReportType::Long:
|
||||||
case dj::ReportType::Long:
|
return length == (dj::LongParamLength + dj::HeaderLength);
|
||||||
return length == (dj::LongParamLength + dj::HeaderLength);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}}}
|
}}}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
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;
|
if (op_str == "--help") option = Option::Help;
|
||||||
if (op_str == "--help") option = Option::Help;
|
if (op_str == "--version") option = Option::Version;
|
||||||
if (op_str == "--version") option = Option::Version;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case 'v': // Verbosity
|
||||||
case 'v': // Verbosity
|
option = Option::Verbose;
|
||||||
option = Option::Verbose;
|
break;
|
||||||
break;
|
case 'V': //Version
|
||||||
case 'V': //Version
|
|
||||||
option = Option::Version;
|
option = Option::Version;
|
||||||
break;
|
break;
|
||||||
case 'c': // Config file path
|
case 'c': // Config file path
|
||||||
option = Option::Config;
|
option = Option::Config;
|
||||||
break;
|
break;
|
||||||
case 'h': // Help
|
case 'h': // Help
|
||||||
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;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Option::Config:
|
std::string loglevel = argv[i];
|
||||||
{
|
try {
|
||||||
if (++i >= argc)
|
global_verbosity = stringToLogLevel(argv[i]);
|
||||||
{
|
} catch (std::invalid_argument &e) {
|
||||||
log_printf(ERROR, "Config file is not specified.");
|
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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
config_file = argv[i];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case Option::Help:
|
break;
|
||||||
{
|
}
|
||||||
printf(R"(logid version %s
|
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]
|
Usage: %s [options]
|
||||||
Possible options are:
|
Possible options are:
|
||||||
-v,--verbose [level] Set log level to debug/info/warn/error (leave blank for debug)
|
-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
|
-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:
|
||||||
}
|
printf("%s\n", LOGIOPS_VERSION);
|
||||||
case Option::Version:
|
exit(EXIT_SUCCESS);
|
||||||
{
|
case Option::None:
|
||||||
printf("%s\n", LOGIOPS_VERSION);
|
break;
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
case Option::None:
|
|
||||||
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();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user