diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index d4b1c3e..fec0e6c 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -248,19 +248,7 @@ void ReceiverHandler::handleEvent(const HIDPP::Report &event) { 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.c_str()); - it->first->stop(); - it->second.join(); - finder->devices.erase(it); - } - else it++; - } + finder->stopAndDeleteDevice(dev->path, event.deviceIndex()); break; } case HIDPP10::IReceiver::DevicePaired: @@ -384,4 +372,4 @@ std::map Device::get_features() _features.insert( {i, ifs.getFeatureID(i) } ); return _features; -} \ No newline at end of file +} diff --git a/src/logid/DeviceFinder.cpp b/src/logid/DeviceFinder.cpp index 1e9e261..31b8fb1 100644 --- a/src/logid/DeviceFinder.cpp +++ b/src/logid/DeviceFinder.cpp @@ -14,6 +14,76 @@ #include "util.h" #include "Device.h" +void stopAndDeletePairedDevice (PairedDevice &pairedDevice) +{ + log_printf(INFO, "%s (Device %d on %s) disconnected", pairedDevice.device->name.c_str(), pairedDevice.device->index, pairedDevice.device->path.c_str()); + pairedDevice.device->stop(); + pairedDevice.associatedThread.join(); + delete(pairedDevice.device); +} + +DeviceFinder::~DeviceFinder() +{ + this->devicesMutex.lock(); + for (auto it = this->devices.begin(); it != this->devices.end(); it++) { + for (auto jt = it->second.begin(); jt != it->second.end(); jt++) { + stopAndDeletePairedDevice(jt->second); + } + } + this->devicesMutex.unlock(); +} + +void DeviceFinder::insertNewDevice(const std::string &path, HIDPP::DeviceIndex index) +{ + Device *device = new Device(path, index); + + this->devicesMutex.lock(); + log_printf(INFO, "%s detected: device %d on %s", device->name.c_str(), index, path.c_str()); + auto pathBucket = this->devices.emplace(path, std::map()).first; + pathBucket->second.emplace(index, PairedDevice{ + device, + std::thread([device]() { + device->start(); + }) + }); + this->devicesMutex.unlock(); +} + +void DeviceFinder::stopAndDeleteAllDevicesIn (const std::string &path) +{ + this->devicesMutex.lock(); + auto pathBucket = this->devices.find(path); + if (pathBucket != this->devices.end()) + { + for (auto& indexBucket : pathBucket->second) { + stopAndDeletePairedDevice(indexBucket.second); + } + this->devices.erase(pathBucket); + } + this->devicesMutex.unlock(); + + log_printf(WARN, "Attempted to disconnect not previously connected devices on %s", path.c_str()); +} + +void DeviceFinder::stopAndDeleteDevice (const std::string &path, HIDPP::DeviceIndex index) +{ + this->devicesMutex.lock(); + auto pathBucket = this->devices.find(path); + if (pathBucket != this->devices.end()) + { + auto indexBucket = pathBucket->second.find(index); + if (indexBucket != pathBucket->second.end()) + { + stopAndDeletePairedDevice(indexBucket->second); + pathBucket->second.erase(indexBucket); + } + } + this->devicesMutex.unlock(); + + log_printf(WARN, "Attempted to disconnect not previously connected device %d on %s", index, path.c_str()); +} + + void DeviceFinder::addDevice(const char *path) { std::string string_path(path); @@ -34,6 +104,7 @@ void DeviceFinder::addDevice(const char *path) HIDPP::WirelessDevice3, HIDPP::WirelessDevice4, HIDPP::WirelessDevice5, HIDPP::WirelessDevice6}) { + if(!has_receiver_index && index == HIDPP::WirelessDevice1) break; for(int i = 0; i < max_tries; i++) @@ -48,18 +119,7 @@ void DeviceFinder::addDevice(const char *path) has_receiver_index = true; if(major > 1) // HID++ 2.0 devices only { - auto dev = new Device(string_path, index); - - this->devicesMutex.lock(); - this->devices.insert({ - dev, - std::thread{[dev]() { - dev->start(); - }} - }); - this->devicesMutex.unlock(); - - log_printf(INFO, "%s detected: device %d on %s", d.name().c_str(), index, string_path.c_str()); + this->insertNewDevice(string_path, index); } break; } @@ -106,18 +166,5 @@ void DeviceFinder::addDevice(const char *path) void DeviceFinder::removeDevice(const char* path) { - devicesMutex.lock(); - // Iterate through Devices, stop all in path - for (auto it = devices.begin(); it != devices.end(); it++) - { - if(it->first->path == path) - { - log_printf(INFO, "%s on %s disconnected.", it->first->name.c_str(), path); - it->first->stop(); - it->second.join(); - delete(it->first); - devices.erase(it); - } - } - devicesMutex.unlock(); + this->stopAndDeleteAllDevicesIn(std::string(path)); } diff --git a/src/logid/DeviceFinder.h b/src/logid/DeviceFinder.h index 2e1e5e2..9ca6a5d 100644 --- a/src/logid/DeviceFinder.h +++ b/src/logid/DeviceFinder.h @@ -5,22 +5,34 @@ #include #include #include -#include +#include +#include #include -#include "Device.h" #include +#include "Device.h" + class Device; +struct PairedDevice { + Device *device; + std::thread associatedThread; +}; + class DeviceFinder : public HID::DeviceMonitor { public: - std::map devices; + ~DeviceFinder(); + + void insertNewDevice (const std::string &path, HIDPP::DeviceIndex index); + void stopAndDeleteAllDevicesIn (const std::string &path); + void stopAndDeleteDevice (const std::string &path, HIDPP::DeviceIndex index); protected: void addDevice(const char* path); void removeDevice(const char* path); private: std::mutex devicesMutex; + std::map> devices; }; extern DeviceFinder* finder;