Use events instead of continous pinging
This commit is contained in:
+90
-83
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user