Use consistent code style

Only files that are currently used in logid are changed.
master
pixl 4 years ago
parent bd080e7ef6
commit dd75df8c18
No known key found for this signature in database
GPG Key ID: 1866C148CD593B6E
  1. 2
      src/logid/Device.cpp
  2. 8
      src/logid/DeviceManager.cpp
  3. 6
      src/logid/DeviceManager.h
  4. 2
      src/logid/backend/Error.cpp
  5. 2
      src/logid/backend/Error.h
  6. 21
      src/logid/backend/dj/Error.cpp
  7. 10
      src/logid/backend/dj/Error.h
  8. 107
      src/logid/backend/dj/Receiver.cpp
  9. 20
      src/logid/backend/dj/Receiver.h
  10. 13
      src/logid/backend/dj/ReceiverMonitor.cpp
  11. 41
      src/logid/backend/dj/Report.cpp
  12. 6
      src/logid/backend/dj/Report.h
  13. 82
      src/logid/backend/hidpp/Device.cpp
  14. 19
      src/logid/backend/hidpp/Device.h
  15. 0
      src/logid/backend/hidpp/Error.cpp
  16. 0
      src/logid/backend/hidpp/Error.h
  17. 105
      src/logid/backend/hidpp/Report.cpp
  18. 22
      src/logid/backend/hidpp/Report.h
  19. 6
      src/logid/backend/hidpp/defs.h
  20. 5
      src/logid/backend/hidpp10/Device.cpp
  21. 59
      src/logid/backend/hidpp10/Error.cpp
  22. 4
      src/logid/backend/hidpp10/Error.h
  23. 51
      src/logid/backend/hidpp20/Error.cpp
  24. 4
      src/logid/backend/hidpp20/Error.h
  25. 2
      src/logid/backend/hidpp20/Feature.h
  26. 4
      src/logid/backend/hidpp20/features/DeviceName.h
  27. 3
      src/logid/backend/hidpp20/features/Root.cpp
  28. 6
      src/logid/backend/hidpp20/features/Root.h
  29. 61
      src/logid/backend/raw/DeviceMonitor.cpp
  30. 14
      src/logid/backend/raw/DeviceMonitor.h
  31. 222
      src/logid/backend/raw/RawDevice.cpp
  32. 39
      src/logid/backend/raw/RawDevice.h
  33. 14
      src/logid/backend/raw/defs.h
  34. 137
      src/logid/logid.cpp

@ -5,7 +5,7 @@ using namespace logid;
using namespace logid::backend;
Device::Device(std::string path, backend::hidpp::DeviceIndex index) :
_hidpp20 (path, index), _path (path), _index (index)
_hidpp20 (path, index), _path (std::move(path)), _index (index)
{
log_printf(DEBUG, "logid::Device created on %s:%d", _path.c_str(), _index);
}

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

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

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

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

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

@ -1,5 +1,5 @@
#ifndef LOGID_HIDPP_BACKEND_DJ_ERROR_H
#define LOGID_HIDPP_BACKEND_DJ_ERROR_H
#ifndef LOGID_BACKEND_DJ_ERROR_H
#define LOGID_BACKEND_DJ_ERROR_H
#include <cstdint>
#include <stdexcept>
@ -17,9 +17,9 @@ namespace dj
KeepAliveTimeout = 0x01
};
Error(uint8_t code);
explicit Error(uint8_t code);
virtual const char* what() const noexcept;
const char* what() const noexcept override;
uint8_t code() const noexcept;
private:
@ -27,4 +27,4 @@ namespace dj
};
}}}
#endif //LOGID_HIDPP_BACKEND_DJ_ERROR_H
#endif //LOGID_BACKEND_DJ_ERROR_H

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

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

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

@ -28,37 +28,36 @@ static const std::array<uint8_t, 34> DJReportDesc = {
bool dj::supportsDjReports(std::vector<uint8_t>&& rdesc)
{
auto it = std::search(rdesc.begin(), rdesc.end(), DJReportDesc.begin(), DJReportDesc.end());
auto it = std::search(rdesc.begin(), rdesc.end(),
DJReportDesc.begin(), DJReportDesc.end());
return it != rdesc.end();
}
Report::Report(std::vector<uint8_t>& data) : _data (data)
{
switch(data[Offset::Type])
{
case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength);
break;
case ReportType::Long:
_data.resize(HeaderLength+LongParamLength);
break;
default:
assert(false);
switch(data[Offset::Type]) {
case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength);
break;
case ReportType::Long:
_data.resize(HeaderLength+LongParamLength);
break;
default:
assert(false);
}
}
Report::Report(Report::Type type, hidpp::DeviceIndex index, uint8_t feature)
{
switch(type)
{
case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength);
break;
case ReportType::Long:
_data.resize(HeaderLength+LongParamLength);
break;
default:
assert(false);
switch(type) {
case ReportType::Short:
_data.resize(HeaderLength+ShortParamLength);
break;
case ReportType::Long:
_data.resize(HeaderLength+LongParamLength);
break;
default:
assert(false);
}
_data[Offset::Type] = type;

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

@ -13,16 +13,15 @@ using namespace logid::backend::hidpp;
const char* Device::InvalidDevice::what() const noexcept
{
switch(_reason)
{
case NoHIDPPReport:
return "Invalid HID++ device";
case InvalidRawDevice:
return "Invalid raw device";
case Asleep:
return "Device asleep";
default:
return "Invalid device";
switch(_reason) {
case NoHIDPPReport:
return "Invalid HID++ device";
case InvalidRawDevice:
return "Invalid raw device";
case Asleep:
return "Device asleep";
default:
return "Invalid device";
}
}
@ -58,10 +57,25 @@ Device::Device(std::shared_ptr<dj::Receiver> receiver,
_init();
}
std::string Device::devicePath() const
{
return _path;
}
DeviceIndex Device::deviceIndex() const
{
return _index;
}
std::tuple<uint8_t, uint8_t> Device::version() const
{
return _version;
}
void Device::_init()
{
supported_reports = getSupportedReports(_raw_device->reportDescriptor());
if(!supported_reports)
_supported_reports = getSupportedReports(_raw_device->reportDescriptor());
if(!_supported_reports)
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
try {
@ -101,20 +115,20 @@ Device::~Device()
void Device::addEventHandler(const std::string& nickname,
const std::shared_ptr<EventHandler>& handler)
{
auto it = event_handlers.find(nickname);
assert(it == event_handlers.end());
auto it = _event_handlers.find(nickname);
assert(it == _event_handlers.end());
event_handlers.emplace(nickname, handler);
_event_handlers.emplace(nickname, handler);
}
void Device::removeEventHandler(const std::string& nickname)
{
event_handlers.erase(nickname);
_event_handlers.erase(nickname);
}
void Device::handleEvent(Report& report)
{
for(auto& handler : event_handlers)
for(auto& handler : _event_handlers)
if(handler.second->condition(report))
handler.second->callback(report);
}
@ -123,26 +137,26 @@ Report Device::sendReport(Report& report)
{
switch(report.type())
{
case Report::Type::Short:
if(!(supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
report.setType(Report::Type::Long);
break;
case Report::Type::Long:
/* Report can be truncated, but that isn't a good idea. */
assert(supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
case Report::Type::Short:
if(!(_supported_reports & HIDPP_REPORT_SHORT_SUPPORTED))
report.setType(Report::Type::Long);
break;
case Report::Type::Long:
/* Report can be truncated, but that isn't a good idea. */
assert(_supported_reports & HIDPP_REPORT_LONG_SUPPORTED);
}
auto raw_response = _raw_device->sendReport(report.rawReport());
Report response(raw_response);
Report::hidpp10_error hidpp10Error{};
if(response.isError10(&hidpp10Error))
throw hidpp10::Error(hidpp10Error.error_code);
Report::Hidpp10Error hidpp10_error{};
if(response.isError10(&hidpp10_error))
throw hidpp10::Error(hidpp10_error.error_code);
Report::hidpp20_error hidpp20Error{};
if(response.isError20(&hidpp20Error))
throw hidpp10::Error(hidpp20Error.error_code);
Report::Hidpp20Error hidpp20_error{};
if(response.isError20(&hidpp20_error))
throw hidpp10::Error(hidpp20_error.error_code);
return response;
}
@ -153,20 +167,20 @@ void Device::listen()
std::thread{[=]() { _raw_device->listen(); }}.detach();
// Pass all HID++ events with device index to this device.
std::shared_ptr<RawEventHandler> rawEventHandler;
rawEventHandler->condition = [this](std::vector<uint8_t>& report)->bool
std::shared_ptr<raw::RawEventHandler> handler;
handler->condition = [this](std::vector<uint8_t>& report)->bool
{
return (report[Offset::Type] == Report::Type::Short ||
report[Offset::Type] == Report::Type::Long) &&
(report[Offset::DeviceIndex] == this->_index);
};
rawEventHandler->callback = [this](std::vector<uint8_t>& report)->void
handler->callback = [this](std::vector<uint8_t>& report)->void
{
Report _report(report);
this->handleEvent(_report);
};
_raw_device->addEventHandler("DEV_" + std::to_string(_index), rawEventHandler);
_raw_device->addEventHandler("DEV_" + std::to_string(_index), handler);
}
void Device::stopListening()

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

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

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

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

@ -41,10 +41,11 @@ std::vector<uint8_t> Device::setRegister(uint8_t address,
return accessRegister(sub_id, address, params);
}
std::vector<uint8_t> Device::accessRegister(uint8_t sub_id, uint8_t address, const std::vector<uint8_t> &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::Short : hidpp::Report::Type::Long;
hidpp::Report::Type::Short : hidpp::Report::Type::Long;
hidpp::Report request(type, deviceIndex(), sub_id, address);
std::copy(params.begin(), params.end(), request.paramBegin());

@ -11,36 +11,35 @@ Error::Error(uint8_t code): _code(code)
const char* Error::what() const noexcept
{
switch(_code)
{
case Success:
return "Success";
case InvalidSubID:
return "Invalid sub ID";
case InvalidAddress:
return "Invalid address";
case InvalidValue:
return "Invalid value";
case ConnectFail:
return "Connection failure";
case TooManyDevices:
return "Too many devices";
case AlreadyExists:
return "Already exists";
case Busy:
return "Busy";
case UnknownDevice:
return "Unknown device";
case ResourceError:
return "Resource error";
case RequestUnavailable:
return "Request unavailable";
case InvalidParameterValue:
return "Invalid parameter value";
case WrongPINCode:
return "Wrong PIN code";
default:
return std::string("Unknown error code " + std::to_string(_code)).c_str();
switch(_code) {
case Success:
return "Success";
case InvalidSubID:
return "Invalid sub ID";
case InvalidAddress:
return "Invalid address";
case InvalidValue:
return "Invalid value";
case ConnectFail:
return "Connection failure";
case TooManyDevices:
return "Too many devices";
case AlreadyExists:
return "Already exists";
case Busy:
return "Busy";
case UnknownDevice:
return "Unknown device";
case ResourceError:
return "Resource error";
case RequestUnavailable:
return "Request unavailable";
case InvalidParameterValue:
return "Invalid parameter value";
case WrongPINCode:
return "Wrong PIN code";
default:
return "Unknown error code";
}
}

@ -28,9 +28,9 @@ namespace hidpp10 {
WrongPINCode = 0x0C
};
Error(uint8_t code);
explicit Error(uint8_t code);
virtual const char* what() const noexcept;
const char* what() const noexcept override;
uint8_t code() const noexcept;
private:

@ -11,32 +11,31 @@ Error::Error(uint8_t code) : _code (code)
const char* Error::what() const noexcept
{
switch(_code)
{
case NoError:
return "No error";
case Unknown:
return "Unknown";
case InvalidArgument:
return "Invalid argument";
case OutOfRange:
return "Out of range";
case HardwareError:
return "Hardware error";
case LogitechInternal:
return "Logitech internal feature";
case InvalidFeatureIndex:
return "Invalid feature index";
case InvalidFunctionID:
return "Invalid function ID";
case Busy:
return "Busy";
case Unsupported:
return "Unsupported";
case UnknownDevice:
return "Unknown device";
default:
return std::string("Unknown error code " + std::to_string(_code)).c_str();
switch(_code) {
case NoError:
return "No error";
case Unknown:
return "Unknown";
case InvalidArgument:
return "Invalid argument";
case OutOfRange:
return "Out of range";
case HardwareError:
return "Hardware error";
case LogitechInternal:
return "Logitech internal feature";
case InvalidFeatureIndex:
return "Invalid feature index";
case InvalidFunctionID:
return "Invalid function ID";
case Busy:
return "Busy";
case Unsupported:
return "Unsupported";
case UnknownDevice:
return "Unknown device";
default:
return "Unknown error code";
}
}

@ -26,9 +26,9 @@ namespace hidpp20 {
UnknownDevice = 10
};
Error(uint8_t code);
explicit Error(uint8_t code);
virtual const char* what() const noexcept;
const char* what() const noexcept override;
uint8_t code() const noexcept;
private:

@ -11,7 +11,7 @@ namespace hidpp20 {
{
public:
explicit UnsupportedFeature(uint16_t ID) : _f_id (ID) {}
virtual const char* what() const noexcept;
const char* what() const noexcept override;
uint16_t code() const noexcept;
private:
uint16_t _f_id;

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

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

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

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

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

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

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

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

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

Loading…
Cancel
Save