From 07b8fc1af4d0a7029b1413e0c086af57ac6969a5 Mon Sep 17 00:00:00 2001 From: pixl Date: Thu, 2 Jul 2020 03:34:14 -0400 Subject: [PATCH] Add DPI feature --- src/logid/CMakeLists.txt | 1 + src/logid/Configuration.cpp | 6 +- src/logid/Device.cpp | 28 +++++-- src/logid/Device.h | 8 +- src/logid/features/DPI.cpp | 114 +++++++++++++++++++++++++++++ src/logid/features/DPI.h | 49 +++++++++++++ src/logid/features/DeviceFeature.h | 7 +- 7 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 src/logid/features/DPI.cpp create mode 100644 src/logid/features/DPI.h diff --git a/src/logid/CMakeLists.txt b/src/logid/CMakeLists.txt index 440f4f2..733ed0d 100644 --- a/src/logid/CMakeLists.txt +++ b/src/logid/CMakeLists.txt @@ -15,6 +15,7 @@ add_executable(logid Device.cpp Receiver.cpp Configuration.cpp + features/DPI.cpp backend/Error.cpp backend/raw/DeviceMonitor.cpp backend/raw/RawDevice.cpp diff --git a/src/logid/Configuration.cpp b/src/logid/Configuration.cpp index 9bb1e14..9846951 100644 --- a/src/logid/Configuration.cpp +++ b/src/logid/Configuration.cpp @@ -44,14 +44,12 @@ Configuration::Configuration(const std::string& config_file) Setting* devices; try { devices = &root["devices"]; } - catch(const SettingNotFoundException &e) - { + catch(const SettingNotFoundException &e) { logPrintf(WARN, "No devices listed in config file."); return; } - for(int i = 0; i < devices->getLength(); i++) - { + for(int i = 0; i < devices->getLength(); i++) { const Setting &device = (*devices)[i]; std::string name; try { diff --git a/src/logid/Device.cpp b/src/logid/Device.cpp index da8746a..ba2949b 100644 --- a/src/logid/Device.cpp +++ b/src/logid/Device.cpp @@ -17,6 +17,7 @@ */ #include "util/log.h" +#include "features/DPI.h" #include "Device.h" using namespace logid; @@ -26,7 +27,7 @@ Device::Device(std::string path, backend::hidpp::DeviceIndex index) : _hidpp20 (path, index), _path (std::move(path)), _index (index), _config (global_config, this) { - ///TODO: Initialize features + _init(); } Device::Device(const std::shared_ptr& raw_device, @@ -34,7 +35,19 @@ Device::Device(const std::shared_ptr& raw_device, (raw_device->hidrawPath()), _index (index), _config (global_config, this) { - ///TODO: Initialize features + _init(); +} + +void Device::_init() +{ + ///TODO: Surely there's a better way of doing this + try { + _features.push_back(std::make_shared(this)); + } catch (backend::hidpp20::UnsupportedFeature& e) { + } + + for(auto& feature: _features) + feature->configure(); } std::string Device::name() @@ -62,7 +75,12 @@ DeviceConfig& Device::config() return _config; } -DeviceConfig::DeviceConfig(std::shared_ptr config, Device* +hidpp20::Device& Device::hidpp20() +{ + return _hidpp20; +} + +DeviceConfig::DeviceConfig(const std::shared_ptr& config, Device* device) : _device (device), _config (config) { try { @@ -73,7 +91,7 @@ DeviceConfig::DeviceConfig(std::shared_ptr config, Device* } } -std::string DeviceConfig::getSetting(std::string path) +libconfig::Setting& DeviceConfig::getSetting(std::string path) { - return _root_setting + '/' + path; + return _config->getSetting(_root_setting + '/' + path); } diff --git a/src/logid/Device.h b/src/logid/Device.h index 5b5fddd..d1226cb 100644 --- a/src/logid/Device.h +++ b/src/logid/Device.h @@ -31,8 +31,9 @@ namespace logid class DeviceConfig { public: - DeviceConfig(std::shared_ptr config, Device* device); - std::string getSetting(std::string path); + DeviceConfig(const std::shared_ptr& config, Device* + device); + libconfig::Setting& getSetting(std::string path); private: Device* _device; std::string _root_setting; @@ -54,10 +55,13 @@ namespace logid uint16_t pid(); DeviceConfig& config(); + backend::hidpp20::Device& hidpp20(); void wakeup(); void sleep(); private: + void _init(); + backend::hidpp20::Device _hidpp20; std::string _path; backend::hidpp::DeviceIndex _index; diff --git a/src/logid/features/DPI.cpp b/src/logid/features/DPI.cpp new file mode 100644 index 0000000..5d1bfd2 --- /dev/null +++ b/src/logid/features/DPI.cpp @@ -0,0 +1,114 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#include +#include +#include "DPI.h" +#include "../Device.h" +#include "../util/log.h" + +using namespace logid::features; +using namespace logid::backend; + +uint16_t getClosestDPI(hidpp20::AdjustableDPI::SensorDPIList& dpi_list, + uint16_t dpi) +{ + if(dpi_list.isRange) { + const uint16_t min = *std::min_element(dpi_list.dpis.begin(), + dpi_list.dpis.end()); + const uint16_t max = *std::max_element(dpi_list.dpis.begin(), + dpi_list.dpis.end()); + if(!((dpi-min) % dpi_list.dpiStep) && dpi >= min && dpi <= max) + return dpi; + else if(dpi > max) + return max; + else if(dpi < min) + return min; + else + return min + round((double)(dpi-min)/dpi_list.dpiStep)*dpi_list + .dpiStep; + } else { + if(std::find(dpi_list.dpis.begin(), dpi_list.dpis.end(), dpi) + != dpi_list.dpis.end()) + return dpi; + else { + auto it = std::min_element(dpi_list.dpis.begin(), dpi_list.dpis + .end(), [dpi](uint16_t a, uint16_t b) { + return (dpi - a) < (dpi - b); + }); + if(it == dpi_list.dpis.end()) + return 0; + else + return *it; + } + } +} + +DPI::DPI(Device* device) : DeviceFeature(device), _config (device), + _adjustable_dpi (&device->hidpp20()) +{ +} + +void DPI::configure() +{ + const uint8_t sensors = _adjustable_dpi.getSensorCount(); + for(uint8_t i = 0; i < _config.getSensorCount() && i < sensors; i++) { + auto dpi = _config.getDPI(i); + if(dpi) { + auto dpi_list = _adjustable_dpi.getSensorDPIList(i); + _adjustable_dpi.setSensorDPI(i, getClosestDPI(dpi_list, + dpi)); + } + } +} + +void DPI::listen() +{ +} + +/* Some devices have multiple sensors, but an older config format + * only supports a single DPI. The dpi setting can be an array or + * an integer. + */ +DPI::Config::Config(Device *dev) : DeviceFeature::Config(dev) +{ + try { + auto& config_root = dev->config().getSetting("dpi"); + if(config_root.isNumber()) { + int dpi = config_root; + _dpis.push_back(dpi); + } else if(config_root.isArray()) { + for(int i = 0; i < config_root.getLength(); i++) + _dpis.push_back((int)config_root[i]); + } else { + logPrintf(WARN, "Line %d: dpi is improperly formatted", + config_root.getSourceLine()); + } + } catch(libconfig::SettingNotFoundException& e) { + // DPI not configured, use default + } +} + +uint8_t DPI::Config::getSensorCount() +{ + return _dpis.size(); +} + +uint16_t DPI::Config::getDPI(uint8_t sensor) +{ + return _dpis[sensor]; +} diff --git a/src/logid/features/DPI.h b/src/logid/features/DPI.h new file mode 100644 index 0000000..5fa346f --- /dev/null +++ b/src/logid/features/DPI.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019-2020 PixlOne + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifndef LOGID_FEATURES_DPI_H +#define LOGID_FEATURES_DPI_H + +#include "../backend/hidpp20/features/AdjustableDPI.h" +#include "DeviceFeature.h" + +namespace logid { +namespace features +{ + class DPI : public DeviceFeature + { + public: + explicit DPI(Device* dev); + virtual void configure(); + virtual void listen(); + + class Config : public DeviceFeature::Config + { + public: + explicit Config(Device* dev); + uint16_t getDPI(uint8_t sensor); + uint8_t getSensorCount(); + protected: + std::vector _dpis; + }; + private: + Config _config; + backend::hidpp20::AdjustableDPI _adjustable_dpi; + }; + }} + +#endif //LOGID_FEATURE_DPI_H diff --git a/src/logid/features/DeviceFeature.h b/src/logid/features/DeviceFeature.h index f3ae122..5bccee1 100644 --- a/src/logid/features/DeviceFeature.h +++ b/src/logid/features/DeviceFeature.h @@ -19,6 +19,8 @@ #ifndef LOGID_FEATURES_DEVICEFEATURE_H #define LOGID_FEATURES_DEVICEFEATURE_H +#include + namespace logid { class Device; namespace features @@ -38,11 +40,10 @@ namespace features { } protected: - virtual const std::string configPath() = 0; Device* _device; - std::string root_setting; }; - private: + + protected: Device* _device; }; }}