Use events instead of continous pinging

This commit is contained in:
PixlOne
2019-07-28 02:08:18 -04:00
parent 684f502b2e
commit b95cc60fd1
13 changed files with 366 additions and 291 deletions
+90 -83
View File
@@ -6,21 +6,23 @@
#include <hidpp20/IFeatureSet.h>
#include <hidpp20/Error.h>
#include <hidpp20/IReprogControls.h>
#include <hidpp20/ISmartShift.h>
#include <hidpp20/Device.h>
#include <hidpp10/Error.h>
#include <algorithm>
#include <cstring>
#include <utility>
#include <hidpp20/UnsupportedFeature.h>
#include <hidpp20/IHiresScroll.h>
#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<uint8_t> 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<ButtonHandler>(hidpp_dev, this) );
auto listener_thread = std::thread { [=]() { listener->start(); } };
listener_thread.detach();
while(!DeviceRemoved)
{
std::mutex m;
std::condition_variable cv;
std::vector<uint8_t> 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<std::mutex> 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<ReceiverHandler>(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<uint16_t>::iterator it;
std::vector<uint16_t> 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<EventHandler> &&handler)
void EventListener::addEventHandler(std::unique_ptr<EventHandler> &&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<uint16_t, uint8_t> Device::get_features()
std::map<uint16_t, uint8_t> 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;
}