diff --git a/logid.example.cfg b/logid.example.cfg index 1ecf303..391281a 100644 --- a/logid.example.cfg +++ b/logid.example.cfg @@ -6,7 +6,12 @@ devices: ( on: true; threshold: 30; }; - hiresscroll: true; + hiresscroll: + { + hires: true; + invert: false; + target: false; + }; dpi: 1000; buttons: ( diff --git a/src/logid/Actions.cpp b/src/logid/Actions.cpp index e031df1..cb3485a 100644 --- a/src/logid/Actions.cpp +++ b/src/logid/Actions.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include "Actions.h" #include "util.h" @@ -55,48 +57,26 @@ void GestureAction::release() void SmartshiftAction::press() { - if(device->features.find(0x2110) == device->features.end()) - { - log_printf(DEBUG, "Error toggling smart shift, feature is non-existent."); - return; - } - const uint8_t f_index = device->features.find(0x2110)->second; - std::vector results; - try { - results = device->hidpp_dev->callFunction(f_index, 0x00); - if(results[0] == 0x02) - results = device->hidpp_dev->callFunction(f_index, 0x01, {0x01}); - else if(results[0] == 0x01) - results = device->hidpp_dev->callFunction(f_index, 0x01, {0x02}); - else - results = device->hidpp_dev->callFunction(f_index, 0x01, {0x01}); + HIDPP20::ISmartShift iss(device->hidpp_dev); + auto s = iss.getStatus(); + iss.setStatus({new bool(!*s.Active)}); } catch(HIDPP20::Error &e) { log_printf(ERROR, "Error toggling smart shift, code %d: %s\n", e.errorCode(), e.what()); - return; } } void HiresScrollAction::press() { - if(device->features.find(0x2110) == device->features.end()) - { - log_printf(DEBUG, "Error toggling hires scroll, feature is non-existent."); - return; - } - const uint8_t f_index = device->features.find(0x2121)->second; - std::vector results; - try { - results = device->hidpp_dev->callFunction(f_index, 0x01); - if(results[0] == 0x02) - results = device->hidpp_dev->callFunction(f_index, 0x02, {0x00}); - else - results = device->hidpp_dev->callFunction(f_index, 0x02, {0x02}); + HIDPP20::IHiresScroll ihs(device->hidpp_dev); + auto mode = ihs.getMode(); + mode ^= HIDPP20::IHiresScroll::Mode::HiRes; + ihs.setMode(mode); } catch(HIDPP20::Error &e) { diff --git a/src/logid/Actions.h b/src/logid/Actions.h index b572ba3..2eee633 100644 --- a/src/logid/Actions.h +++ b/src/logid/Actions.h @@ -1,9 +1,10 @@ -#ifndef LOGIOPS_ACTIONS_H -#define LOGIOPS_ACTIONS_H +#ifndef ACTIONS_H +#define ACTIONS_H +#include "Device.h" #include +#include #include -#include "Device.h" enum class Action { @@ -119,4 +120,4 @@ private: int dpi_inc; }; -#endif //LOGIOPS_ACTIONS_H +#endif //ACTIONS_H \ No newline at end of file diff --git a/src/logid/Configuration.cpp b/src/logid/Configuration.cpp index e7e8900..1be9463 100644 --- a/src/logid/Configuration.cpp +++ b/src/logid/Configuration.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Configuration.h" #include "util.h" @@ -79,10 +80,48 @@ DeviceConfig::DeviceConfig(const libconfig::Setting &root) try { - bool b; - if(!root.lookupValue("hiresscroll", b)) - throw SettingTypeException(root["hiresscroll"]); - hiresscroll = new bool(b); + const Setting& hr = root["hiresscroll"]; + uint8_t hss = 0; + try + { + bool b; + if(!hr.lookupValue("hires", b)) + throw SettingTypeException(root["hires"]); + if(b) hss |= HIDPP20::IHiresScroll::HiRes; + } + catch(SettingNotFoundException &e) { } + catch(SettingTypeException &e) + { + log_printf(INFO, "Line %d: hires field must be a boolean", hr["hires"].getSourceLine()); + } + + try + { + bool b; + if(!hr.lookupValue("invert", b)) + throw SettingTypeException(root["invert"]); + if(b) hss |= HIDPP20::IHiresScroll::Inverted; + } + catch(SettingNotFoundException &e) { } + catch(SettingTypeException &e) + { + log_printf(INFO, "Line %d: invert field must be a boolean", hr["invert"].getSourceLine()); + } + + try + { + bool b; + if(!hr.lookupValue("target", b)) + throw SettingTypeException(root["target"]); + if(b) hss |= HIDPP20::IHiresScroll::Target; + } + catch(SettingNotFoundException &e) { } + catch(SettingTypeException &e) + { + log_printf(INFO, "Line %d: target field must be a boolean", hr["target"].getSourceLine()); + } + + hiresscroll = new uint8_t(hss); } catch(const SettingNotFoundException &e) { @@ -90,18 +129,18 @@ DeviceConfig::DeviceConfig(const libconfig::Setting &root) } catch(const SettingTypeException &e) { - log_printf(WARN, "Line %d: DPI must me an integer; not setting.", root["hiresscroll"].getSourceLine()); + log_printf(WARN, "Line %d: hiresscroll should be an object", root["hiresscroll"].getSourceLine()); } try { const Setting& ss = root["smartshift"]; - smartshift = new smartshift_options; + smartshift = new HIDPP20::ISmartShift::SmartshiftStatus {}; bool on; int threshold; try { - if (ss.lookupValue("on", on)) smartshift->on = new bool(on); + if (ss.lookupValue("on", on)) smartshift->Active = new bool(on); else log_printf(WARN, "Line %d: on field must be a boolean", ss["on"].getSourceLine()); } catch(const SettingNotFoundException &e) { } @@ -113,26 +152,24 @@ DeviceConfig::DeviceConfig(const libconfig::Setting &root) if(threshold < 0) { threshold = 1; - log_printf(INFO, "Smartshift threshold must be > 0 or < 100, setting to 0."); + log_printf(INFO, "Smartshift threshold must be > 0 or < 100, setting to 1."); } if(threshold >= 100) { threshold = 99; log_printf(INFO, "Smartshift threshold must be > 0 or < 100, setting to 99."); } - smartshift->threshold = new uint8_t(threshold); + smartshift->AutoDisengage = new uint8_t(threshold); + smartshift->DefaultAutoDisengage = new uint8_t(threshold); } else log_printf(WARN, "Line %d: threshold must be an integer", ss["threshold"].getSourceLine()); } - catch(const SettingNotFoundException &e) - { - log_printf(INFO, "Missing threshold for smartshift, not setting."); - } + catch(const SettingNotFoundException &e) { } } catch(const SettingNotFoundException &e) { } catch(const SettingTypeException &e) { - log_printf(WARN, "Line %d: smartshift field must be an object", root["hiressscroll"].getSourceLine()); + log_printf(WARN, "Line %d: smartshift field must be an object", root["smartshift"].getSourceLine()); } Setting* buttons; diff --git a/src/logid/Configuration.h b/src/logid/Configuration.h index 5e1adc4..ac1eea9 100644 --- a/src/logid/Configuration.h +++ b/src/logid/Configuration.h @@ -1,14 +1,10 @@ -#ifndef MASTEROPTIONS_CONFIGURATION_H -#define MASTEROPTIONS_CONFIGURATION_H +#ifndef CONFIGURATION_H +#define CONFIGURATION_H #include #include - -struct smartshift_options -{ - bool* on = nullptr; - uint8_t* threshold = nullptr; -}; +#include +#include "Actions.h" class DeviceConfig; class ButtonAction; @@ -20,8 +16,8 @@ public: DeviceConfig(); DeviceConfig(const libconfig::Setting& root); const int* dpi = nullptr; - struct smartshift_options* smartshift = nullptr; - const bool* hiresscroll = nullptr; + HIDPP20::ISmartShift::SmartshiftStatus* smartshift; + const uint8_t* hiresscroll = nullptr; std::map actions; }; @@ -38,4 +34,4 @@ ButtonAction* parse_action(Action action, const libconfig::Setting* action_confi extern Configuration* global_config; -#endif //MASTEROPTIONS_CONFIGURATION_H +#endif //CONFIGURATION_H \ No newline at end of file diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index 4e62fe8..82a9ac2 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -6,21 +6,23 @@ #include #include #include +#include #include #include #include #include +#include #include +#include #include "Device.h" -#include "Actions.h" -#include "Configuration.h" #include "util.h" #include "EvdevDevice.h" + using namespace std::chrono_literals; -Device::Device(std::string p, const HIDPP::DeviceIndex i) : path(p), index (i) +Device::Device(std::string p, const HIDPP::DeviceIndex i) : path(std::move(p)), index (i) { // Initialise variables DeviceRemoved = false; @@ -74,39 +76,42 @@ void Device::divert_buttons(bool scanning) } catch(HIDPP20::UnsupportedFeature &e) { - log_printf(DEBUG, "%s does not support Reprog controls, not diverting!", name); + log_printf(DEBUG, "%s does not support Reprog controls, not diverting!", name.c_str()); } } -void Device::set_smartshift(smartshift_options ops, bool scanning) +void Device::set_smartshift(HIDPP20::ISmartShift::SmartshiftStatus ops, bool scanning) { - std::vector parameters; - parameters.push_back(ops.on == nullptr ? 0 : (*ops.on)? 2 : 1); - if(ops.threshold != nullptr) + try { - parameters.push_back(*ops.threshold); - parameters.push_back(*ops.threshold); + HIDPP20::ISmartShift ss(hidpp_dev); + ss.setStatus(ops); } - - if(features.find(0x2110) == features.end()) + catch (HIDPP20::UnsupportedFeature &e) { - log_printf(DEBUG, "Error toggling smart shift, feature is non-existent."); - return; + log_printf(ERROR, "Device does not support SmartShift"); } - const uint8_t f_index = features.find(0x2110)->second; - - try { hidpp_dev->callFunction(f_index, 0x01, parameters); } catch (HIDPP20::Error &e) { - if(scanning) - throw e; - log_printf(ERROR, "Error setting smartshift options, code %d: %s\n", e.errorCode(), e.what()); + log_printf(ERROR, "Error setting SmartShift options, code %d: %s\n", e.errorCode(), e.what()); } } -void Device::set_hiresscroll(bool b, bool scanning) +void Device::set_hiresscroll(uint8_t ops, bool scanning) { - + try + { + HIDPP20::IHiresScroll hs(hidpp_dev); + hs.setMode(ops); + } + catch (HIDPP20::UnsupportedFeature &e) + { + log_printf(ERROR, "Device does not support Hires Scrolling"); + } + catch (HIDPP20::Error &e) + { + log_printf(ERROR, "Error setting Hires Scrolling options, code %d: %s\n", e.errorCode(), e.what()); + } } void Device::set_dpi(int dpi, bool scanning) @@ -128,49 +133,11 @@ void Device::start() auto *d = new HIDPP::SimpleDispatcher(path.c_str()); listener = new SimpleListener(d, index); listener->addEventHandler( std::make_unique(hidpp_dev, this) ); - auto listener_thread = std::thread { [=]() { listener->start(); } }; - listener_thread.detach(); - while(!DeviceRemoved) - { - std::mutex m; - std::condition_variable cv; - std::vector results; - - std::thread t([&cv, &results, dev=hidpp_dev, removed=&DeviceRemoved]() - { - try { results = dev->callFunction(0x00, 0x00); } - catch(HIDPP10::Error &e) { usleep(500000); } - catch(std::system_error &e) - { - cv.notify_one(); - if(*removed) printf("REMOVED!\n"); - *removed = true; - } - cv.notify_one(); - }); - t.detach(); - - std::unique_lock l(m); - if(cv.wait_for(l, 500ms) == std::cv_status::timeout) - { - while(!DeviceRemoved) - { - try - { - configure(true); - break; - } - catch(std::exception &e) {} // Retry infinitely on failure - } - } - usleep(200000); - } - - listener->stop(); - listener_thread.join(); + listener->addEventHandler( std::make_unique(this) ); + listener->start(); } -void Device::ButtonHandler::handleEvent (const HIDPP::Report &event) +void ButtonHandler::handleEvent (const HIDPP::Report &event) { switch (event.function()) { @@ -187,7 +154,7 @@ void Device::ButtonHandler::handleEvent (const HIDPP::Report &event) std::vector::iterator it; std::vector cids(states.size() + new_states.size()); it = std::set_union(states.begin(), states.end(), new_states.begin(), new_states.end(), cids.begin()); - cids.resize(it - cids.begin()); + cids.resize((ulong)(it - cids.begin())); for (uint16_t i : cids) { if (std::find(new_states.begin(), new_states.end(), i) != new_states.end()) @@ -208,10 +175,54 @@ void Device::ButtonHandler::handleEvent (const HIDPP::Report &event) std::thread{[=]() { dev->move_diverted(i, raw_xy); }}.detach(); break; } + default: + break; } } -void Device::EventListener::removeEventHandlers () +void ReceiverHandler::handleEvent(const HIDPP::Report &event) +{ + switch(event.featureIndex()) + { + case HIDPP10::IReceiver::DeviceUnpaired: + { + // Find device, stop it, and delete it + auto it = finder->devices.begin(); + while (it != finder->devices.end()) + { + if(it->first->path == dev->path && it->first->index == event.deviceIndex()) + { + log_printf(INFO, "%s (Device %d on %s) unpaired.", it->first->name.c_str(), event.deviceIndex(), dev->path); + it->first->stop(); + it->second.join(); + finder->devices.erase(it); + } + else it++; + } + break; + } + case HIDPP10::IReceiver::DevicePaired: + { + break; + } + case HIDPP10::IReceiver::ConnectionStatus: + { + auto status = HIDPP10::IReceiver::connectionStatusEvent(event); + if(status == HIDPP10::IReceiver::LinkLoss) + log_printf(INFO, "Link lost to device %d on %s", event.deviceIndex(), dev->path.c_str()); + else if (status == HIDPP10::IReceiver::ConnectionEstablished) + { + dev->configure(); + log_printf(INFO, "Connection established to device %d on %s", event.deviceIndex(), dev->path.c_str()); + } + break; + } + default: + break; + } +} + +void EventListener::removeEventHandlers () { for (const auto &p: iterators) dispatcher->unregisterEventHandler(p.second); @@ -219,35 +230,37 @@ void Device::EventListener::removeEventHandlers () iterators.clear(); } -Device::EventListener::~EventListener() +EventListener::~EventListener() { removeEventHandlers(); } -void Device::EventListener::addEventHandler(std::unique_ptr &&handler) +void EventListener::addEventHandler(std::unique_ptr &&handler) { - uint8_t feature = handler->feature()->index(); EventHandler *ptr = handler.get(); - handlers.emplace(feature, std::move(handler)); - dispatcher->registerEventHandler(index, feature, [ptr](const HIDPP::Report &report) + for(uint8_t feature : handler->featureIndices()) { - ptr->handleEvent(report); - return true; - }); + handlers.emplace(feature, std::move(handler)); + dispatcher->registerEventHandler(index, feature, [=](const HIDPP::Report &report) + { + ptr->handleEvent(report); + return true; + }); + } } -void Device::SimpleListener::start() +void SimpleListener::start() { try { dispatcher->listen(); } catch(std::system_error &e) { } } -void Device::SimpleListener::stop() +void SimpleListener::stop() { dispatcher->stop(); } -bool Device::SimpleListener::event (EventHandler *handler, const HIDPP::Report &report) +bool SimpleListener::event (EventHandler *handler, const HIDPP::Report &report) { handler->handleEvent (report); return true; @@ -255,7 +268,7 @@ bool Device::SimpleListener::event (EventHandler *handler, const HIDPP::Report & void Device::stop() { - DeviceRemoved = true; + listener->stop(); } void Device::press_button(uint16_t cid) @@ -296,11 +309,5 @@ std::map Device::get_features() std::map features; HIDPP20::IFeatureSet ifs (hidpp_dev); unsigned int feature_count = ifs.getCount(); - for(uint8_t i = 1; i <= feature_count; i++) - { - features.insert({ifs.getFeatureID(i), i}); - log_printf(DEBUG, "%s: 0x%02x : 0x%04x", name.c_str(), i, ifs.getFeatureID(i)); - } - return features; } \ No newline at end of file diff --git a/src/logid/Device.h b/src/logid/Device.h index aed7866..2400f2c 100644 --- a/src/logid/Device.h +++ b/src/logid/Device.h @@ -1,13 +1,18 @@ -#ifndef LOGIOPS_DEVICE_H -#define LOGIOPS_DEVICE_H +#ifndef DEVICE_H +#define DEVICE_H + +#include "Actions.h" +#include "DeviceFinder.h" +#include "Configuration.h" #include #include #include #include +#include -#include "Actions.h" -#include "Configuration.h" +class EventListener; +class DeviceConfig; class Device { @@ -29,80 +34,98 @@ public: std::map features; - std::string path; + const std::string path; const HIDPP::DeviceIndex index; HIDPP::Dispatcher* dispatcher; HIDPP20::Device* hidpp_dev; - class EventHandler - { - public: - virtual const HIDPP20::FeatureInterface *feature() const = 0; - virtual void handleEvent (const HIDPP::Report &event) = 0; - }; - class ButtonHandler : public EventHandler - { - public: - ButtonHandler (HIDPP20::Device *hidppdev, Device *d) : _irc (HIDPP20::IReprogControls::auto_version(hidppdev)), dev (d) { } - const HIDPP20::FeatureInterface *feature () const - { - return &_irc; - } - void handleEvent (const HIDPP::Report &event); - protected: - HIDPP20::IReprogControls _irc; - Device* dev; - std::vector states; - std::vector new_states; - }; - - class EventListener - { - HIDPP::Dispatcher *dispatcher; - HIDPP::DeviceIndex index; - std::map> handlers; - std::map iterators; - public: - EventListener (HIDPP::Dispatcher *dispatcher, HIDPP::DeviceIndex index): dispatcher (dispatcher), index (index) {} - - virtual void removeEventHandlers (); - virtual ~EventListener(); - virtual void addEventHandler (std::unique_ptr &&handler); - - virtual void start () = 0; - virtual void stop () = 0; - - protected: - virtual bool event (EventHandler* handler, const HIDPP::Report &report) = 0; - }; - class SimpleListener : public EventListener - { - HIDPP::SimpleDispatcher *dispatcher; - - public: - SimpleListener (HIDPP::SimpleDispatcher* dispatcher, HIDPP::DeviceIndex index): - EventListener (dispatcher, index), - dispatcher (dispatcher) - { - } - - virtual void start(); - virtual void stop(); - - protected: - virtual bool event (EventHandler* handler, const HIDPP::Report &report); - }; - protected: DeviceConfig* config; bool DeviceRemoved; EventListener* listener; void divert_buttons(bool scanning=false); - void set_smartshift(struct smartshift_options ops, bool scanning=false); - void set_hiresscroll(bool b, bool scanning=false); + void set_smartshift(HIDPP20::ISmartShift::SmartshiftStatus ops, bool scanning=false); + void set_hiresscroll(uint8_t flags, bool scanning=false); void set_dpi(int dpi, bool scanning=false); }; +class EventHandler +{ +public: + virtual const HIDPP20::FeatureInterface *feature() const = 0; + virtual const std::vector featureIndices() const + { + return {feature()->index()}; + }; + virtual void handleEvent (const HIDPP::Report &event) = 0; +}; +class ButtonHandler : public EventHandler +{ +public: + ButtonHandler (HIDPP20::Device *hidppdev, Device *d) : _irc (HIDPP20::IReprogControls::auto_version(hidppdev)), dev (d) { } + const HIDPP20::FeatureInterface *feature () const + { + return &_irc; + } + void handleEvent (const HIDPP::Report &event); +protected: + HIDPP20::IReprogControls _irc; + Device* dev; + std::vector states; + std::vector new_states; +}; +class ReceiverHandler : public EventHandler +{ +public: + ReceiverHandler (Device *d) : dev (d) { } + const HIDPP20::FeatureInterface *feature () const + { + } + virtual const std::vector featureIndices() const + { + return HIDPP10::IReceiver::Events; + } + void handleEvent (const HIDPP::Report &event); +protected: + Device* dev; +}; -#endif //LOGIOPS_DEVICE_H +class EventListener +{ + HIDPP::Dispatcher *dispatcher; + HIDPP::DeviceIndex index; + std::map> handlers; + std::map iterators; +public: + EventListener (HIDPP::Dispatcher *dispatcher, HIDPP::DeviceIndex index): dispatcher (dispatcher), index (index) {} + + virtual void removeEventHandlers (); + virtual ~EventListener(); + virtual void addEventHandler (std::unique_ptr &&handler); + + virtual void start () = 0; + virtual void stop () = 0; + +protected: + virtual bool event (EventHandler* handler, const HIDPP::Report &report) = 0; +}; +class SimpleListener : public EventListener +{ + HIDPP::SimpleDispatcher *dispatcher; + +public: + SimpleListener (HIDPP::SimpleDispatcher* dispatcher, HIDPP::DeviceIndex index): + EventListener (dispatcher, index), + dispatcher (dispatcher) + { + } + + virtual void start(); + virtual void stop(); + +protected: + virtual bool event (EventHandler* handler, const HIDPP::Report &report); +}; + +#endif //DEVICE_H \ No newline at end of file diff --git a/src/logid/DeviceFinder.cpp b/src/logid/DeviceFinder.cpp index 9bcc720..6047955 100644 --- a/src/logid/DeviceFinder.cpp +++ b/src/logid/DeviceFinder.cpp @@ -2,10 +2,11 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -13,16 +14,10 @@ #include "util.h" #include "Device.h" -void find_device() -{ - auto df = new DeviceFinder(); - df->run(); -} +constexpr uint16_t DeviceFinder::UnifyingReceivers[]; void DeviceFinder::addDevice(const char *path) { - const int max_tries = 5; - const int try_delay = 50000; std::string string_path(path); // Asynchronously scan device std::thread{[=]() @@ -50,6 +45,10 @@ void DeviceFinder::addDevice(const char *path) if(hidraw_info.find("HID_NAME") != hidraw_info.end()) if (hidraw_info.find("HID_NAME")->second.find("Logitech") == std::string::npos) return; + std::vector _devs; + const int max_tries = 5; + const int try_delay = 50000; + //Check if device is an HID++ device and handle it accordingly try { @@ -61,80 +60,84 @@ void DeviceFinder::addDevice(const char *path) HIDPP::WirelessDevice3, HIDPP::WirelessDevice4, HIDPP::WirelessDevice5, HIDPP::WirelessDevice6}) { - /// TODO: CONTINUOUSLY SCAN ALL DEVICES ON RECEIVER - //Skip wireless devices if default device (receiver) has failed - if(!has_receiver_index && index == HIDPP::WirelessDevice1) - break; - for(int i = 0; i < max_tries; i++) - { - try - { - HIDPP::Device d(&dispatcher, index); - auto version = d.protocolVersion(); - if(index == HIDPP::DefaultDevice && version == std::make_tuple(1, 0)) - has_receiver_index = true; - uint major, minor; - std::tie(major, minor) = d.protocolVersion(); - if(major > 1) // HID++ 2.0 devices only - { - auto dev = new Device(string_path, index); - handlers.insert({ - dev, std::async(std::launch::async, &Device::start, *dev) - }); - log_printf(INFO, "%s detected: device %d on %s", d.name().c_str(), index, string_path.c_str()); - } - break; - } - catch(HIDPP10::Error &e) - { - if(e.errorCode() != HIDPP10::Error::UnknownDevice) - { - if(i == max_tries - 1) - log_printf(WARN, "Error while querying %s, wireless device %d: %s", string_path.c_str(), index, e.what()); - else usleep(try_delay); - } - } - catch(HIDPP20::Error &e) - { - if(e.errorCode() != HIDPP20::Error::UnknownDevice) - { - if(i == max_tries - 1) - log_printf(WARN, "Error while querying %s, device %d: %s", string_path.c_str(), index, e.what()); - else usleep(try_delay); - } - } - catch(HIDPP::Dispatcher::TimeoutError &e) - { - if(i == max_tries - 1) - log_printf(WARN, "Device %s (index %d) timed out.", string_path.c_str(), index); - else usleep(try_delay); - } - catch(std::runtime_error &e) - { - if(i == max_tries - 1) - log_printf(WARN, "Runtime error on device %d on %s: %s", index, string_path.c_str(), e.what()); - else usleep(try_delay); - } - } + if(!has_receiver_index && index == HIDPP::WirelessDevice1) + break; + for(int i = 0; i < max_tries; i++) + { + try + { + HIDPP::Device d(&dispatcher, index); + auto version = d.protocolVersion(); + uint major, minor; + std::tie(major, minor) = version; + if(index == HIDPP::DefaultDevice && version == std::make_tuple(1, 0)) + has_receiver_index = true; + if(major > 1) // HID++ 2.0 devices only + { + auto dev = new Device(string_path, index); + _devs.push_back(dev); + log_printf(INFO, "%s detected: device %d on %s", d.name().c_str(), index, string_path.c_str()); + } + break; + } + catch(HIDPP10::Error &e) + { + if(e.errorCode() != HIDPP10::Error::UnknownDevice) + { + if(i == max_tries - 1) + log_printf(ERROR, "Error while querying %s, wireless device %d: %s", string_path.c_str(), index, e.what()); + else usleep(try_delay); + } + else break; + } + catch(HIDPP20::Error &e) + { + if(e.errorCode() != HIDPP20::Error::UnknownDevice) + { + if(i == max_tries - 1) + log_printf(ERROR, "Error while querying %s, device %d: %s", string_path.c_str(), index, e.what()); + else usleep(try_delay); + } + else break; + } + catch(HIDPP::Dispatcher::TimeoutError &e) + { + if(i == max_tries - 1) + log_printf(ERROR, "Device %s (index %d) timed out.", string_path.c_str(), index); + else usleep(try_delay); + } + catch(std::runtime_error &e) + { + if(i == max_tries - 1) + log_printf(ERROR, "Runtime error on device %d on %s: %s", index, string_path.c_str(), e.what()); + else usleep(try_delay); + } + } } } - catch(HIDPP::Dispatcher::NoHIDPPReportException &e) {} catch(std::system_error &e) { log_printf(WARN, "Failed to open %s: %s", string_path.c_str(), e.what()); } + + for(auto dev : _devs) + { + devices.insert({dev, std::thread{[dev]() { dev->start(); }}}); + devices[dev].detach(); + } + }}.detach(); } void DeviceFinder::removeDevice(const char* path) { // Iterate through Devices, stop all in path - auto it = handlers.begin(); - while (it != handlers.end()) + auto it = devices.begin(); + while (it != devices.end()) { if(it->first->path == path) { log_printf(INFO, "%s on %s disconnected.", it->first->name.c_str(), path); it->first->stop(); - it->second.wait(); - //handlers.erase(it); + it->second.join(); + devices.erase(it); it++; } else diff --git a/src/logid/DeviceFinder.h b/src/logid/DeviceFinder.h index f5cd478..a075479 100644 --- a/src/logid/DeviceFinder.h +++ b/src/logid/DeviceFinder.h @@ -1,18 +1,39 @@ -#ifndef MASTEROPTIONS_DEVICEFINDER_H -#define MASTEROPTIONS_DEVICEFINDER_H +#ifndef DEVICEFINDER_H +#define DEVICEFINDER_H +#include +#include +#include +#include +#include +#include +#include #include "Device.h" -struct handler_pair; +class Device; class DeviceFinder : public HID::DeviceMonitor { +public: + std::map devices; + static constexpr uint16_t UnifyingReceivers[] = + { + 0xc52b, 0xc532, // Official Unifying receivers + 0xc52f, 0xc526, // Nano receivers + 0xc52e, 0xc51b, + 0xc531, 0xc517, + 0xc518, 0xc51a, + 0xc521, 0xc525, + 0xc534, + 0xc539, 0xc53a, // Lightspeed receivers + 0xc53f, + 0x17ef, // Lenovo nano receivers + }; protected: void addDevice(const char* path); void removeDevice(const char* path); - std::map> handlers; }; -void find_device(); +extern DeviceFinder* finder; -#endif //MASTEROPTIONS_DEVICEFINDER_H +#endif //DEVICEFINDER_H \ No newline at end of file diff --git a/src/logid/EvdevDevice.h b/src/logid/EvdevDevice.h index 57ded21..36e3a57 100644 --- a/src/logid/EvdevDevice.h +++ b/src/logid/EvdevDevice.h @@ -1,5 +1,5 @@ -#ifndef MASTEROPTIONS_EVDEVDEVICE_H -#define MASTEROPTIONS_EVDEVDEVICE_H +#ifndef EVDEVDEVICE_H +#define EVDEVDEVICE_H #include #include @@ -16,4 +16,4 @@ public: extern EvdevDevice* global_evdev; -#endif //MASTEROPTIONS_EVDEVDEVICE_H +#endif //EVDEVDEVICE_H \ No newline at end of file diff --git a/src/logid/logid.cpp b/src/logid/logid.cpp index 93dde33..541e617 100644 --- a/src/logid/logid.cpp +++ b/src/logid/logid.cpp @@ -21,6 +21,7 @@ LogLevel global_verbosity = DEBUG; Configuration* global_config; EvdevDevice* global_evdev; +DeviceFinder* finder; int main(int argc, char** argv) { @@ -36,7 +37,9 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - find_device(); // Scan devices, create listeners, handlers, etc. + // Scan devices, create listeners, handlers, etc. + finder = new DeviceFinder(); + finder->run(); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/logid/util.cpp b/src/logid/util.cpp index 88876d0..e5feab0 100644 --- a/src/logid/util.cpp +++ b/src/logid/util.cpp @@ -6,7 +6,6 @@ #include #include "util.h" -#include "Actions.h" void log_printf(LogLevel level, const char* format, ...) { diff --git a/src/logid/util.h b/src/logid/util.h index be6e491..cbf95cf 100644 --- a/src/logid/util.h +++ b/src/logid/util.h @@ -1,5 +1,5 @@ -#ifndef MASTEROPTIONS_LOGGER_H -#define MASTEROPTIONS_LOGGER_H +#ifndef UTIL_H +#define UTIL_H #include "Actions.h" @@ -22,4 +22,4 @@ Direction string_to_direction(std::string s); GestureMode string_to_gesturemode(std::string s); Action string_to_action(std::string s); -#endif //MASTEROPTIONS_LOGGER_H +#endif //UTIL_H \ No newline at end of file