From 1d001237ba45b7ca5ee319f0b09d6e764b7dadb3 Mon Sep 17 00:00:00 2001 From: pixl Date: Wed, 24 Jun 2020 00:53:04 -0400 Subject: [PATCH] Monitor wake up/sleep events with Receiver --- src/logid/Receiver.cpp | 20 ++++++++---- src/logid/Receiver.h | 4 +-- src/logid/backend/dj/Receiver.cpp | 39 +++++++++++++++--------- src/logid/backend/dj/Receiver.h | 14 +++++++-- src/logid/backend/dj/ReceiverMonitor.cpp | 2 ++ src/logid/backend/dj/ReceiverMonitor.h | 2 +- src/logid/backend/raw/DeviceMonitor.cpp | 2 +- 7 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/logid/Receiver.cpp b/src/logid/Receiver.cpp index c718c11..de28907 100644 --- a/src/logid/Receiver.cpp +++ b/src/logid/Receiver.cpp @@ -25,7 +25,7 @@ using namespace logid; using namespace logid::backend; -Receiver::Receiver(std::string path) : dj::ReceiverMonitor(path) +Receiver::Receiver(std::string path) : dj::ReceiverMonitor(path), _path (path) { log_printf(DEBUG, "logid::Receiver created on %s", path.c_str()); } @@ -33,8 +33,17 @@ Receiver::Receiver(std::string path) : dj::ReceiverMonitor(path) void Receiver::addDevice(hidpp::DeviceConnectionEvent event) { try { + auto dev = _devices.find(event.index); + if(dev != _devices.end()) { + if(event.linkEstablished) + dev->second->wakeup(); + else + dev->second->sleep(); + return; + } + if(!event.linkEstablished) - return; // Device is probably asleep, wait until it wakes up + return; hidpp::Device hidpp_device(receiver(), event); @@ -49,13 +58,12 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event) std::shared_ptr device = std::make_shared( receiver()->rawDevice(), event.index); - assert(_devices.find(event.index) == _devices.end()); - _devices.emplace(event.index, device); } catch(hidpp10::Error &e) { - log_printf(ERROR, "Caught HID++ 1.0 error while trying to initialize " - "%s:%d: %s", _path.c_str(), event.index, e.what()); + log_printf(ERROR, + "Caught HID++ 1.0 error while trying to initialize " + "%s:%d: %s", _path.c_str(), event.index, e.what()); } catch(hidpp20::Error &e) { log_printf(ERROR, "Caught HID++ 2.0 error while trying to initialize " "%s:%d: %s", _path.c_str(), event.index, e.what()); diff --git a/src/logid/Receiver.h b/src/logid/Receiver.h index 313bc91..029c80c 100644 --- a/src/logid/Receiver.h +++ b/src/logid/Receiver.h @@ -31,8 +31,8 @@ namespace logid Receiver(std::string path); protected: - virtual void addDevice(backend::hidpp::DeviceConnectionEvent event); - virtual void removeDevice(backend::hidpp::DeviceIndex index); + void addDevice(backend::hidpp::DeviceConnectionEvent event) override; + void removeDevice(backend::hidpp::DeviceIndex index) override; private: std::map> _devices; std::string _path; diff --git a/src/logid/backend/dj/Receiver.cpp b/src/logid/backend/dj/Receiver.cpp index 08784f1..b3d183a 100644 --- a/src/logid/backend/dj/Receiver.cpp +++ b/src/logid/backend/dj/Receiver.cpp @@ -53,7 +53,7 @@ Receiver::Receiver(std::string path) : void Receiver::enumerateDj() { - sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{}); + _sendDjRequest(hidpp::DefaultDevice, GetPairedDevices,{}); } Receiver::NotificationFlags Receiver::getHidppNotifications() @@ -228,29 +228,29 @@ hidpp::DeviceConnectionEvent Receiver::deviceConnectionEvent( hidpp::DeviceConnectionEvent event{}; event.index = report.deviceIndex(); - event.unifying = ((report.paramBegin()[0] & 0b111) == 0x04); + event.unifying = ((report.address() & 0b111) == 0x04); event.deviceType = static_cast( - report.paramBegin()[1] & 0x0f); - event.softwarePresent = report.paramBegin()[1] & (1<<4); - event.encrypted = report.paramBegin()[1] & (1<<5); - event.linkEstablished = report.paramBegin()[1] & (1<<6); - event.withPayload = report.paramBegin()[1] & (1<<7); + report.paramBegin()[0] & 0x0f); + event.softwarePresent = report.paramBegin()[0] & (1<<4); + event.encrypted = report.paramBegin()[0] & (1<<5); + event.linkEstablished = !(report.paramBegin()[0] & (1<<6)); + event.withPayload = report.paramBegin()[0] & (1<<7); - event.pid = report.paramBegin()[3]; - event.pid |= (report.paramBegin()[2] << 8); + event.pid =(report.paramBegin()[2] << 8); + event.pid |= report.paramBegin()[1]; return event; } -void Receiver::handleDjEvent(Report& report) +void Receiver::_handleDjEvent(Report& report) { for(auto& handler : _dj_event_handlers) if(handler.second->condition(report)) handler.second->callback(report); } -void Receiver::handleHidppEvent(hidpp::Report &report) +void Receiver::_handleHidppEvent(hidpp::Report &report) { for(auto& handler : _hidpp_event_handlers) if(handler.second->condition(report)) @@ -295,7 +295,7 @@ Receiver::hidppEventHandlers() return _hidpp_event_handlers; } -void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function, +void Receiver::_sendDjRequest(hidpp::DeviceIndex index, uint8_t function, const std::vector&& params) { assert(params.size() <= LongParamLength); @@ -310,10 +310,19 @@ void Receiver::sendDjRequest(hidpp::DeviceIndex index, uint8_t function, _raw_device->sendReportNoResponse(request.rawData()); } +Receiver::ConnectionStatusEvent Receiver::connectionStatusEvent(Report& report) +{ + assert(report.feature() == ConnectionStatus); + ConnectionStatusEvent event{}; + event.index = report.index(); + event.linkLost = report.paramBegin()[0]; + return event; +} + void Receiver::listen() { if(!_raw_device->isListening()) - std::thread{[=]() { _raw_device->listen(); }}.detach(); + std::thread{[this]() { this->_raw_device->listen(); }}.detach(); if(_raw_device->eventHandlers().find("RECV_HIDPP") == _raw_device->eventHandlers().end()) { @@ -328,7 +337,7 @@ void Receiver::listen() hidpp_handler->callback = [this](std::vector& report) ->void { hidpp::Report _report(report); - this->handleHidppEvent(_report); + this->_handleHidppEvent(_report); }; _raw_device->addEventHandler("RECV_HIDPP", hidpp_handler); } @@ -346,7 +355,7 @@ void Receiver::listen() dj_handler->callback = [this](std::vector& report)->void { Report _report(report); - this->handleDjEvent(_report); + this->_handleDjEvent(_report); }; _raw_device->addEventHandler("RECV_DJ", dj_handler); } diff --git a/src/logid/backend/dj/Receiver.h b/src/logid/backend/dj/Receiver.h index ce39330..97aca4a 100644 --- a/src/logid/backend/dj/Receiver.h +++ b/src/logid/backend/dj/Receiver.h @@ -69,6 +69,14 @@ namespace dj void enumerateDj(); + struct ConnectionStatusEvent + { + hidpp::DeviceIndex index; + bool linkLost; + }; + + ConnectionStatusEvent connectionStatusEvent(dj::Report& report); + /* The following functions deal with HID++ 1.0 features. * While these are not technically DJ functions, it is redundant * to have a separate hidpp10::Receiver class for these functions. @@ -153,11 +161,11 @@ namespace dj std::shared_ptr rawDevice() const; private: - void sendDjRequest(hidpp::DeviceIndex index, uint8_t function, + void _sendDjRequest(hidpp::DeviceIndex index, uint8_t function, const std::vector&& params); - void handleDjEvent(dj::Report& report); - void handleHidppEvent(hidpp::Report& report); + void _handleDjEvent(dj::Report& report); + void _handleHidppEvent(hidpp::Report& report); std::map> _dj_event_handlers; diff --git a/src/logid/backend/dj/ReceiverMonitor.cpp b/src/logid/backend/dj/ReceiverMonitor.cpp index 5674b5f..6447f75 100644 --- a/src/logid/backend/dj/ReceiverMonitor.cpp +++ b/src/logid/backend/dj/ReceiverMonitor.cpp @@ -73,6 +73,8 @@ void ReceiverMonitor::run() void ReceiverMonitor::stop() { + _receiver->removeHidppEventHandler("RECVMON"); + _receiver->stopListening(); } diff --git a/src/logid/backend/dj/ReceiverMonitor.h b/src/logid/backend/dj/ReceiverMonitor.h index 860aed7..73d7938 100644 --- a/src/logid/backend/dj/ReceiverMonitor.h +++ b/src/logid/backend/dj/ReceiverMonitor.h @@ -32,7 +32,7 @@ namespace dj class ReceiverMonitor { public: - ReceiverMonitor(std::string path); + explicit ReceiverMonitor(std::string path); void enumerate(); void run(); diff --git a/src/logid/backend/raw/DeviceMonitor.cpp b/src/logid/backend/raw/DeviceMonitor.cpp index 6a9027c..8d4beda 100644 --- a/src/logid/backend/raw/DeviceMonitor.cpp +++ b/src/logid/backend/raw/DeviceMonitor.cpp @@ -149,7 +149,7 @@ void DeviceMonitor::enumerate() std::string devnode = udev_device_get_devnode(device); udev_device_unref(device); - std::thread([this](const std::string name) { + std::thread([this](const std::string& name) { this->addDevice(name); }, devnode).detach(); }