diff --git a/src/logid/Configuration.h b/src/logid/Configuration.h index 03eb62d..168c416 100644 --- a/src/logid/Configuration.h +++ b/src/logid/Configuration.h @@ -58,7 +58,6 @@ namespace logid libconfig::Config _config; }; - extern std::shared_ptr global_config; } #endif //LOGID_CONFIGURATION_H diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index 6f34d6b..5788b95 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -20,6 +20,7 @@ #include "util/log.h" #include "features/DPI.h" #include "Device.h" +#include "DeviceManager.h" #include "Receiver.h" #include "features/SmartShift.h" #include "features/RemapButton.h" @@ -31,24 +32,37 @@ using namespace logid; using namespace logid::backend; -Device::Device(std::string path, backend::hidpp::DeviceIndex index) : - _hidpp20 (path, index), _path (std::move(path)), _index (index), - _config (global_config, this), _receiver (nullptr) +Device::Device(std::string path, backend::hidpp::DeviceIndex index, + const std::shared_ptr& manager) : + _hidpp20 (path, index, + manager->config()->ioTimeout(), manager->workQueue()), + _path (std::move(path)), _index (index), + _config (manager->config(), this), + _receiver (nullptr), + _manager (manager) { _init(); } Device::Device(const std::shared_ptr& raw_device, - hidpp::DeviceIndex index) : _hidpp20(raw_device, index), _path - (raw_device->hidrawPath()), _index (index), - _config (global_config, this), _receiver (nullptr) + hidpp::DeviceIndex index, + const std::shared_ptr& manager) : + _hidpp20(raw_device, index), + _path (raw_device->hidrawPath()), _index (index), + _config (manager->config(), this), + _receiver (nullptr), + _manager (manager) { _init(); } -Device::Device(Receiver* receiver, hidpp::DeviceIndex index) : _hidpp20 - (receiver->rawReceiver(), index), _path (receiver->path()), _index (index), - _config (global_config, this), _receiver (receiver) +Device::Device(Receiver* receiver, hidpp::DeviceIndex index, + const std::shared_ptr& manager) : + _hidpp20 (receiver->rawReceiver(), index), + _path (receiver->path()), _index (index), + _config (manager->config(), this), + _receiver (receiver), + _manager (manager) { _init(); } @@ -111,6 +125,30 @@ void Device::reset() "available.", _path.c_str(), _index); } +std::shared_ptr Device::workQueue() const { + if(auto manager = _manager.lock()) { + return manager->workQueue(); + } else { + logPrintf(ERROR, "Device manager lost"); + logPrintf(ERROR, + "Fatal error occurred, file a bug report," + " the program will now exit."); + std::terminate(); + } +} + +std::shared_ptr Device::virtualInput() const { + if(auto manager = _manager.lock()) { + return manager->virtualInput(); + } else { + logPrintf(ERROR, "Device manager lost"); + logPrintf(ERROR, + "Fatal error occurred, file a bug report," + " the program will now exit."); + std::terminate(); + } +} + DeviceConfig& Device::config() { return _config; diff --git a/src/logid/Device.h b/src/logid/Device.h index f1ddd1f..fdb8c33 100644 --- a/src/logid/Device.h +++ b/src/logid/Device.h @@ -27,8 +27,10 @@ namespace logid { + class DeviceManager; class Device; class Receiver; + class InputDevice; class DeviceConfig { @@ -49,10 +51,13 @@ namespace logid class Device { public: - Device(std::string path, backend::hidpp::DeviceIndex index); + Device(std::string path, backend::hidpp::DeviceIndex index, + const std::shared_ptr& manager); Device(const std::shared_ptr& raw_device, - backend::hidpp::DeviceIndex index); - Device(Receiver* receiver, backend::hidpp::DeviceIndex index); + backend::hidpp::DeviceIndex index, + const std::shared_ptr& manager); + Device(Receiver* receiver, backend::hidpp::DeviceIndex index, + const std::shared_ptr& manager); std::string name(); uint16_t pid(); @@ -65,6 +70,10 @@ namespace logid void reset(); + [[nodiscard]] std::shared_ptr workQueue() const; + + [[nodiscard]] std::shared_ptr virtualInput() const; + template std::shared_ptr getFeature(std::string name) { auto it = _features.find(name); @@ -100,6 +109,7 @@ namespace logid DeviceConfig _config; Receiver* _receiver; + const std::weak_ptr _manager; void _makeResetMechanism(); std::unique_ptr> _reset_mechanism; diff --git a/src/logid/DeviceManager.cpp b/src/logid/DeviceManager.cpp index 924c499..37402d0 100644 --- a/src/logid/DeviceManager.cpp +++ b/src/logid/DeviceManager.cpp @@ -18,16 +18,55 @@ #include #include +#include #include "DeviceManager.h" #include "Receiver.h" #include "util/log.h" +#include "util/workqueue.h" #include "backend/hidpp10/Error.h" #include "backend/Error.h" using namespace logid; using namespace logid::backend; +namespace logid { + class _DeviceManager : public logid::DeviceManager + { + public: + template + explicit _DeviceManager(Args... args) : + DeviceManager(std::forward(args)...) { } + }; +} + +DeviceManager::DeviceManager(std::shared_ptr config, + std::shared_ptr virtual_input) : + backend::raw::DeviceMonitor(config->workerCount()), + _config (std::move(config)), + _virtual_input (std::move(virtual_input)) +{ +} + +std::shared_ptr DeviceManager::make( + const std::shared_ptr& config, + const std::shared_ptr& virtual_input) +{ + auto ret = std::make_shared<_DeviceManager>(config, virtual_input); + ret->_self = ret; + return ret; +} + +std::shared_ptr DeviceManager::config() const +{ + return _config; +} + +std::shared_ptr DeviceManager::virtualInput() const +{ + return _virtual_input; +} + void DeviceManager::addDevice(std::string path) { bool defaultExists = true; @@ -35,8 +74,8 @@ void DeviceManager::addDevice(std::string path) // Check if device is ignored before continuing { - raw::RawDevice raw_dev(path); - if(global_config->isIgnored(raw_dev.productId())) { + raw::RawDevice raw_dev(path, config()->ioTimeout(), workQueue()); + if(config()->isIgnored(raw_dev.productId())) { logPrintf(DEBUG, "%s: Device 0x%04x ignored.", path.c_str(), raw_dev.productId()); return; @@ -44,7 +83,8 @@ void DeviceManager::addDevice(std::string path) } try { - hidpp::Device device(path, hidpp::DefaultDevice); + hidpp::Device device(path, hidpp::DefaultDevice, + config()->ioTimeout(), workQueue()); isReceiver = device.version() == std::make_tuple(1, 0); } catch(hidpp10::Error &e) { if(e.code() != hidpp10::Error::UnknownDevice) @@ -62,19 +102,20 @@ void DeviceManager::addDevice(std::string path) if(isReceiver) { logPrintf(INFO, "Detected receiver at %s", path.c_str()); - auto receiver = std::make_shared(path); + auto receiver = std::make_shared(path, _self.lock()); receiver->run(); _receivers.emplace(path, receiver); } else { /* TODO: Can non-receivers only contain 1 device? * If the device exists, it is guaranteed to be an HID++ 2.0 device */ if(defaultExists) { - auto device = std::make_shared(path, hidpp::DefaultDevice); + auto device = std::make_shared(path, hidpp::DefaultDevice, + _self.lock()); _devices.emplace(path, device); } else { try { auto device = std::make_shared(path, - hidpp::CordedDevice); + hidpp::CordedDevice, _self.lock()); _devices.emplace(path, device); } catch(hidpp10::Error &e) { if(e.code() != hidpp10::Error::UnknownDevice) diff --git a/src/logid/DeviceManager.h b/src/logid/DeviceManager.h index 6305963..55c53f5 100644 --- a/src/logid/DeviceManager.h +++ b/src/logid/DeviceManager.h @@ -30,21 +30,31 @@ namespace logid { + class workqueue; + class InputDevice; class DeviceManager : public backend::raw::DeviceMonitor { public: - DeviceManager() = default; + static std::shared_ptr make( + const std::shared_ptr& config, + const std::shared_ptr& virtual_input); + [[nodiscard]] std::shared_ptr config() const; + [[nodiscard]] std::shared_ptr virtualInput() const; protected: - void addDevice(std::string path) override; - void removeDevice(std::string path) override; + void addDevice(std::string path) final; + void removeDevice(std::string path) final; private: - + friend class _DeviceManager; + DeviceManager(std::shared_ptr config, + std::shared_ptr virtual_input); + std::weak_ptr _self; + std::shared_ptr _config; + std::shared_ptr _virtual_input; std::map> _devices; std::map> _receivers; }; - extern std::unique_ptr device_manager; } #endif //LOGID_DEVICEMANAGER_H \ No newline at end of file diff --git a/src/logid/InputDevice.h b/src/logid/InputDevice.h index c3c803d..17e5045 100644 --- a/src/logid/InputDevice.h +++ b/src/logid/InputDevice.h @@ -65,8 +65,6 @@ namespace logid libevdev* device; libevdev_uinput* ui_device{}; }; - - extern std::unique_ptr virtual_input; } #endif //LOGID_INPUTDEVICE_H diff --git a/src/logid/Receiver.cpp b/src/logid/Receiver.cpp index 49c053d..98a6459 100644 --- a/src/logid/Receiver.cpp +++ b/src/logid/Receiver.cpp @@ -17,6 +17,7 @@ */ #include "Receiver.h" +#include "DeviceManager.h" #include "util/log.h" #include "backend/hidpp10/Error.h" #include "backend/hidpp20/Error.h" @@ -25,17 +26,30 @@ using namespace logid; using namespace logid::backend; -Receiver::Receiver(const std::string& path) : - dj::ReceiverMonitor(path), _path (path) +Receiver::Receiver(const std::string& path, + const std::shared_ptr& manager) : + dj::ReceiverMonitor(path, + manager->config()->ioTimeout(), + manager->workQueue()), + _path (path), _manager (manager) { } void Receiver::addDevice(hidpp::DeviceConnectionEvent event) { std::unique_lock lock(_devices_change); + + auto manager = _manager.lock(); + if(!manager) { + logPrintf(ERROR, "Orphan Receiver, missing DeviceManager"); + logPrintf(ERROR, + "Fatal error, file a bug report. Program will now exit."); + std::terminate(); + } + try { // Check if device is ignored before continuing - if(global_config->isIgnored(event.pid)) { + if(manager->config()->isIgnored(event.pid)) { logPrintf(DEBUG, "%s:%d: Device 0x%04x ignored.", _path.c_str(), event.index, event.pid); return; @@ -64,7 +78,7 @@ void Receiver::addDevice(hidpp::DeviceConnectionEvent event) } std::shared_ptr device = std::make_shared(this, - event.index); + event.index, manager); _devices.emplace(event.index, device); diff --git a/src/logid/Receiver.h b/src/logid/Receiver.h index e055008..509113f 100644 --- a/src/logid/Receiver.h +++ b/src/logid/Receiver.h @@ -28,7 +28,8 @@ namespace logid class Receiver : public backend::dj::ReceiverMonitor { public: - explicit Receiver(const std::string& path); + explicit Receiver(const std::string& path, + const std::shared_ptr& manager); const std::string& path() const; std::shared_ptr rawReceiver(); protected: @@ -38,6 +39,7 @@ namespace logid std::mutex _devices_change; std::map> _devices; std::string _path; + std::weak_ptr _manager; }; } diff --git a/src/logid/actions/ChangeDPI.cpp b/src/logid/actions/ChangeDPI.cpp index faab6b9..3929fbc 100644 --- a/src/logid/actions/ChangeDPI.cpp +++ b/src/logid/actions/ChangeDPI.cpp @@ -39,7 +39,8 @@ void ChangeDPI::press() { _pressed = true; if(_dpi) { - task::spawn([this]{ + task::spawn(_device->workQueue(), + [this]{ try { uint16_t last_dpi = _dpi->getDPI(_config.sensor()); _dpi->setDPI(last_dpi + _config.interval(), _config.sensor()); diff --git a/src/logid/actions/ChangeHostAction.cpp b/src/logid/actions/ChangeHostAction.cpp index 411b8ac..84c3375 100644 --- a/src/logid/actions/ChangeHostAction.cpp +++ b/src/logid/actions/ChangeHostAction.cpp @@ -44,7 +44,8 @@ void ChangeHostAction::press() void ChangeHostAction::release() { if(_change_host) { - task::spawn([this] { + task::spawn(_device->workQueue(), + [this] { auto host_info = _change_host->getHostInfo(); auto next_host = _config.nextHost(host_info); if(next_host != host_info.currentHost) diff --git a/src/logid/actions/CycleDPI.cpp b/src/logid/actions/CycleDPI.cpp index 19b729c..a5b33c7 100644 --- a/src/logid/actions/CycleDPI.cpp +++ b/src/logid/actions/CycleDPI.cpp @@ -40,7 +40,8 @@ void CycleDPI::press() { _pressed = true; if(_dpi && !_config.empty()) { - task::spawn([this](){ + task::spawn(_device->workQueue(), + [this](){ uint16_t dpi = _config.nextDPI(); try { _dpi->setDPI(dpi, _config.sensor()); diff --git a/src/logid/actions/KeypressAction.cpp b/src/logid/actions/KeypressAction.cpp index a71546b..caa004c 100644 --- a/src/logid/actions/KeypressAction.cpp +++ b/src/logid/actions/KeypressAction.cpp @@ -16,6 +16,7 @@ * */ #include "KeypressAction.h" +#include "../Device.h" #include "../util/log.h" #include "../InputDevice.h" #include "../backend/hidpp20/features/ReprogControls.h" @@ -32,14 +33,14 @@ void KeypressAction::press() { _pressed = true; for(auto& key : _config.keys()) - virtual_input->pressKey(key); + _device->virtualInput()->pressKey(key); } void KeypressAction::release() { _pressed = false; for(auto& key : _config.keys()) - virtual_input->releaseKey(key); + _device->virtualInput()->releaseKey(key); } uint8_t KeypressAction::reprogFlags() const @@ -64,11 +65,13 @@ KeypressAction::Config::Config(Device* device, libconfig::Setting& config) : auto& key = keys[i]; if(key.isNumber()) { _keys.push_back(key); - virtual_input->registerKey(key); + _device->virtualInput()->registerKey(key); } else if(key.getType() == libconfig::Setting::TypeString) { try { - _keys.push_back(virtual_input->toKeyCode(key)); - virtual_input->registerKey(virtual_input->toKeyCode(key)); + _keys.push_back( + _device->virtualInput()->toKeyCode(key)); + _device->virtualInput()->registerKey( + _device->virtualInput()->toKeyCode(key)); } catch(InputDevice::InvalidEventCode& e) { logPrintf(WARN, "Line %d: Invalid keycode %s, skipping." , key.getSourceLine(), key.c_str()); diff --git a/src/logid/actions/ToggleHiresScroll.cpp b/src/logid/actions/ToggleHiresScroll.cpp index 0c57d54..591e09b 100644 --- a/src/logid/actions/ToggleHiresScroll.cpp +++ b/src/logid/actions/ToggleHiresScroll.cpp @@ -38,7 +38,8 @@ void ToggleHiresScroll::press() _pressed = true; if(_hires_scroll) { - task::spawn([hires=this->_hires_scroll](){ + task::spawn(_device->workQueue(), + [hires=this->_hires_scroll](){ auto mode = hires->getMode(); mode ^= backend::hidpp20::HiresScroll::HiRes; hires->setMode(mode); diff --git a/src/logid/actions/ToggleSmartShift.cpp b/src/logid/actions/ToggleSmartShift.cpp index 5e4fd6e..58c5e36 100644 --- a/src/logid/actions/ToggleSmartShift.cpp +++ b/src/logid/actions/ToggleSmartShift.cpp @@ -37,7 +37,8 @@ void ToggleSmartShift::press() { _pressed = true; if(_smartshift) { - task::spawn([ss=this->_smartshift](){ + task::spawn(_device->workQueue(), + [ss=this->_smartshift](){ auto status = ss->getStatus(); status.setActive = true; status.active = !status.active; diff --git a/src/logid/actions/gesture/AxisGesture.cpp b/src/logid/actions/gesture/AxisGesture.cpp index 8ec26f5..2da114d 100644 --- a/src/logid/actions/gesture/AxisGesture.cpp +++ b/src/logid/actions/gesture/AxisGesture.cpp @@ -17,6 +17,7 @@ */ #include #include "AxisGesture.h" +#include "../../Device.h" #include "../../InputDevice.h" #include "../../util/log.h" @@ -69,19 +70,19 @@ void AxisGesture::move(int16_t axis) if(low_res_axis != -1) { int lowres_movement = 0, hires_movement = move_floor; - virtual_input->moveAxis(_config.axis(), hires_movement); + _device->virtualInput()->moveAxis(_config.axis(), hires_movement); hires_remainder += hires_movement; if(abs(hires_remainder) >= 60) { lowres_movement = hires_remainder/120; if(lowres_movement == 0) lowres_movement = hires_remainder > 0 ? 1 : -1; hires_remainder -= lowres_movement*120; - virtual_input->moveAxis(low_res_axis, lowres_movement); + _device->virtualInput()->moveAxis(low_res_axis, lowres_movement); } _hires_remainder = hires_remainder; } else { - virtual_input->moveAxis(_config.axis(), move_floor); + _device->virtualInput()->moveAxis(_config.axis(), move_floor); } } _axis = new_axis; @@ -104,11 +105,11 @@ AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) : auto& axis = setting.lookup("axis"); if(axis.isNumber()) { _axis = axis; - virtual_input->registerAxis(_axis); + _device->virtualInput()->registerAxis(_axis); } else if(axis.getType() == libconfig::Setting::TypeString) { try { - _axis = virtual_input->toAxisCode(axis); - virtual_input->registerAxis(_axis); + _axis = _device->virtualInput()->toAxisCode(axis); + _device->virtualInput()->registerAxis(_axis); } catch(InputDevice::InvalidEventCode& e) { logPrintf(WARN, "Line %d: Invalid axis %s, skipping." , axis.getSourceLine(), axis.c_str()); @@ -143,7 +144,7 @@ AxisGesture::Config::Config(Device *device, libconfig::Setting &setting) : int low_res_axis = InputDevice::getLowResAxis(_axis); if(low_res_axis != -1) { _multiplier *= 120; - virtual_input->registerAxis(low_res_axis); + _device->virtualInput()->registerAxis(low_res_axis); } } diff --git a/src/logid/backend/dj/Receiver.cpp b/src/logid/backend/dj/Receiver.cpp index 40cbbbd..2f3e4d7 100644 --- a/src/logid/backend/dj/Receiver.cpp +++ b/src/logid/backend/dj/Receiver.cpp @@ -44,8 +44,11 @@ InvalidReceiver::Reason InvalidReceiver::code() const noexcept return _reason; } -Receiver::Receiver(std::string path) : - _raw_device (std::make_shared(std::move(path))), +Receiver::Receiver(std::string path, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq) : + _raw_device (std::make_shared( + std::move(path), io_timeout, wq)), _hidpp10_device (_raw_device, hidpp::DefaultDevice) { if(!supportsDjReports(_raw_device->reportDescriptor())) diff --git a/src/logid/backend/dj/Receiver.h b/src/logid/backend/dj/Receiver.h index 767689a..f0e4a21 100644 --- a/src/logid/backend/dj/Receiver.h +++ b/src/logid/backend/dj/Receiver.h @@ -52,7 +52,9 @@ namespace dj class Receiver final { public: - explicit Receiver(std::string path); + Receiver(std::string path, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); enum DjEvents : uint8_t { diff --git a/src/logid/backend/dj/ReceiverMonitor.cpp b/src/logid/backend/dj/ReceiverMonitor.cpp index 80a9283..f847a75 100644 --- a/src/logid/backend/dj/ReceiverMonitor.cpp +++ b/src/logid/backend/dj/ReceiverMonitor.cpp @@ -25,8 +25,12 @@ using namespace logid::backend::dj; -ReceiverMonitor::ReceiverMonitor(std::string path) : _receiver ( - std::make_shared(std::move(path))) +ReceiverMonitor::ReceiverMonitor( + std::string path, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq) : + _workqueue (wq), + _receiver (std::make_shared(std::move(path), io_timeout, wq)) { assert(_receiver->hidppEventHandlers().find("RECVMON") == _receiver->hidppEventHandlers().end()); @@ -62,14 +66,15 @@ void ReceiverMonitor::run() /* Running in a new thread prevents deadlocks since the * receiver may be enumerating. */ - task::spawn({[this, report]() { + task::spawn(_workqueue, + [this, report]() { if (report.subId() == Receiver::DeviceConnection) this->addDevice(this->_receiver->deviceConnectionEvent (report)); else if (report.subId() == Receiver::DeviceDisconnection) this->removeDevice(this->_receiver-> deviceDisconnectionEvent(report)); - }}, {[report, path=this->_receiver->rawDevice()->hidrawPath()] + }, {[report, path=this->_receiver->rawDevice()->hidrawPath()] (std::exception& e) { if(report.subId() == Receiver::DeviceConnection) logPrintf(ERROR, "Failed to add device %d to receiver " @@ -117,7 +122,8 @@ void ReceiverMonitor::waitForDevice(hidpp::DeviceIndex index) event.index = index; event.fromTimeoutCheck = true; - task::spawn({[this, event, nickname]() { + task::spawn(_workqueue, + {[this, event, nickname]() { _receiver->rawDevice()->removeEventHandler(nickname); this->addDevice(event); }}, {[path=_receiver->rawDevice()->hidrawPath(), event] diff --git a/src/logid/backend/dj/ReceiverMonitor.h b/src/logid/backend/dj/ReceiverMonitor.h index 88d7686..6c88627 100644 --- a/src/logid/backend/dj/ReceiverMonitor.h +++ b/src/logid/backend/dj/ReceiverMonitor.h @@ -32,7 +32,9 @@ namespace dj class ReceiverMonitor { public: - explicit ReceiverMonitor(std::string path); + ReceiverMonitor(std::string path, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); virtual ~ReceiverMonitor(); void enumerate(); @@ -53,6 +55,7 @@ namespace dj std::shared_ptr receiver() const; private: + std::shared_ptr _workqueue; std::shared_ptr _receiver; }; diff --git a/src/logid/backend/hidpp/Device.cpp b/src/logid/backend/hidpp/Device.cpp index cc9db25..0b853c1 100644 --- a/src/logid/backend/hidpp/Device.cpp +++ b/src/logid/backend/hidpp/Device.cpp @@ -49,9 +49,11 @@ Device::InvalidDevice::Reason Device::InvalidDevice::code() const noexcept return _reason; } -Device::Device(const std::string& path, DeviceIndex index): - _raw_device (std::make_shared(path)), _receiver (nullptr), - _path (path), _index (index) +Device::Device(const std::string& path, DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq): + _raw_device (std::make_shared(path, io_timeout, wq)), + _receiver (nullptr), _path (path), _index (index) { _init(); } diff --git a/src/logid/backend/hidpp/Device.h b/src/logid/backend/hidpp/Device.h index 612318b..666ad45 100644 --- a/src/logid/backend/hidpp/Device.h +++ b/src/logid/backend/hidpp/Device.h @@ -61,7 +61,9 @@ namespace hidpp Reason _reason; }; - explicit Device(const std::string& path, DeviceIndex index); + Device(const std::string& path, DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); Device(std::shared_ptr raw_device, DeviceIndex index); Device(std::shared_ptr receiver, diff --git a/src/logid/backend/hidpp10/Device.cpp b/src/logid/backend/hidpp10/Device.cpp index c56e407..ab5f990 100644 --- a/src/logid/backend/hidpp10/Device.cpp +++ b/src/logid/backend/hidpp10/Device.cpp @@ -24,8 +24,10 @@ using namespace logid::backend; using namespace logid::backend::hidpp10; -Device::Device(const std::string &path, hidpp::DeviceIndex index) : - hidpp::Device(path, index) +Device::Device(const std::string &path, hidpp::DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq) : + hidpp::Device(path, index, io_timeout, wq) { assert(version() == std::make_tuple(1, 0)); } diff --git a/src/logid/backend/hidpp10/Device.h b/src/logid/backend/hidpp10/Device.h index a86d0e5..b6d92b5 100644 --- a/src/logid/backend/hidpp10/Device.h +++ b/src/logid/backend/hidpp10/Device.h @@ -28,7 +28,9 @@ namespace hidpp10 class Device : public hidpp::Device { public: - Device(const std::string& path, hidpp::DeviceIndex index); + Device(const std::string& path, hidpp::DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); Device(std::shared_ptr raw_dev, hidpp::DeviceIndex index); Device(std::shared_ptr receiver, diff --git a/src/logid/backend/hidpp20/Device.cpp b/src/logid/backend/hidpp20/Device.cpp index d32bf41..278f119 100644 --- a/src/logid/backend/hidpp20/Device.cpp +++ b/src/logid/backend/hidpp20/Device.cpp @@ -23,13 +23,16 @@ using namespace logid::backend::hidpp20; -Device::Device(std::string path, hidpp::DeviceIndex index) - : hidpp::Device(path, index) +Device::Device(std::string path, hidpp::DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq) : + hidpp::Device(path, index, io_timeout, wq) { assert(std::get<0>(version()) >= 2); } -Device::Device(std::shared_ptr raw_device, hidpp::DeviceIndex index) +Device::Device(std::shared_ptr raw_device, + hidpp::DeviceIndex index) : hidpp::Device(raw_device, index) { assert(std::get<0>(version()) >= 2); diff --git a/src/logid/backend/hidpp20/Device.h b/src/logid/backend/hidpp20/Device.h index 2628016..f593758 100644 --- a/src/logid/backend/hidpp20/Device.h +++ b/src/logid/backend/hidpp20/Device.h @@ -28,7 +28,9 @@ namespace hidpp20 { class Device : public hidpp::Device { public: - Device(std::string path, hidpp::DeviceIndex index); + Device(std::string path, hidpp::DeviceIndex index, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); Device(std::shared_ptr raw_device, hidpp::DeviceIndex index); Device(std::shared_ptr receiver, hidpp::DeviceIndex index); diff --git a/src/logid/backend/raw/DeviceMonitor.cpp b/src/logid/backend/raw/DeviceMonitor.cpp index f98ed48..8520c23 100644 --- a/src/logid/backend/raw/DeviceMonitor.cpp +++ b/src/logid/backend/raw/DeviceMonitor.cpp @@ -18,6 +18,7 @@ #include "DeviceMonitor.h" #include "../../util/task.h" +#include "../../util/workqueue.h" #include "../../util/log.h" #include "RawDevice.h" #include "../hidpp/Device.h" @@ -31,9 +32,11 @@ extern "C" #include } +using namespace logid; using namespace logid::backend::raw; -DeviceMonitor::DeviceMonitor() +DeviceMonitor::DeviceMonitor(int worker_count) : + _workqueue (std::make_shared(worker_count)) { if(-1 == pipe(_pipe)) throw std::system_error(errno, std::system_category(), @@ -100,7 +103,8 @@ void DeviceMonitor::run() std::string devnode = udev_device_get_devnode(device); if (action == "add") - task::spawn([this, name=devnode]() { + task::spawn(_workqueue, + [this, name=devnode]() { // Wait for device to initialise std::this_thread::sleep_for(std::chrono::milliseconds(100)); auto supported_reports = backend::hidpp::getSupportedReports( @@ -115,7 +119,8 @@ void DeviceMonitor::run() name.c_str(), e.what()); }); else if (action == "remove") - task::spawn([this, name=devnode]() { + task::spawn(_workqueue, + [this, name=devnode]() { this->removeDevice(name); }, [name=devnode](std::exception& e){ logPrintf(WARN, "Error removing device %s: %s", @@ -167,7 +172,8 @@ void DeviceMonitor::enumerate() std::string devnode = udev_device_get_devnode(device); udev_device_unref(device); - task::spawn([this, name=devnode]() { + task::spawn(_workqueue, + [this, name=devnode]() { auto supported_reports = backend::hidpp::getSupportedReports( RawDevice::getReportDescriptor(name)); if(supported_reports) @@ -182,4 +188,8 @@ void DeviceMonitor::enumerate() } udev_enumerate_unref(udev_enum); -} \ No newline at end of file +} + +std::shared_ptr DeviceMonitor::workQueue() const { + return _workqueue; +} diff --git a/src/logid/backend/raw/DeviceMonitor.h b/src/logid/backend/raw/DeviceMonitor.h index d795019..c54cb64 100644 --- a/src/logid/backend/raw/DeviceMonitor.h +++ b/src/logid/backend/raw/DeviceMonitor.h @@ -22,13 +22,12 @@ #include #include #include +#include -extern "C" -{ -#include -} +struct udev; namespace logid { + class workqueue; namespace backend { namespace raw { @@ -38,8 +37,10 @@ namespace raw void enumerate(); void run(); void stop(); + + std::shared_ptr workQueue() const; protected: - DeviceMonitor(); + explicit DeviceMonitor(int worker_count); virtual ~DeviceMonitor(); virtual void addDevice(std::string device) = 0; virtual void removeDevice(std::string device) = 0; @@ -48,6 +49,7 @@ namespace raw int _pipe[2]; std::atomic _run_monitor; std::mutex _running; + std::shared_ptr _workqueue; }; }}} diff --git a/src/logid/backend/raw/RawDevice.cpp b/src/logid/backend/raw/RawDevice.cpp index 0493862..95e6995 100644 --- a/src/logid/backend/raw/RawDevice.cpp +++ b/src/logid/backend/raw/RawDevice.cpp @@ -64,8 +64,13 @@ bool RawDevice::supportedReport(uint8_t id, uint8_t length) } } -RawDevice::RawDevice(std::string path) : _path (std::move(path)), - _continue_listen (false), _continue_respond (false) +RawDevice::RawDevice(std::string path, + const milliseconds& io_timeout, + const std::shared_ptr& wq) : + _path (std::move(path)), + _continue_listen (false), _continue_respond (false), + _io_timeout (io_timeout), + _workqueue (wq) { int ret; @@ -189,7 +194,7 @@ std::vector RawDevice::sendReport(const std::vector& report) _io_queue.push(task); interruptRead(false); // Alert listener to prioritise cv.wait(lock, [&top_of_queue]{ return top_of_queue; }); - auto status = f.wait_for(global_config->ioTimeout()); + auto status = f.wait_for(_io_timeout); if(status == std::future_status::timeout) { _continue_respond = false; interruptRead(); @@ -210,9 +215,9 @@ std::vector RawDevice::sendReport(const std::vector& report) _exception = std::make_exception_ptr(e); } }); - global_workqueue->queue(t); + _workqueue->queue(t); t->waitStart(); - auto status = t->waitFor(global_config->ioTimeout()); + auto status = t->waitFor(_io_timeout); if(_exception) std::rethrow_exception(_exception); if(status == std::future_status::timeout) { @@ -257,7 +262,7 @@ std::vector RawDevice::_respondToReport while(_continue_respond) { std::vector response; auto current_point = std::chrono::steady_clock::now(); - auto timeout = global_config->ioTimeout() - std::chrono::duration_cast + auto timeout = _io_timeout - std::chrono::duration_cast (current_point - start_point); if(timeout.count() <= 0) throw TimeoutError(); @@ -337,7 +342,7 @@ int RawDevice::_sendReport(const std::vector& report) int RawDevice::_readReport(std::vector &report, std::size_t maxDataLength) { - return _readReport(report, maxDataLength, global_config->ioTimeout()); + return _readReport(report, maxDataLength, _io_timeout); } int RawDevice::_readReport(std::vector &report, @@ -348,10 +353,10 @@ int RawDevice::_readReport(std::vector &report, report.resize(maxDataLength); timeval timeout_tv{}; - timeout_tv.tv_sec = duration_cast(global_config->ioTimeout()) + timeout_tv.tv_sec = duration_cast(_io_timeout) .count(); timeout_tv.tv_usec = duration_cast( - global_config->ioTimeout()).count() % + _io_timeout).count() % duration_cast(seconds(1)).count(); auto timeout_ms = duration_cast(timeout).count(); diff --git a/src/logid/backend/raw/RawDevice.h b/src/logid/backend/raw/RawDevice.h index 9ec935a..7935a0c 100644 --- a/src/logid/backend/raw/RawDevice.h +++ b/src/logid/backend/raw/RawDevice.h @@ -31,6 +31,8 @@ #include "../../util/mutex_queue.h" namespace logid { + class workqueue; + namespace backend { namespace raw { @@ -39,7 +41,9 @@ namespace raw public: static bool supportedReport(uint8_t id, uint8_t length); - explicit RawDevice(std::string path); + explicit RawDevice(std::string path, + const std::chrono::milliseconds& io_timeout, + const std::shared_ptr& wq); ~RawDevice(); std::string hidrawPath() const; @@ -80,6 +84,9 @@ namespace raw std::atomic _continue_respond; std::condition_variable _listen_condition; + const std::chrono::milliseconds _io_timeout; + const std::shared_ptr _workqueue; + std::map> _event_handlers; std::mutex _event_handler_lock; diff --git a/src/logid/features/DeviceStatus.cpp b/src/logid/features/DeviceStatus.cpp index 7ff8a01..b41a7a2 100644 --- a/src/logid/features/DeviceStatus.cpp +++ b/src/logid/features/DeviceStatus.cpp @@ -62,7 +62,7 @@ void DeviceStatus::listen() auto event = hidpp20::WirelessDeviceStatus::statusBroadcastEvent( report); if(event.reconfNeeded) - task::spawn([dev](){ dev->wakeup(); }); + task::spawn(dev->workQueue(), [dev](){ dev->wakeup(); }); }; _device->hidpp20().addEventHandler(EVENTHANDLER_NAME, handler); diff --git a/src/logid/logid.cpp b/src/logid/logid.cpp index ddb77ec..0352b1f 100644 --- a/src/logid/logid.cpp +++ b/src/logid/logid.cpp @@ -23,7 +23,6 @@ #include "util/log.h" #include "DeviceManager.h" -#include "logid.h" #include "InputDevice.h" #include "util/workqueue.h" @@ -43,13 +42,6 @@ struct CmdlineOptions }; LogLevel logid::global_loglevel = INFO; -std::shared_ptr logid::global_config; -std::unique_ptr logid::device_manager; -std::unique_ptr logid::virtual_input; -std::shared_ptr logid::global_workqueue; - -bool logid::kill_logid = false; -std::mutex logid::device_manager_reload; enum class Option { @@ -162,16 +154,16 @@ int main(int argc, char** argv) { CmdlineOptions options{}; readCliOptions(argc, argv, options); + std::shared_ptr config; + std::shared_ptr virtual_input; // Read config try { - global_config = std::make_shared(options.config_file); + config = std::make_shared(options.config_file); } catch (std::exception &e) { - global_config = std::make_shared(); + config = std::make_shared(); } - global_workqueue = std::make_shared( - global_config->workerCount()); //Create a virtual input device try { @@ -182,13 +174,9 @@ int main(int argc, char** argv) } // Scan devices, create listeners, handlers, etc. - device_manager = std::make_unique(); + auto device_manager = DeviceManager::make(config, virtual_input); - while(!kill_logid) { - device_manager_reload.lock(); - device_manager_reload.unlock(); - device_manager->run(); - } + device_manager->run(); return EXIT_SUCCESS; } diff --git a/src/logid/logid.h b/src/logid/logid.h deleted file mode 100644 index 850721f..0000000 --- a/src/logid/logid.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019-2020 PixlOne - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#ifndef LOGID_LOGID_H -#define LOGID_LOGID_H - -#include - -namespace logid -{ - // void reload(); - - extern bool kill_logid; - extern std::mutex device_manager_reload; -} - -#endif //LOGID_LOGID_H \ No newline at end of file diff --git a/src/logid/util/log.h b/src/logid/util/log.h index fad0b66..920ee71 100644 --- a/src/logid/util/log.h +++ b/src/logid/util/log.h @@ -22,6 +22,8 @@ namespace logid { + /// TODO: Replace with a safer object-oriented logger + enum LogLevel { RAWREPORT, diff --git a/src/logid/util/task.cpp b/src/logid/util/task.cpp index 29a4987..7a680d7 100644 --- a/src/logid/util/task.cpp +++ b/src/logid/util/task.cpp @@ -72,9 +72,10 @@ std::future_status task::waitFor(std::chrono::milliseconds ms) return _future.wait_for(ms); } -void task::spawn(const std::function& function, - const std::function& exception_handler) +void task::spawn(std::shared_ptr wq, + const std::function& function, + const std::function& exception_handler) { auto t = std::make_shared(function, exception_handler); - global_workqueue->queue(t); + wq->queue(t); } \ No newline at end of file diff --git a/src/logid/util/task.h b/src/logid/util/task.h index c988cc9..728504d 100644 --- a/src/logid/util/task.h +++ b/src/logid/util/task.h @@ -25,6 +25,8 @@ namespace logid { + class workqueue; + class task { public: @@ -50,7 +52,8 @@ namespace logid /* This function spawns a new task into the least used worker queue * and forgets about it. */ - static void spawn(const std::function& function, + static void spawn(std::shared_ptr wq, + const std::function& function, const std::function& exception_handler={[](std::exception& e) {ExceptionHandler::Default(e);}}); diff --git a/src/logid/util/workqueue.h b/src/logid/util/workqueue.h index 301b60b..b8191fd 100644 --- a/src/logid/util/workqueue.h +++ b/src/logid/util/workqueue.h @@ -52,7 +52,6 @@ namespace logid std::size_t _worker_count; }; - extern std::shared_ptr global_workqueue; } #endif //LOGID_WORKQUEUE_H