From 7f1af8191010fdc50e6fa53b3d0159e233f271ca Mon Sep 17 00:00:00 2001 From: pixl Date: Fri, 19 Jun 2020 21:58:33 -0400 Subject: [PATCH] Rewrite logid::DeviceMonitor --- src/logid/CMakeLists.txt | 2 + src/logid/Device.cpp | 547 +---------------------- src/logid/Device.h | 172 +------ src/logid/DeviceMonitor.cpp | 199 +++------ src/logid/DeviceMonitor.h | 27 +- src/logid/Receiver.cpp | 9 + src/logid/Receiver.h | 17 + src/logid/backend/dj/ReceiverMonitor.cpp | 0 src/logid/backend/dj/ReceiverMonitor.h | 6 + src/logid/backend/hidpp20/Device.cpp | 12 + src/logid/backend/hidpp20/Device.h | 3 + src/logid/util.h | 2 +- 12 files changed, 129 insertions(+), 867 deletions(-) create mode 100644 src/logid/Receiver.cpp create mode 100644 src/logid/Receiver.h create mode 100644 src/logid/backend/dj/ReceiverMonitor.cpp create mode 100644 src/logid/backend/dj/ReceiverMonitor.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index 4ce4d1f..4aed930 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -12,6 +12,8 @@ add_executable(logid logid.cpp util.cpp DeviceMonitor.cpp + Device.cpp + Receiver.cpp backend/Error.cpp backend/raw/DeviceMonitor.cpp backend/raw/RawDevice.cpp diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index 215a833..a5689eb 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -1,551 +1,20 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Device.h" #include "util.h" -#include "EvdevDevice.h" +#include "Device.h" using namespace logid; -using namespace std::chrono_literals; - -Device::Device(std::string p, const HIDPP::DeviceIndex i) : path(std::move(p)), index (i) +Device::Device(std::string path, backend::hidpp::DeviceIndex index) : + _hidpp20 (path, index), _path (path), _index (index) { - disconnected = true; - dispatcher = new HIDPP::SimpleDispatcher(path.c_str()); - listener = new SimpleListener(new HIDPP::SimpleDispatcher(path.c_str()), index); - config = new DeviceConfig(); + log_printf(DEBUG, "logid::Device created on %s:%d"); } -bool Device::init() +void Device::sleep() { - // Initialise variables - disconnected = false; - try - { - hidpp_dev = new HIDPP20::Device(dispatcher, index); - } - catch(HIDPP10::Error &e) { return false; } - catch(HIDPP20::Error &e) { return false; } - - name = hidpp_dev->name(); - - if(std::find(global_config->blacklist.begin(), global_config->blacklist.end(), - hidpp_dev->productID()) != global_config->blacklist.end()) - { - log_printf(INFO, "Ignored blacklisted device %s", name.c_str()); - throw BlacklistedDevice(); - } - - features = getFeatures(); - // Set config, if none is found for this device then use default - if(global_config->devices.find(name) == global_config->devices.end()) - log_printf(INFO, "Device %s not configured, using default config.", hidpp_dev->name().c_str()); - else - { - delete(config); - config = global_config->devices.find(name)->second; - } - - initialized = true; - - return true; + log_printf(INFO, "%s:%d fell asleep.", _path.c_str(), _index); } -Device::~Device() +void Device::wakeup() { - if(!disconnected) - this->reset(); - if(!config->baseConfig) - delete(this->config); -} - -void Device::configure() -{ - if(config->baseConfig) - config = new DeviceConfig(config, this); - - if(!configuring.try_lock()) - { - log_printf(DEBUG, "%s %d: skip config task", path.c_str(), index); - return; - } - usleep(500000); - - try - { - if(disconnected) - goto ret; - // Divert buttons - divert_buttons(); - - if(disconnected) - goto ret; - // Set DPI if it is configured - if(config->dpi != nullptr) - setDPI(*config->dpi); - - if(disconnected) - goto ret; - // Set Smartshift if it is configured - if(config->smartshift != nullptr) - setSmartShift(*config->smartshift); - - if(disconnected) - goto ret; - // Set Hires Scroll if it is configured - if(config->hiresscroll != nullptr) - setHiresScroll(*config->hiresscroll); - } - catch(HIDPP10::Error &e) - { - log_printf(ERROR, "HID++ 1.0 Error whjle configuring %s: %s", name.c_str(), e.what()); - } - -ret: - configuring.unlock(); -} - -void Device::reset() -{ - try - { - HIDPP20::IReset iReset(hidpp_dev); - iReset.reset(); - } - catch(HIDPP20::UnsupportedFeature &e) { } - catch(HIDPP10::Error &e) - { - log_printf(ERROR, "Failed to reset %s: %s", name.c_str(), e.what()); - } -} - -void Device::divert_buttons() -{ - try - { - HIDPP20::IReprogControls irc = HIDPP20::IReprogControls::auto_version(hidpp_dev); - if(disconnected) - return; - int controlCount = irc.getControlCount(); - for(int i = 0; i < controlCount; i++) - { - if(disconnected) - return; - uint16_t cid = irc.getControlInfo(i).control_id; - uint8_t flags = 0; - flags |= HIDPP20::IReprogControls::ChangeTemporaryDivert; - flags |= HIDPP20::IReprogControls::ChangeRawXYDivert; - - auto action = config->actions.find(cid); - if(action != config->actions.end()) - { - flags |= HIDPP20::IReprogControls::ChangeTemporaryDivert; - flags |= HIDPP20::IReprogControls::TemporaryDiverted; - if(action->second->type == Action::Gestures) - flags |= HIDPP20::IReprogControls::RawXYDiverted; - } - if(disconnected) - return; - irc.setControlReporting(cid, flags, cid); - } - } - catch(HIDPP20::UnsupportedFeature &e) - { - log_printf(DEBUG, "%s does not support Reprog controls, not diverting!", name.c_str()); - } - catch(HIDPP20::Error &e) - { - if(e.errorCode() == HIDPP20::Error::InvalidFunctionID) { - // Not really an error, the device does not support diverting buttons - } - else { - log_printf(ERROR, "Could not divert buttons: HID++ 2.0 Error %s!", e.what()); - } - } - catch(HIDPP10::Error &e) - { - log_printf(DEBUG, "Could not divert buttons: HID++ 1.0 Error %s!", e.what()); - } -} - -void Device::setSmartShift(HIDPP20::ISmartShift::SmartshiftStatus ops) -{ - try - { - if(disconnected) return; - HIDPP20::ISmartShift ss(hidpp_dev); - if(disconnected) return; - ss.setStatus(ops); - } - catch (HIDPP20::UnsupportedFeature &e) - { - log_printf(ERROR, "Device does not support SmartShift"); - } - catch (HIDPP20::Error &e) - { - log_printf(ERROR, "Error setting SmartShift options, code %d: %s\n", e.errorCode(), e.what()); - } -} - -void Device::setHiresScroll(uint8_t ops) -{ - try - { - if(disconnected) return; - HIDPP20::IHiresScroll hs(hidpp_dev); - if(disconnected) return; - 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::setDPI(int dpi) -{ - if(disconnected) return; - HIDPP20::IAdjustableDPI iad(hidpp_dev); - if(disconnected) return; - try { for(unsigned int i = 0; i < iad.getSensorCount(); i++) iad.setSensorDPI(i, dpi); } - catch (HIDPP20::Error &e) { log_printf(ERROR, "Error while setting DPI: %s", e.what()); } -} - -void Device::waitForReceiver() -{ - while(true) - { - waiting_for_receiver = true; - listener->addEventHandler(std::make_unique(this)); - listener->start(); - // Listener stopped, check if stopped or ReceiverHandler event - if (waiting_for_receiver) - return; - - usleep(200000); - - try - { - if(this->init()) break; - } - catch(BlacklistedDevice& e) { return; } - - log_printf(ERROR, "Failed to initialize device %d on %s, waiting for receiver"); - delete(listener); - listener = new SimpleListener(new HIDPP::SimpleDispatcher(path.c_str()), index); - } - log_printf(INFO, "%s detected: device %d on %s", name.c_str(), index, path.c_str()); - this->start(); -} - -void Device::printCIDs() { - try - { - HIDPP20::IReprogControls irc = HIDPP20::IReprogControls::auto_version(hidpp_dev); - if(disconnected) - return; - int controlCount = irc.getControlCount(); - for(int i = 0; i < controlCount; i++) - { - if(disconnected) - return; - uint16_t cid = irc.getControlInfo(i).control_id; - log_printf(DEBUG, "Available CID: 0x%x", cid); - } - } - catch(HIDPP20::UnsupportedFeature &e) - { - log_printf(DEBUG, "%s does not support Reprog controls, not diverting!", name.c_str()); - } -} - -void Device::start() -{ - printCIDs(); - configure(); - try { listener->addEventHandler(std::make_unique(this)); } - catch(HIDPP20::UnsupportedFeature &e) { } - - if(index == HIDPP::DefaultDevice || index == HIDPP::CordedDevice) - { - try { listener->addEventHandler( std::make_unique(this) ); } - catch(HIDPP20::UnsupportedFeature &e) { } - } - listener->start(); -} - -bool Device::testConnection() -{ - int i = MAX_CONNECTION_TRIES; - do { - try - { - HIDPP20::Device _hpp20dev(dispatcher, index); - return true; - } - catch(HIDPP10::Error &e) - { - if(e.errorCode() == HIDPP10::Error::ResourceError) // Asleep, wait for next event - return false; - if(i == MAX_CONNECTION_TRIES-1) - return false; - } - catch(std::exception &e) - { - if(i == MAX_CONNECTION_TRIES-1) - return false; - } - i++; - } while(i < MAX_CONNECTION_TRIES); - - return false; -} - -void ButtonHandler::handleEvent (const HIDPP::Report &event) -{ - switch (event.function()) - { - case HIDPP20::IReprogControls::Event::DivertedButtonEvent: - { - new_states = HIDPP20::IReprogControls::divertedButtonEvent(event); - if (states.empty()) - { - for (uint16_t i : new_states) - std::thread{[=]() { dev->pressButton(i); }}.detach(); - states = new_states; - break; - } - 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((ulong)(it - cids.begin())); - for (uint16_t i : cids) - { - if (std::find(new_states.begin(), new_states.end(), i) != new_states.end()) - { - if (std::find(states.begin(), states.end(), i) == states.end()) - std::thread{[=]() { dev->pressButton(i); }}.detach(); - } else - std::thread{[=]() { dev->releaseButton(i); }}.detach(); - } - states = new_states; - break; - } - case HIDPP20::IReprogControlsV4::Event::DivertedRawXYEvent: - { - auto raw_xy = HIDPP20::IReprogControlsV4::divertedRawXYEvent(event); - - for(uint16_t i : states) - std::thread{[=]() { dev->moveDiverted(i, raw_xy); }}.detach(); - break; - } - default: - break; - } -} - -void ReceiverHandler::handleEvent(const HIDPP::Report &event) -{ - switch(event.featureIndex()) - { - case HIDPP10::IReceiver::DeviceUnpaired: - { - log_printf(INFO, "%s (Device %d on %s) unpaired from receiver", dev->name.c_str(), dev->index, dev->path.c_str()); - std::thread {[=]() - { - finder->stopAndDeleteDevice(dev->path, dev->index); - finder->insertNewReceiverDevice(dev->path, dev->index); - }}.detach(); - break; - } - case HIDPP10::IReceiver::DevicePaired: - { - log_printf(DEBUG, "Receiver on %s: Device %d paired", dev->path.c_str(), event.deviceIndex()); - if(dev->waiting_for_receiver) - { - if(!dev->testConnection()) return; - dev->waiting_for_receiver = false; - dev->stop(); - } - //else: Likely an enumeration event, ignore. - break; - } - case HIDPP10::IReceiver::ConnectionStatus: - { - auto status = HIDPP10::IReceiver::connectionStatusEvent(event); - if(status == HIDPP10::IReceiver::LinkLoss) - { - log_printf(INFO, "Link lost to %s", dev->name.c_str()); - dev->disconnected = true; - } - else if (status == HIDPP10::IReceiver::ConnectionEstablished) - { - if(dev->waiting_for_receiver) - { - log_printf(DEBUG, "Receiver on %s: Connection established to device %d", dev->path.c_str(), event.deviceIndex()); - if(!dev->testConnection()) return; - dev->waiting_for_receiver = false; - std::thread { [=]() { dev->stop(); } }.detach(); - } - else - { - if(!dev->initialized) return; - dev->disconnected = false; - dev->configure(); - log_printf(INFO, "Connection established to %s", dev->name.c_str()); - } - } - break; - } - default: - break; - } -} - -void WirelessStatusHandler::handleEvent(const HIDPP::Report &event) -{ - switch(event.function()) - { - case HIDPP20::IWirelessDeviceStatus::StatusBroadcast: - { - auto status = HIDPP20::IWirelessDeviceStatus::statusBroadcastEvent(event); - if(status.ReconfNeeded) - dev->configure(); - break; - } - default: - { - log_printf(DEBUG, "Undocumented event %02x from WirelessDeviceStatus", event.function()); - break; - } - } -} - -void EventListener::removeEventHandlers () -{ - for (const auto &p: iterators) - dispatcher->unregisterEventHandler(p.second); - handlers.clear(); - iterators.clear(); -} - -EventListener::~EventListener() -{ - removeEventHandlers(); -} - -void EventListener::addEventHandler(std::unique_ptr &&handler) -{ - EventHandler *ptr = handler.get(); - for(uint8_t feature : handler->featureIndices()) - { - handlers.emplace(feature, std::move(handler)); - dispatcher->registerEventHandler(index, feature, [=](const HIDPP::Report &report) - { - ptr->handleEvent(report); - return true; - }); - } -} - -void SimpleListener::start() -{ - bool retry; - do - { - retry = false; - try { dispatcher->listen(); } - catch(std::system_error &e) - { - retry = true; - usleep(250000); - } - } while(retry && !stopped); - -} - -void SimpleListener::stop() -{ - this->stopped = true; - dispatcher->stop(); -} - -bool SimpleListener::event (EventHandler *handler, const HIDPP::Report &report) -{ - handler->handleEvent (report); - return true; -} - -void Device::stop() -{ - disconnected = true; - listener->stop(); -} - -void Device::pressButton(uint16_t cid) -{ - if(config->actions.find(cid) == config->actions.end()) - { - log_printf(DEBUG, "0x%x was pressed but no action was found.", cid); - return; - } - config->actions.find(cid)->second->press(); -} - -void Device::releaseButton(uint16_t cid) -{ - if(config->actions.find(cid) == config->actions.end()) - { - log_printf(DEBUG, "0x%x was released but no action was found.", cid); - return; - } - config->actions.find(cid)->second->release(); -} - -void Device::moveDiverted(uint16_t cid, HIDPP20::IReprogControlsV4::Move m) -{ - auto action = config->actions.find(cid); - if(action == config->actions.end()) - return; - switch(action->second->type) - { - case Action::Gestures: - ((GestureAction*)action->second)->move(m); - break; - default: - break; - } -} - -std::map Device::getFeatures() -{ - std::map _features; - HIDPP20::IFeatureSet ifs (hidpp_dev); - uint8_t feature_count = ifs.getCount(); - - for(uint8_t i = 0; i < feature_count; i++) - _features.insert( {i, ifs.getFeatureID(i) } ); - - return _features; + log_printf(INFO, "%s:%d woke up.", _path.c_str(), _index); } diff --git a/src/logid/Device.h b/src/logid/Device.h index 4a3ca6c..a9f22da 100644 --- a/src/logid/Device.h +++ b/src/logid/Device.h @@ -1,172 +1,26 @@ #ifndef LOGID_DEVICE_H #define LOGID_DEVICE_H -#include "Actions.h" -#include "DeviceMonitor.h" -#include "Configuration.h" - -#include -#include -#include -#include -#include -#include -#include +#include "backend/hidpp/defs.h" +#include "backend/hidpp20/Device.h" namespace logid { - class EventListener; - class DeviceConfig; - - class BlacklistedDevice : public std::exception - { - public: - BlacklistedDevice() = default; - virtual const char* what() - { - return "Blacklisted device"; - } - }; - + /* TODO: Implement HID++ 1.0 support + * Currently, the logid::Device class has a hardcoded requirement + * for an HID++ 2.0 device. + */ class Device { public: - Device(std::string p, const HIDPP::DeviceIndex i); - ~Device(); - - std::string name; - - bool init(); - void configure(); - void reset(); - - void pressButton(uint16_t cid); - void releaseButton(uint16_t cid); - void moveDiverted(uint16_t cid, HIDPP20::IReprogControlsV4::Move move); - - void waitForReceiver(); - void start(); - void stop(); - bool testConnection(); - - std::map getFeatures(); - - std::map features; - - const std::string path; - const HIDPP::DeviceIndex index; - HIDPP::Dispatcher* dispatcher; - HIDPP20::Device* hidpp_dev; - - std::mutex configuring; - std::atomic_bool disconnected; - bool initialized = false; - bool waiting_for_receiver = false; - - protected: - DeviceConfig* config; - EventListener* listener; - - void divert_buttons(); - void printCIDs(); - void setSmartShift(HIDPP20::ISmartShift::SmartshiftStatus ops); - void setHiresScroll(uint8_t flags); - void setDPI(int dpi); + Device(std::string path, backend::hidpp::DeviceIndex index); + void wakeup(); + void sleep(); + private: + backend::hidpp20::Device _hidpp20; + std::string _path; + backend::hidpp::DeviceIndex _index; }; - - 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 (Device *d) : dev (d), _irc (HIDPP20::IReprogControls::auto_version(d->hidpp_dev)) { } - const HIDPP20::FeatureInterface *feature () const - { - return &_irc; - } - void handleEvent (const HIDPP::Report &event); - protected: - Device* dev; - HIDPP20::IReprogControls _irc; - std::vector states; - std::vector new_states; - }; - class ReceiverHandler : public EventHandler - { - public: - ReceiverHandler (Device *d) : dev (d) { } - const HIDPP20::FeatureInterface *feature () const - { - return nullptr; // This sounds like a horrible idea - } - virtual const std::vector featureIndices() const - { - return HIDPP10::IReceiver::Events; - } - void handleEvent (const HIDPP::Report &event); - protected: - Device* dev; - }; - class WirelessStatusHandler : public EventHandler - { - public: - WirelessStatusHandler (Device *d) : dev (d), _iws (d->hidpp_dev) { } - const HIDPP20::FeatureInterface *feature () const - { - return &_iws; - } - void handleEvent (const HIDPP::Report &event); - protected: - Device* dev; - HIDPP20::IWirelessDeviceStatus _iws; - }; - - 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) - { - } - - bool stopped = false; - virtual void start(); - virtual void stop(); - - protected: - virtual bool event (EventHandler* handler, const HIDPP::Report &report); - }; - } #endif //LOGID_DEVICE_H diff --git a/src/logid/DeviceMonitor.cpp b/src/logid/DeviceMonitor.cpp index a24aec4..0f9beb4 100644 --- a/src/logid/DeviceMonitor.cpp +++ b/src/logid/DeviceMonitor.cpp @@ -2,6 +2,7 @@ #include #include "DeviceMonitor.h" +#include "Receiver.h" #include "util.h" #include "backend/hidpp10/Error.h" #include "backend/dj/Receiver.h" @@ -11,161 +12,65 @@ using namespace logid; using namespace logid::backend; -/* -void stopAndDeleteConnectedDevice (ConnectedDevice &connected_device) -{ - if(!connected_device.device->waiting_for_receiver) - log_printf(INFO, "%s (Device %d on %s) disconnected", connected_device.device->name.c_str(), - connected_device.device->index, connected_device.device->path.c_str()); - connected_device.device->stop(); - connected_device.associatedThread.join(); - delete(connected_device.device); -} - -DeviceMonitor::~DeviceMonitor() -{ - this->devices_mutex.lock(); - for (auto it = this->devices.begin(); it != this->devices.end(); it++) { - for (auto jt = it->second.begin(); jt != it->second.end(); jt++) { - stopAndDeleteConnectedDevice(jt->second); - } - } - this->devices_mutex.unlock(); -} - -Device* DeviceMonitor::insertNewDevice(const std::string &path, HIDPP::DeviceIndex index) -{ - auto device = new Device(path, index); - device->init(); - - this->devices_mutex.lock(); - log_printf(INFO, "%s detected: device %d on %s", device->name.c_str(), index, path.c_str()); - auto path_bucket = this->devices.emplace(path, std::map()).first; - path_bucket->second.emplace(index, ConnectedDevice{ - device, - std::thread([device]() { - device->start(); - }) - }); - this->devices_mutex.unlock(); - - return device; -} - -Device* DeviceMonitor::insertNewReceiverDevice(const std::string &path, HIDPP::DeviceIndex index) -{ - auto *device = new Device(path, index); - this->devices_mutex.lock(); - auto path_bucket = this->devices.emplace(path, std::map()).first; - path_bucket->second.emplace(index, ConnectedDevice{ - device, - std::thread([device]() { - device->waitForReceiver(); - }) - }); - this->devices_mutex.unlock(); - - return device; -} - -void DeviceMonitor::stopAndDeleteAllDevicesIn (const std::string &path) -{ - this->devices_mutex.lock(); - auto path_bucket = this->devices.find(path); - if (path_bucket != this->devices.end()) - { - for (auto& index_bucket : path_bucket->second) { - stopAndDeleteConnectedDevice(index_bucket.second); - } - this->devices.erase(path_bucket); - } - this->devices_mutex.unlock(); -} - -void DeviceMonitor::stopAndDeleteDevice (const std::string &path, HIDPP::DeviceIndex index) -{ - this->devices_mutex.lock(); - auto path_bucket = this->devices.find(path); - if (path_bucket != this->devices.end()) - { - auto index_bucket = path_bucket->second.find(index); - if (index_bucket != path_bucket->second.end()) - { - stopAndDeleteConnectedDevice(index_bucket->second); - path_bucket->second.erase(index_bucket); - } - } - this->devices_mutex.unlock(); - - log_printf(WARN, "Attempted to disconnect not previously connected device %d on %s", index, path.c_str()); -} -*/ - void DeviceMonitor::addDevice(std::string path) { + bool defaultExists = true; + bool isReceiver = false; try { - std::tuple version; - try - { - hidpp::Device device(path, hidpp::DefaultDevice); - - log_printf(DEBUG, "Detected HID++ device at %s", path.c_str()); - - version = device.version(); - log_printf(DEBUG, "HID++ version: %d.%d", std::get<0>(version), std::get<1>(version)); - } catch(std::system_error &e) { } - - if(version == std::make_tuple(1, 0)) - { - // This is a receiver - dj::Receiver receiver(path); - receiver.enumerate(); - receiver.listen(); - while(true) {} - } - /* - auto eventHandler = std::make_shared(); - eventHandler->condition = [device](backend::hidpp::Report& report)->bool - { - return true; - }; - eventHandler->callback = [device](backend::hidpp::Report& report)->void - { - log_printf(DEBUG, "Event on %s:%d", device->devicePath().c_str(), - device->deviceIndex()); - for(auto& i : report.rawReport()) - printf("%02x ", i); - printf("\n"); - }; - - device->addEventHandler("MONITOR_ALL", eventHandler); - - devices.push_back(device);*/ - - //std::thread([device]() { device->listen(); }).detach(); - } - catch(hidpp10::Error &e) - { - if(e.code() == hidpp10::Error::UnknownDevice) {} - else + hidpp::Device device(path, hidpp::DefaultDevice); + isReceiver = device.version() == std::make_tuple(1, 0); + } catch(hidpp10::Error &e) { + if(e.code() != hidpp10::Error::UnknownDevice) throw; + } catch(hidpp::Device::InvalidDevice &e) { // Ignore + defaultExists = false; + } catch(std::system_error &e) { + log_printf(WARN, "I/O error on %s: %s, skipping device.", + path.c_str(), e.what()); + return; } - catch(hidpp::Device::InvalidDevice &e) - { - log_printf(DEBUG, "Detected device at %s but %s", path.c_str(), e.what()); + + if(isReceiver) { + log_printf(INFO, "Detected receiver at %s", path.c_str()); + auto receiver = std::make_shared(path); + _receivers.emplace(path, receiver); + // receiver->listen(); + } else { + /* TODO: Error check? + * 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); + _devices.emplace(path, device); + } else { + try { + auto device = std::make_shared(path, hidpp::CordedDevice); + _devices.emplace(path, device); + } catch(hidpp10::Error &e) { + if(e.code() != hidpp10::Error::UnknownDevice) + throw; + } catch(hidpp::Device::InvalidDevice &e) { // Ignore + } catch(std::system_error &e) { + // This error should have been thrown previously + log_printf(WARN, "I/O error on %s: %s", path.c_str(), + e.what()); + } + } } - /* - catch(std::system_error &e) - { - log_printf(WARN, "Failed to open %s: %s", path.c_str(), e.what()); - } */ } void DeviceMonitor::removeDevice(std::string path) { - log_printf(DEBUG, "Device %s disconnected", path.c_str()); - /* - ipc_server->removeReceiver(path); - this->stopAndDeleteAllDevicesIn(std::string(path)); - */ + auto receiver = _receivers.find(path); + + if(receiver != _receivers.end()) { + _receivers.erase(receiver); + log_printf(INFO, "Receiver on %s disconnected", path.c_str()); + } else { + auto device = _devices.find(path); + if(device != _devices.find(path)) { + _devices.erase(device); + log_printf(INFO, "Device on %s disconnected", path.c_str()); + } + } } diff --git a/src/logid/DeviceMonitor.h b/src/logid/DeviceMonitor.h index f95f642..dfd7650 100644 --- a/src/logid/DeviceMonitor.h +++ b/src/logid/DeviceMonitor.h @@ -7,38 +7,23 @@ #include "backend/raw/DeviceMonitor.h" #include "backend/hidpp/Device.h" - -#define MAX_CONNECTION_TRIES 10 -#define TIME_BETWEEN_CONNECTION_TRIES 500ms +#include "Device.h" +#include "Receiver.h" namespace logid { - class Device; - - struct ConnectedDevice { - Device *device; - std::thread associatedThread; - }; - class DeviceMonitor : public backend::raw::DeviceMonitor { public: - ~DeviceMonitor(); - - /* - Device* insertNewDevice (const std::string &path, HIDPP::DeviceIndex index); - Device* insertNewReceiverDevice (const std::string &path, HIDPP::DeviceIndex index); - void stopAndDeleteAllDevicesIn (const std::string &path); - void stopAndDeleteDevice (const std::string &path, HIDPP::DeviceIndex index); - */ + DeviceMonitor() = default; protected: void addDevice(std::string path) override; void removeDevice(std::string path) override; private: - std::mutex devices_mutex; - std::vector> devices; //tmp - //std::map> devices; + + std::map> _devices; + std::map> _receivers; }; extern DeviceMonitor* finder; diff --git a/src/logid/Receiver.cpp b/src/logid/Receiver.cpp new file mode 100644 index 0000000..77d34c8 --- /dev/null +++ b/src/logid/Receiver.cpp @@ -0,0 +1,9 @@ +#include "Receiver.h" +#include "util.h" + +using namespace logid; + +Receiver::Receiver(std::string path) : _path (path) +{ + log_printf(DEBUG, "logid::Receiver created on %s", path.c_str()); +} \ No newline at end of file diff --git a/src/logid/Receiver.h b/src/logid/Receiver.h new file mode 100644 index 0000000..a01f37f --- /dev/null +++ b/src/logid/Receiver.h @@ -0,0 +1,17 @@ +#ifndef LOGID_RECEIVER_H +#define LOGID_RECEIVER_H + +#include + +namespace logid +{ + class Receiver + { + public: + Receiver(std::string path); + private: + std::string _path; + }; +} + +#endif //LOGID_RECEIVER_H \ No newline at end of file diff --git a/src/logid/backend/dj/ReceiverMonitor.cpp b/src/logid/backend/dj/ReceiverMonitor.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/logid/backend/dj/ReceiverMonitor.h b/src/logid/backend/dj/ReceiverMonitor.h new file mode 100644 index 0000000..f717da0 --- /dev/null +++ b/src/logid/backend/dj/ReceiverMonitor.h @@ -0,0 +1,6 @@ +#ifndef LOGID_BACKEND_DJ_RECEIVERMONITOR_H +#define LOGID_BACKEND_DJ_RECEIVERMONITOR_H + + + +#endif //LOGID_BACKEND_DJ_RECEIVERMONITOR_H \ No newline at end of file diff --git a/src/logid/backend/hidpp20/Device.cpp b/src/logid/backend/hidpp20/Device.cpp index 917601c..0d93ecc 100644 --- a/src/logid/backend/hidpp20/Device.cpp +++ b/src/logid/backend/hidpp20/Device.cpp @@ -5,6 +5,18 @@ using namespace logid::backend::hidpp20; +Device::Device(std::string path, hidpp::DeviceIndex index) + : hidpp::Device(path, index) +{ + assert(std::get<0>(version()) >= 2); +} + +Device::Device(std::shared_ptr raw_device, hidpp::DeviceIndex index) + : hidpp::Device(raw_device, index) +{ + assert(std::get<0>(version()) >= 2); +} + std::vector Device::callFunction(uint8_t feature_index, uint8_t function, std::vector& params) { diff --git a/src/logid/backend/hidpp20/Device.h b/src/logid/backend/hidpp20/Device.h index 38f42eb..c0b2ff4 100644 --- a/src/logid/backend/hidpp20/Device.h +++ b/src/logid/backend/hidpp20/Device.h @@ -10,6 +10,9 @@ namespace hidpp20 { class Device : public hidpp::Device { public: + Device(std::string path, hidpp::DeviceIndex index); + Device(std::shared_ptr raw_device, hidpp::DeviceIndex index); + std::vector callFunction(uint8_t feature_index, uint8_t function, std::vector& params); diff --git a/src/logid/util.h b/src/logid/util.h index 09bea48..1478fed 100644 --- a/src/logid/util.h +++ b/src/logid/util.h @@ -1,7 +1,7 @@ #ifndef LOGID_UTIL_H #define LOGID_UTIL_H -//#include "Actions.h" +#include namespace logid {