mirror of
https://github.com/PixlOne/logiops.git
synced 2025-07-14 05:12:34 +08:00
Ignore hidpp responses to kernel driver
Also fixes a bug where unconfigured devices would error.
This commit is contained in:
parent
7862c85d71
commit
f25a1e4657
@ -296,7 +296,12 @@ config::Device& Device::_getConfig(
|
||||
auto& devices = manager->config()->devices;
|
||||
if(!devices.has_value())
|
||||
devices = decltype(config::Config::devices)();
|
||||
auto& device = devices.value()[name];
|
||||
|
||||
if(!devices.value().count(name)) {
|
||||
devices.value().emplace(name, config::Device());
|
||||
}
|
||||
|
||||
auto& device = devices.value().at(name);
|
||||
if(std::holds_alternative<config::Profile>(device)) {
|
||||
config::Device d;
|
||||
d.profiles["default"] = std::get<config::Profile>(device);
|
||||
@ -306,7 +311,7 @@ config::Device& Device::_getConfig(
|
||||
|
||||
auto& conf = std::get<config::Device>(device);
|
||||
if(conf.profiles.empty()) {
|
||||
conf.profiles["default"] = std::get<config::Profile>(device);
|
||||
conf.profiles["default"] = {};
|
||||
conf.default_profile = "default";
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,13 @@ void DeviceManager::addDevice(std::string path)
|
||||
} catch(hidpp10::Error &e) {
|
||||
if(e.code() != hidpp10::Error::UnknownDevice)
|
||||
throw;
|
||||
} catch(hidpp::Device::InvalidDevice &e) { // Ignore
|
||||
} catch(hidpp::Device::InvalidDevice &e) {
|
||||
if(e.code() == hidpp::Device::InvalidDevice::VirtualNode) {
|
||||
logPrintf(DEBUG, "Ignoring virtual node on %s",
|
||||
path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
defaultExists = false;
|
||||
} catch(std::system_error &e) {
|
||||
logPrintf(WARN, "I/O error on %s: %s, skipping device.",
|
||||
|
@ -47,6 +47,61 @@ std::shared_ptr<Action> _makeAction(Device* device,
|
||||
return std::make_shared<typename action_type<T>::type>(device, action);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::shared_ptr<Action> _makeAction(
|
||||
Device *device, const std::string &name,
|
||||
std::optional<T>& config)
|
||||
{
|
||||
if(name == "pizza.pixl.LogiOps.Action.ChangeDPI") {
|
||||
config = config::ChangeDPI();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.ChangeHost") {
|
||||
config = config::ChangeHost();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.CycleDPI") {
|
||||
config = config::CycleDPI();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.Keypress") {
|
||||
config = config::KeypressAction();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.None") {
|
||||
config = config::NoAction();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.ToggleHiresScroll") {
|
||||
config = config::ToggleHiresScroll();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.ToggleSmartShift") {
|
||||
config = config::ToggleHiresScroll();
|
||||
return Action::makeAction(device, config.value());
|
||||
} else if(name == "pizza.pixl.LogiOps.Action.Default") {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
throw InvalidAction();
|
||||
}
|
||||
|
||||
std::shared_ptr<Action> Action::makeAction(
|
||||
Device *device, const std::string &name,
|
||||
std::optional<config::BasicAction> &config)
|
||||
{
|
||||
return _makeAction(device, name, config);
|
||||
}
|
||||
|
||||
std::shared_ptr<Action> Action::makeAction(
|
||||
Device *device, const std::string &name,
|
||||
std::optional<config::Action> &config)
|
||||
{
|
||||
try {
|
||||
return _makeAction(device, name, config);
|
||||
} catch(actions::InvalidAction& e) {
|
||||
if(name == "pizza.pixl.LogiOps.Action.Gesture") {
|
||||
config = config::GestureAction();
|
||||
return makeAction(device, config.value());
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Action> Action::makeAction(Device *device,
|
||||
config::BasicAction& action)
|
||||
{
|
||||
|
@ -46,6 +46,14 @@ namespace actions {
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<Action> makeAction(
|
||||
Device* device, const std::string& name,
|
||||
std::optional<config::BasicAction>& config);
|
||||
|
||||
static std::shared_ptr<Action> makeAction(
|
||||
Device* device, const std::string& name,
|
||||
std::optional<config::Action>& config);
|
||||
|
||||
static std::shared_ptr<Action> makeAction(Device* device,
|
||||
config::BasicAction& action);
|
||||
|
||||
|
@ -22,8 +22,3 @@ const char *logid::backend::TimeoutError::what() const noexcept
|
||||
{
|
||||
return "Device timed out";
|
||||
}
|
||||
|
||||
const char *logid::backend::InvalidDevice::what() const noexcept
|
||||
{
|
||||
return "Device has become invalidated";
|
||||
}
|
||||
|
@ -30,12 +30,6 @@ public:
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
|
||||
class InvalidDevice : public std::exception
|
||||
{
|
||||
public:
|
||||
InvalidDevice() = default;
|
||||
const char* what() const noexcept override;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif //LOGID_BACKEND_ERROR_H
|
@ -41,6 +41,8 @@ const char* Device::InvalidDevice::what() const noexcept
|
||||
return "Invalid raw device";
|
||||
case Asleep:
|
||||
return "Device asleep";
|
||||
case VirtualNode:
|
||||
return "Virtual device";
|
||||
default:
|
||||
return "Invalid device";
|
||||
}
|
||||
@ -122,6 +124,35 @@ void Device::_init()
|
||||
if(!supported_reports)
|
||||
throw InvalidDevice(InvalidDevice::NoHIDPPReport);
|
||||
|
||||
/* hid_logitech_dj creates virtual /dev/hidraw nodes for receiver
|
||||
* devices. We should ignore these devices.
|
||||
*/
|
||||
if(_index == hidpp::DefaultDevice) {
|
||||
_raw_handler = _raw_device->addEventHandler({
|
||||
[index=this->_index](const std::vector<uint8_t>& report)->bool {
|
||||
return (report[Offset::Type] == Report::Type::Short ||
|
||||
report[Offset::Type] == Report::Type::Long);
|
||||
}, [this](const std::vector<uint8_t>& report)->void {
|
||||
Report _report(report);
|
||||
this->handleEvent(_report);
|
||||
} });
|
||||
|
||||
try {
|
||||
auto rsp = sendReport({ReportType::Short, _index, 0, 0,
|
||||
LOGID_HIDPP_SOFTWARE_ID});
|
||||
if(rsp.deviceIndex() != _index) {
|
||||
throw InvalidDevice(InvalidDevice::VirtualNode);
|
||||
}
|
||||
} catch(hidpp10::Error& e) {
|
||||
// Ignore
|
||||
} catch(std::exception& e) {
|
||||
_raw_device->removeEventHandler(_raw_handler);
|
||||
throw;
|
||||
}
|
||||
|
||||
_raw_device->removeEventHandler(_raw_handler);
|
||||
}
|
||||
|
||||
_raw_handler = _raw_device->addEventHandler({
|
||||
[index=this->_index](const std::vector<uint8_t>& report)->bool {
|
||||
return (report[Offset::Type] == Report::Type::Short ||
|
||||
@ -227,14 +258,16 @@ Report Device::sendReport(const Report &report)
|
||||
if(!valid)
|
||||
throw TimeoutError();
|
||||
|
||||
std::lock_guard<std::mutex> sl(_slot_lock);
|
||||
|
||||
{
|
||||
Report::Hidpp10Error error{};
|
||||
if(report.isError10(&error))
|
||||
if(_report_slot.value().isError10(&error))
|
||||
throw hidpp10::Error(error.error_code);
|
||||
}
|
||||
{
|
||||
Report::Hidpp20Error error{};
|
||||
if(report.isError20(&error))
|
||||
if(_report_slot.value().isError20(&error))
|
||||
throw hidpp20::Error(error.error_code);
|
||||
}
|
||||
return _report_slot.value();
|
||||
@ -247,6 +280,11 @@ bool Device::responseReport(const Report &report)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Basic check to see if the report is a response
|
||||
if( (report.swId() != LOGID_HIDPP_SOFTWARE_ID)
|
||||
&& report.subId() < 0x80)
|
||||
return false;
|
||||
|
||||
std::lock_guard lock(_slot_lock);
|
||||
_report_slot = report;
|
||||
_resp_cv.notify_all();
|
||||
|
@ -53,7 +53,8 @@ namespace hidpp
|
||||
{
|
||||
NoHIDPPReport,
|
||||
InvalidRawDevice,
|
||||
Asleep
|
||||
Asleep,
|
||||
VirtualNode
|
||||
};
|
||||
InvalidDevice(Reason reason) : _reason (reason) {}
|
||||
virtual const char* what() const noexcept;
|
||||
|
@ -246,10 +246,10 @@ uint8_t Report::swId() const
|
||||
return _data[Offset::Function] & 0x0f;
|
||||
}
|
||||
|
||||
void Report::setSwId(uint8_t sub_id)
|
||||
void Report::setSwId(uint8_t sw_id)
|
||||
{
|
||||
_data[Offset::Function] &= 0xf0;
|
||||
_data[Offset::Function] |= sub_id & 0x0f;
|
||||
_data[Offset::Function] |= sw_id & 0x0f;
|
||||
}
|
||||
|
||||
uint8_t Report::address() const
|
||||
|
@ -19,7 +19,7 @@
|
||||
#ifndef LOGID_BACKEND_HIDPP_DEFS_H
|
||||
#define LOGID_BACKEND_HIDPP_DEFS_H
|
||||
|
||||
#define LOGID_HIDPP_SOFTWARE_ID 1
|
||||
#define LOGID_HIDPP_SOFTWARE_ID 2
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
@ -169,12 +169,16 @@ hidpp::Report Device::sendReport(const hidpp::Report& report)
|
||||
bool Device::responseReport(const hidpp::Report& report)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_response_lock);
|
||||
uint8_t sw_id = report.swId();
|
||||
uint8_t sw_id;
|
||||
|
||||
bool is_error = false;
|
||||
hidpp::Report::Hidpp20Error hidpp20_error {};
|
||||
if(report.isError20(&hidpp20_error))
|
||||
if(report.isError20(&hidpp20_error)) {
|
||||
is_error = true;
|
||||
sw_id = hidpp20_error.software_id;
|
||||
} else {
|
||||
sw_id = report.swId();
|
||||
}
|
||||
|
||||
auto response_slot = _responses.find(sw_id);
|
||||
if(response_slot == _responses.end())
|
||||
|
@ -74,6 +74,10 @@ uint8_t EssentialDeviceName::getNameLength()
|
||||
std::vector<uint8_t> params(0);
|
||||
|
||||
auto response = this->callFunction(DeviceName::Function::GetLength, params);
|
||||
|
||||
if(response[0] == 1)
|
||||
return 1;
|
||||
|
||||
return response[0];
|
||||
}
|
||||
|
||||
|
@ -92,5 +92,8 @@ std::tuple<uint8_t, uint8_t> EssentialRoot::getVersion()
|
||||
std::vector<uint8_t> params(0);
|
||||
auto response = this->callFunction(Root::Function::Ping, params);
|
||||
|
||||
if(response[0] == 0x11)
|
||||
return std::make_tuple(1, 0);
|
||||
|
||||
return std::make_tuple(response[0], response[1]);
|
||||
}
|
@ -155,8 +155,10 @@ const std::vector<uint8_t>& RawDevice::reportDescriptor() const
|
||||
|
||||
void RawDevice::sendReport(const std::vector<uint8_t>& report)
|
||||
{
|
||||
if(!_valid)
|
||||
throw InvalidDevice();
|
||||
if(!_valid) {
|
||||
// We could throw an error here, but this will likely be closed soon.
|
||||
return;
|
||||
}
|
||||
|
||||
if(logid::global_loglevel <= LogLevel::RAWREPORT) {
|
||||
printf("[RAWREPORT] %s OUT: ", _path.c_str());
|
||||
|
@ -382,11 +382,10 @@ namespace logid::config {
|
||||
struct config_io<std::optional<T>> {
|
||||
static std::optional<T> get(const libconfig::Setting& parent,
|
||||
const std::string& name) {
|
||||
try {
|
||||
if(parent.exists(name))
|
||||
return config_io<T>::get(parent.lookup(name));
|
||||
} catch(libconfig::SettingException& e) {
|
||||
else
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static void set(libconfig::Setting& parent,
|
||||
|
Loading…
Reference in New Issue
Block a user