Split Configuration into several classes
Each feature should handle its own configuration.
This commit is contained in:
parent
181be50f88
commit
f6b93b94af
|
@ -14,6 +14,7 @@ add_executable(logid
|
||||||
DeviceManager.cpp
|
DeviceManager.cpp
|
||||||
Device.cpp
|
Device.cpp
|
||||||
Receiver.cpp
|
Receiver.cpp
|
||||||
|
Configuration.cpp
|
||||||
backend/Error.cpp
|
backend/Error.cpp
|
||||||
backend/raw/DeviceMonitor.cpp
|
backend/raw/DeviceMonitor.cpp
|
||||||
backend/raw/RawDevice.cpp
|
backend/raw/RawDevice.cpp
|
||||||
|
|
|
@ -16,521 +16,79 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstdint>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <linux/input-event-codes.h>
|
|
||||||
#include <libevdev/libevdev.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <hidpp20/IHiresScroll.h>
|
|
||||||
|
|
||||||
#include "Configuration.h"
|
#include "Configuration.h"
|
||||||
#include "util.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
using namespace logid;
|
using namespace logid;
|
||||||
using namespace libconfig;
|
using namespace libconfig;
|
||||||
|
|
||||||
Configuration::Configuration(const char *config_file)
|
Configuration::Configuration(const std::string& config_file)
|
||||||
{
|
{
|
||||||
//Read config file
|
try {
|
||||||
try
|
_config.readFile(config_file.c_str());
|
||||||
{
|
} catch(const FileIOException &e) {
|
||||||
cfg.readFile(config_file);
|
logPrintf(ERROR, "I/O Error while reading %s: %s", config_file.c_str(),
|
||||||
}
|
e.what());
|
||||||
catch(const FileIOException &e)
|
throw e;
|
||||||
{
|
} catch(const ParseException &e) {
|
||||||
log_printf(ERROR, "I/O Error while reading %s: %s", config_file, e.what());
|
logPrintf(ERROR, "Parse error in %s, line %d: %s", e.getFile(),
|
||||||
|
e.getLine(), e.getError());
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
catch(const ParseException &e)
|
|
||||||
{
|
|
||||||
log_printf(ERROR, "Parse error in %s, line %d: %s", e.getFile(), e.getLine(), e.getError());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
const Setting &root = cfg.getRoot();
|
|
||||||
|
|
||||||
try
|
const Setting &root = _config.getRoot();
|
||||||
{
|
Setting* devices;
|
||||||
auto& _blacklist = root.lookup("blacklist");
|
|
||||||
if(_blacklist.isArray() || _blacklist.isList())
|
try { devices = &root["devices"]; }
|
||||||
{
|
|
||||||
int len = _blacklist.getLength();
|
|
||||||
for(int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
if(!_blacklist[i].isNumber()) {
|
|
||||||
log_printf(WARN, "Line %d: blacklist must only contain "
|
|
||||||
"PIDs", _blacklist[i].getSourceLine());
|
|
||||||
if(_blacklist.isArray())
|
|
||||||
break;
|
|
||||||
if(_blacklist.isList())
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
blacklist.push_back((int)_blacklist[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: blacklist must be an array or list, "
|
|
||||||
"ignnoring.", _blacklist.getSourceLine());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e)
|
catch(const SettingNotFoundException &e)
|
||||||
{
|
{
|
||||||
}
|
logPrintf(WARN, "No devices listed in config file.");
|
||||||
|
|
||||||
Setting* _devices;
|
|
||||||
|
|
||||||
try { _devices = &root["devices"]; }
|
|
||||||
catch(const SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "No devices listed in config file.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < _devices->getLength(); i++)
|
for(int i = 0; i < devices->getLength(); i++)
|
||||||
{
|
{
|
||||||
const Setting &device = (*_devices)[i];
|
const Setting &device = (*devices)[i];
|
||||||
std::string name;
|
std::string name;
|
||||||
try
|
try {
|
||||||
{
|
if(!device.lookupValue("name", name)) {
|
||||||
if(!device.lookupValue("name", name))
|
logPrintf(WARN, "Line %d: 'name' must be a string, skipping "
|
||||||
{
|
"device.", device["name"].getSourceLine());
|
||||||
log_printf(WARN, "Line %d: 'name' must be a string, skipping device.", device["name"].getSourceLine());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
} catch(SettingNotFoundException &e) {
|
||||||
catch(SettingNotFoundException &e)
|
logPrintf(WARN, "Line %d: Missing 'name' field, skipping device."
|
||||||
{
|
, device.getSourceLine());
|
||||||
log_printf(WARN, "Line %d: Missing 'name' field, skipping device.", device.getSourceLine());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
devices.insert({name, new DeviceConfig(device)});
|
_device_paths.insert({name, device.getPath()});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceConfig::DeviceConfig(const libconfig::Setting &root)
|
libconfig::Setting& Configuration::getSetting(std::string path)
|
||||||
{
|
{
|
||||||
try
|
return _config.lookup(path);
|
||||||
{
|
|
||||||
int d;
|
|
||||||
if(!root.lookupValue("dpi", d))
|
|
||||||
throw SettingTypeException(root["dpi"]);
|
|
||||||
dpi = new int(d);
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e) { }
|
|
||||||
catch(const SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: DPI must me an integer; not setting.", root["dpi"].getSourceLine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
std::string Configuration::getDevice(std::string name)
|
||||||
{
|
{
|
||||||
const Setting& hr = root["hiresscroll"];
|
auto it = _device_paths.find(name);
|
||||||
uint8_t hss = 0;
|
if(it == _device_paths.end())
|
||||||
try
|
throw DeviceNotFound(name);
|
||||||
{
|
else
|
||||||
bool b;
|
return it->second;
|
||||||
if(!hr.lookupValue("hires", b))
|
|
||||||
throw SettingTypeException(root["hires"]);
|
|
||||||
if(b) hss |= HIDPP20::IHiresScroll::HiRes;
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e) { }
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Line %d: hires field must be a boolean", hr["hires"].getSourceLine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
Configuration::DeviceNotFound::DeviceNotFound(std::string name) :
|
||||||
|
_name (std::move(name))
|
||||||
{
|
{
|
||||||
bool b;
|
|
||||||
if(!hr.lookupValue("invert", b))
|
|
||||||
throw SettingTypeException(root["invert"]);
|
|
||||||
if(b) hss |= HIDPP20::IHiresScroll::Inverted;
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e) { }
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Line %d: invert field must be a boolean", hr["invert"].getSourceLine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
const char * Configuration::DeviceNotFound::what()
|
||||||
{
|
{
|
||||||
bool b;
|
return _name.c_str();
|
||||||
if(!hr.lookupValue("target", b))
|
|
||||||
throw SettingTypeException(root["target"]);
|
|
||||||
if(b) hss |= HIDPP20::IHiresScroll::Target;
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e) { }
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Line %d: target field must be a boolean", hr["target"].getSourceLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
hiresscroll = new uint8_t(hss);
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Missing hiresscroll option, not setting.");
|
|
||||||
}
|
|
||||||
catch(const SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: hiresscroll should be an object", root["hiresscroll"].getSourceLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const Setting& ss = root["smartshift"];
|
|
||||||
smartshift = new HIDPP20::ISmartShift::SmartshiftStatus {};
|
|
||||||
bool on;
|
|
||||||
int threshold;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (ss.lookupValue("on", on)) smartshift->Active = new bool(on);
|
|
||||||
else log_printf(WARN, "Line %d: on field must be a boolean", ss["on"].getSourceLine());
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e) { }
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (ss.lookupValue("threshold", threshold))
|
|
||||||
{
|
|
||||||
if(threshold < 0)
|
|
||||||
{
|
|
||||||
threshold = 1;
|
|
||||||
log_printf(INFO, "Smartshift threshold must be > 0 or < 100, setting to 1.");
|
|
||||||
}
|
|
||||||
if(threshold >= 100)
|
|
||||||
{
|
|
||||||
threshold = 99;
|
|
||||||
log_printf(INFO, "Smartshift threshold must be > 0 or < 100, setting to 99.");
|
|
||||||
}
|
|
||||||
smartshift->AutoDisengage = new uint8_t(threshold);
|
|
||||||
smartshift->DefaultAutoDisengage = new uint8_t(threshold);
|
|
||||||
}
|
|
||||||
else log_printf(WARN, "Line %d: threshold must be an integer", ss["threshold"].getSourceLine());
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e) { }
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e) { }
|
|
||||||
catch(const SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: smartshift field must be an object", root["smartshift"].getSourceLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
Setting* buttons;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
buttons = &root["buttons"];
|
|
||||||
}
|
|
||||||
catch(const SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "No button configuration found, reverting to null config.");
|
|
||||||
new std::map<uint16_t, ButtonAction*>();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < buttons->getLength(); i++)
|
|
||||||
{
|
|
||||||
const Setting &button = (*buttons)[i];
|
|
||||||
|
|
||||||
int cid;
|
|
||||||
try { button.lookupValue("cid", cid); }
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Entry on line %d is missing a cid", button.getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(actions.find(cid) != actions.end())
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Duplicate entries for cid 0x%x, skipping entry on line %d", cid, button.getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Setting* action_config;
|
|
||||||
try { action_config = &button["action"]; }
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "cid 0x%x is missing an action, not diverting!", cid);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Action action_type;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string action_type_str;
|
|
||||||
action_config->lookupValue("type", action_type_str);
|
|
||||||
action_type = stringToAction(action_type_str);
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "cid 0x%x is missing an action type, not diverting!", cid);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(std::invalid_argument &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: %s", (*action_config)["type"].getSourceLine(), e.what());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try { actions.insert({cid, parse_action(action_type, action_config)}); }
|
|
||||||
catch(std::exception &e) { log_printf(ERROR, "%s", e.what()); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonAction* logid::parse_action(Action type, const Setting* action_config, bool is_gesture)
|
|
||||||
{
|
|
||||||
if(type == Action::None) return new NoAction();
|
|
||||||
if(type == Action::Keypress)
|
|
||||||
{
|
|
||||||
std::vector<unsigned int> keys;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const Setting &keys_config = (*action_config)["keys"];
|
|
||||||
for (int i = 0; i < keys_config.getLength(); i++)
|
|
||||||
{
|
|
||||||
int keycode = libevdev_event_code_from_name(EV_KEY, keys_config[i]);
|
|
||||||
if(keycode == -1)
|
|
||||||
{
|
|
||||||
const char* keyname = keys_config[i];
|
|
||||||
log_printf(WARN, "%s is not a valid keycode, skipping", keyname);
|
|
||||||
}
|
|
||||||
else keys.push_back(keycode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Expected keys parameter on line %d", action_config->getSourceLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new KeyAction(keys);
|
|
||||||
}
|
|
||||||
else if(type == Action::Gestures)
|
|
||||||
{
|
|
||||||
if(is_gesture)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: Recursive gesture, defaulting to no action.", action_config->getSourceLine());
|
|
||||||
return new NoAction();
|
|
||||||
}
|
|
||||||
std::map<Direction, Gesture*> gestures;
|
|
||||||
|
|
||||||
Setting* gestures_config;
|
|
||||||
|
|
||||||
try { gestures_config = &(*action_config)["gestures"]; }
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "No gestures parameter for line %d, skipping", action_config->getSourceLine());
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < gestures_config->getLength(); i++)
|
|
||||||
{
|
|
||||||
const Setting &gesture_config = (*gestures_config)[i];
|
|
||||||
|
|
||||||
std::string direction_str;
|
|
||||||
Direction direction;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
gesture_config.lookupValue("direction", direction_str);
|
|
||||||
direction = stringToDirection(direction_str);
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "No direction set on line %d", gesture_config.getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(std::invalid_argument &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: %s", gesture_config["direction"].getSourceLine(), e.what());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(gestures.find(direction) != gestures.end())
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Entry on line %d is a duplicate, skipping...", gesture_config["direction"].getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GestureMode mode;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string mode_str;
|
|
||||||
gesture_config.lookupValue("mode", mode_str);
|
|
||||||
mode = stringToGestureMode(mode_str);
|
|
||||||
}
|
|
||||||
catch (SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Gesture mode on line %d not found, defaulting to OnRelease", gesture_config.getSourceLine());
|
|
||||||
mode = GestureMode::OnRelease;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == GestureMode::NoPress)
|
|
||||||
{
|
|
||||||
gestures.insert({direction, new Gesture(new NoAction(), mode)});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mode == GestureMode::Axis)
|
|
||||||
{
|
|
||||||
Gesture::axis_info axis;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string axis_str;
|
|
||||||
if(!gesture_config.lookupValue("axis", axis_str))
|
|
||||||
throw SettingTypeException(gesture_config["axis"]);
|
|
||||||
axis.code = libevdev_event_code_from_name(EV_REL, axis_str.c_str());
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: No axis found, defaulting to no action.", gesture_config.getSourceLine());
|
|
||||||
gestures.insert({direction, new Gesture(new NoAction(), GestureMode::NoPress)});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: Axis must be a string (e.g. 'REL_WHEEL')", gesture_config["axis"].getSourceLine());
|
|
||||||
gestures.insert({direction, new Gesture(new NoAction(), GestureMode::NoPress)});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
axis.multiplier = 1;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if(!gesture_config.lookupValue("axis_multiplier", axis.multiplier))
|
|
||||||
{
|
|
||||||
int im = 1;
|
|
||||||
if(!gesture_config.lookupValue("axis_multiplier", im))
|
|
||||||
throw SettingTypeException(gesture_config["axis_multiplier"]);
|
|
||||||
axis.multiplier = (float)im;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e) { }
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: axis_multiplier must be a float/integer", gesture_config["axis_multiplier"].getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gestures.insert({direction, new Gesture(new NoAction(), GestureMode::Axis, &axis)});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Setting* g_action;
|
|
||||||
try { g_action = &gesture_config["action"]; }
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "No action set for %s", direction_str.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Action g_type;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::string type_str;
|
|
||||||
g_action->lookupValue("type", type_str);
|
|
||||||
g_type = stringToAction(type_str);
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(INFO, "Missing an action type on line %d, skipping", g_action->getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
catch(std::invalid_argument &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: %s", (*g_action)["type"].getSourceLine(), e.what());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonAction* ba;
|
|
||||||
|
|
||||||
try { ba = parse_action(g_type, g_action, true); }
|
|
||||||
catch(std::exception &e) { continue; }
|
|
||||||
|
|
||||||
if(mode == GestureMode::OnFewPixels)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int pp;
|
|
||||||
if(!gesture_config.lookupValue("pixels", pp))
|
|
||||||
throw SettingTypeException(gesture_config["pixels"]);
|
|
||||||
gestures.insert({direction, new Gesture(ba, mode, &pp)});
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: OnFewPixels requires a 'pixels' field.", gesture_config.getSourceLine());
|
|
||||||
}
|
|
||||||
catch(SettingTypeException &e)
|
|
||||||
{
|
|
||||||
log_printf(WARN, "Line %d: pixels must be an integer", gesture_config["pixels"].getSourceLine());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else gestures.insert({direction, new Gesture(ba, mode)});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GestureAction(gestures);
|
|
||||||
}
|
|
||||||
else if(type == Action::ToggleSmartshift) return new SmartshiftAction();
|
|
||||||
else if(type == Action::ToggleHiresScroll) return new HiresScrollAction();
|
|
||||||
else if(type == Action::CycleDPI)
|
|
||||||
{
|
|
||||||
std::vector<int> dpis;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
const Setting &keys_config = (*action_config)["dpis"];
|
|
||||||
for (int i = 0; i < keys_config.getLength(); i++)
|
|
||||||
{
|
|
||||||
dpis.push_back((int)keys_config[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(ERROR, "Line %d: CycleDPI action is missing 'dpis' field, defaulting to NoAction.", action_config->getSourceLine());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CycleDPIAction(dpis);
|
|
||||||
}
|
|
||||||
else if(type == Action::ChangeDPI)
|
|
||||||
{
|
|
||||||
int inc;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
action_config->lookupValue("inc", inc);
|
|
||||||
}
|
|
||||||
catch(SettingNotFoundException &e)
|
|
||||||
{
|
|
||||||
log_printf(ERROR, "Line %d: ChangeDPI action is missing an 'inc' field, defaulting to NoAction.",action_config->getSourceLine());
|
|
||||||
return new NoAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ChangeDPIAction(inc);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_printf(ERROR, "This shouldn't have happened. Unhandled action type? Defaulting to NoAction");
|
|
||||||
return new NoAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceConfig::DeviceConfig(DeviceConfig* dc, Device* dev) : baseConfig (false)
|
|
||||||
{
|
|
||||||
dpi = dc->dpi;
|
|
||||||
smartshift = dc->smartshift;
|
|
||||||
hiresscroll = dc->hiresscroll;
|
|
||||||
for(auto it : dc->actions)
|
|
||||||
actions.insert( { it.first, it.second->copy(dev) } );
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceConfig::DeviceConfig()
|
|
||||||
{
|
|
||||||
dpi = nullptr;
|
|
||||||
hiresscroll = nullptr;
|
|
||||||
smartshift = nullptr;
|
|
||||||
actions = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceConfig::~DeviceConfig()
|
|
||||||
{
|
|
||||||
for(auto it : this->actions)
|
|
||||||
delete(it.second);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,43 +21,32 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <libconfig.h++>
|
#include <libconfig.h++>
|
||||||
#include <hidpp20/ISmartShift.h>
|
#include <memory>
|
||||||
#include "Actions.h"
|
|
||||||
|
|
||||||
namespace logid
|
namespace logid
|
||||||
{
|
{
|
||||||
class DeviceConfig;
|
|
||||||
class ButtonAction;
|
|
||||||
enum class Action;
|
|
||||||
|
|
||||||
class DeviceConfig
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DeviceConfig();
|
|
||||||
~DeviceConfig();
|
|
||||||
DeviceConfig(DeviceConfig* dc, Device* dev);
|
|
||||||
DeviceConfig(const libconfig::Setting& root);
|
|
||||||
const int* dpi = nullptr;
|
|
||||||
HIDPP20::ISmartShift::SmartshiftStatus* smartshift = nullptr;
|
|
||||||
const uint8_t* hiresscroll = nullptr;
|
|
||||||
std::map<uint16_t, ButtonAction*> actions;
|
|
||||||
const bool baseConfig = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Configuration
|
class Configuration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Configuration(const char* config_file);
|
explicit Configuration(const std::string& config_file);
|
||||||
Configuration() {}
|
Configuration() = default;
|
||||||
std::map<std::string, DeviceConfig*> devices;
|
libconfig::Setting& getSetting(std::string path);
|
||||||
std::vector<uint16_t> blacklist;
|
std::string getDevice(std::string name);
|
||||||
|
|
||||||
|
class DeviceNotFound : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit DeviceNotFound(std::string name);
|
||||||
|
virtual const char* what();
|
||||||
private:
|
private:
|
||||||
libconfig::Config cfg;
|
std::string _name;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> _device_paths;
|
||||||
|
libconfig::Config _config;
|
||||||
};
|
};
|
||||||
|
|
||||||
ButtonAction* parse_action(Action action, const libconfig::Setting* action_config, bool is_gesture=false);
|
extern std::shared_ptr<Configuration> global_config;
|
||||||
|
|
||||||
extern Configuration* global_config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //LOGID_CONFIGURATION_H
|
#endif //LOGID_CONFIGURATION_H
|
|
@ -23,16 +23,28 @@ using namespace logid;
|
||||||
using namespace logid::backend;
|
using namespace logid::backend;
|
||||||
|
|
||||||
Device::Device(std::string path, backend::hidpp::DeviceIndex index) :
|
Device::Device(std::string path, backend::hidpp::DeviceIndex index) :
|
||||||
_hidpp20 (path, index), _path (std::move(path)), _index (index)
|
_hidpp20 (path, index), _path (std::move(path)), _index (index),
|
||||||
|
_config (global_config, this)
|
||||||
{
|
{
|
||||||
logPrintf(DEBUG, "logid::Device created on %s:%d", _path.c_str(), _index);
|
///TODO: Initialize features
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
Device::Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
||||||
hidpp::DeviceIndex index) : _hidpp20(raw_device, index), _path
|
hidpp::DeviceIndex index) : _hidpp20(raw_device, index), _path
|
||||||
(raw_device->hidrawPath()), _index (index)
|
(raw_device->hidrawPath()), _index (index),
|
||||||
|
_config (global_config, this)
|
||||||
{
|
{
|
||||||
logPrintf(DEBUG, "logid::Device created on %s:%d", _path.c_str(), _index);
|
///TODO: Initialize features
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Device::name()
|
||||||
|
{
|
||||||
|
return _hidpp20.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Device::pid()
|
||||||
|
{
|
||||||
|
return _hidpp20.pid();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::sleep()
|
void Device::sleep()
|
||||||
|
@ -44,3 +56,24 @@ void Device::wakeup()
|
||||||
{
|
{
|
||||||
logPrintf(INFO, "%s:%d woke up.", _path.c_str(), _index);
|
logPrintf(INFO, "%s:%d woke up.", _path.c_str(), _index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceConfig& Device::config()
|
||||||
|
{
|
||||||
|
return _config;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceConfig::DeviceConfig(std::shared_ptr<Configuration> config, Device*
|
||||||
|
device) : _device (device), _config (config)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
_root_setting = config->getDevice(device->name());
|
||||||
|
} catch(Configuration::DeviceNotFound& e) {
|
||||||
|
logPrintf(INFO, "Device %s not configured, using default config.",
|
||||||
|
device->name().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DeviceConfig::getSetting(std::string path)
|
||||||
|
{
|
||||||
|
return _root_setting + '/' + path;
|
||||||
|
}
|
||||||
|
|
|
@ -22,9 +22,23 @@
|
||||||
#include "backend/hidpp/defs.h"
|
#include "backend/hidpp/defs.h"
|
||||||
#include "backend/hidpp20/Device.h"
|
#include "backend/hidpp20/Device.h"
|
||||||
#include "features/DeviceFeature.h"
|
#include "features/DeviceFeature.h"
|
||||||
|
#include "Configuration.h"
|
||||||
|
|
||||||
namespace logid
|
namespace logid
|
||||||
{
|
{
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
class DeviceConfig
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DeviceConfig(std::shared_ptr<Configuration> config, Device* device);
|
||||||
|
std::string getSetting(std::string path);
|
||||||
|
private:
|
||||||
|
Device* _device;
|
||||||
|
std::string _root_setting;
|
||||||
|
std::shared_ptr<Configuration> _config;
|
||||||
|
};
|
||||||
|
|
||||||
/* TODO: Implement HID++ 1.0 support
|
/* TODO: Implement HID++ 1.0 support
|
||||||
* Currently, the logid::Device class has a hardcoded requirement
|
* Currently, the logid::Device class has a hardcoded requirement
|
||||||
* for an HID++ 2.0 device.
|
* for an HID++ 2.0 device.
|
||||||
|
@ -35,6 +49,12 @@ namespace logid
|
||||||
Device(std::string path, backend::hidpp::DeviceIndex index);
|
Device(std::string path, backend::hidpp::DeviceIndex index);
|
||||||
Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
Device(const std::shared_ptr<backend::raw::RawDevice>& raw_device,
|
||||||
backend::hidpp::DeviceIndex index);
|
backend::hidpp::DeviceIndex index);
|
||||||
|
|
||||||
|
std::string name();
|
||||||
|
uint16_t pid();
|
||||||
|
|
||||||
|
DeviceConfig& config();
|
||||||
|
|
||||||
void wakeup();
|
void wakeup();
|
||||||
void sleep();
|
void sleep();
|
||||||
private:
|
private:
|
||||||
|
@ -42,6 +62,7 @@ namespace logid
|
||||||
std::string _path;
|
std::string _path;
|
||||||
backend::hidpp::DeviceIndex _index;
|
backend::hidpp::DeviceIndex _index;
|
||||||
std::vector<std::shared_ptr<features::DeviceFeature>> _features;
|
std::vector<std::shared_ptr<features::DeviceFeature>> _features;
|
||||||
|
DeviceConfig _config;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,16 @@ Report Device::sendReport(Report& report)
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Device::name() const
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Device::pid() const
|
||||||
|
{
|
||||||
|
return _pid;
|
||||||
|
}
|
||||||
|
|
||||||
void Device::listen()
|
void Device::listen()
|
||||||
{
|
{
|
||||||
if(!_raw_device->isListening())
|
if(!_raw_device->isListening())
|
||||||
|
|
|
@ -72,6 +72,9 @@ namespace hidpp
|
||||||
DeviceIndex deviceIndex() const;
|
DeviceIndex deviceIndex() const;
|
||||||
std::tuple<uint8_t, uint8_t> version() const;
|
std::tuple<uint8_t, uint8_t> version() const;
|
||||||
|
|
||||||
|
std::string name() const;
|
||||||
|
uint16_t pid() const;
|
||||||
|
|
||||||
void listen(); // Runs asynchronously
|
void listen(); // Runs asynchronously
|
||||||
void stopListening();
|
void stopListening();
|
||||||
|
|
||||||
|
|
|
@ -20,13 +20,30 @@
|
||||||
#define LOGID_FEATURES_DEVICEFEATURE_H
|
#define LOGID_FEATURES_DEVICEFEATURE_H
|
||||||
|
|
||||||
namespace logid {
|
namespace logid {
|
||||||
|
class Device;
|
||||||
namespace features
|
namespace features
|
||||||
{
|
{
|
||||||
class DeviceFeature
|
class DeviceFeature
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
explicit DeviceFeature(Device* dev) : _device (dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
virtual void configure() = 0;
|
virtual void configure() = 0;
|
||||||
virtual void listen() = 0;
|
virtual void listen() = 0;
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Config(Device* dev) : _device (dev)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
virtual const std::string configPath() = 0;
|
||||||
|
Device* _device;
|
||||||
|
std::string root_setting;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
Device* _device;
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ using namespace logid;
|
||||||
std::string config_file = DEFAULT_CONFIG_FILE;
|
std::string config_file = DEFAULT_CONFIG_FILE;
|
||||||
|
|
||||||
LogLevel logid::global_loglevel = INFO;
|
LogLevel logid::global_loglevel = INFO;
|
||||||
// Configuration* logid::global_config;
|
std::shared_ptr<Configuration> logid::global_config;
|
||||||
std::unique_ptr<DeviceManager> logid::device_manager;
|
std::unique_ptr<DeviceManager> logid::device_manager;
|
||||||
|
|
||||||
bool logid::kill_logid = false;
|
bool logid::kill_logid = false;
|
||||||
|
@ -155,12 +155,15 @@ int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
readCliOptions(argc, argv);
|
readCliOptions(argc, argv);
|
||||||
|
|
||||||
/*
|
|
||||||
// Read config
|
// Read config
|
||||||
try { global_config = new Configuration(config_file.c_str()); }
|
try {
|
||||||
catch (std::exception &e) { global_config = new Configuration(); }
|
global_config = std::make_shared<Configuration>(config_file);
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
global_config = std::make_shared<Configuration>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
//Create an evdev device called 'logid'
|
//Create an evdev device called 'logid'
|
||||||
try { global_evdev = new EvdevDevice(evdev_name); }
|
try { global_evdev = new EvdevDevice(evdev_name); }
|
||||||
catch(std::system_error& e)
|
catch(std::system_error& e)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user