feat: Add config parsing for profiles and layouts

This change adds new configuration parameters to support profile inputs
on Linux.
profile-support
nirenjan 2026-04-02 23:17:07 -07:00
parent 0fdcb725af
commit a3d9708d1e
11 changed files with 103 additions and 22 deletions

View File

View File

@ -54,6 +54,9 @@ exe_x52ctl = executable('x52ctl', 'x52ctl.c',
install_data('x52d.conf', install_data('x52d.conf',
install_dir: join_paths(get_option('sysconfdir'), 'x52d')) install_dir: join_paths(get_option('sysconfdir'), 'x52d'))
install_subdir('layouts.d',
install_dir: join_paths(get_option('sysconfdir'), 'x52d'))
test('daemon-communication', files('test_daemon_comm.py')[0], test('daemon-communication', files('test_daemon_comm.py')[0],
depends: [exe_x52d, exe_x52ctl], protocol: 'tap') depends: [exe_x52d, exe_x52ctl], protocol: 'tap')

View File

@ -120,6 +120,25 @@ CurveFactor=3
# you to push more to get any motion out of the virtual mouse. # you to push more to get any motion out of the virtual mouse.
Deadzone=0 Deadzone=0
######################################################################
# Layouts - only valid on Linux
######################################################################
[Layouts]
# Directory containing .layout files (character → HID key recipes).
Directory=/etc/x52d/layouts.d
######################################################################
# Keyboard (profile input mapping) - only valid on Linux
######################################################################
[Keyboard]
# Base layout name: loads <Directory>/<DefaultKeymap>.layout
DefaultKeymap=us
# Enabled=no disables keyboard emulation from profiles (virtual keyboard).
Enabled=yes
###################################################################### ######################################################################
# Profiles - only valid on Linux # Profiles - only valid on Linux
###################################################################### ######################################################################
@ -139,6 +158,9 @@ ClutchEnabled=no
# be held down to remain in clutch mode. # be held down to remain in clutch mode.
ClutchLatched=no ClutchLatched=no
# Axis band hysteresis: expand/shrink band edges by this percentage (0-50).
AxisHysteresisPercent=0
################## ##################
#X52 Input Servic# #X52 Input Servic#
#Version 0.3.3 # #Version 0.3.3 #

View File

@ -85,9 +85,13 @@ const char *x52d_config_get(const char *section, const char *key)
/* Callback stubs /* Callback stubs
* TODO: Remove the ones below when their implementation is complete * TODO: Remove the ones below when their implementation is complete
*/ */
void x52d_cfg_set_Layouts_Directory(char *param) { (void)param; }
void x52d_cfg_set_Keyboard_DefaultKeymap(char *param) { (void)param; }
void x52d_cfg_set_Keyboard_Enabled(bool param) { (void)param; }
void x52d_cfg_set_Profiles_Directory(char* param) { (void)param; } void x52d_cfg_set_Profiles_Directory(char* param) { (void)param; }
void x52d_cfg_set_Profiles_ClutchEnabled(bool param) { (void)param; } void x52d_cfg_set_Profiles_ClutchEnabled(bool param) { (void)param; }
void x52d_cfg_set_Profiles_ClutchLatched(bool param) { (void)param; } void x52d_cfg_set_Profiles_ClutchLatched(bool param) { (void)param; }
void x52d_cfg_set_Profiles_AxisHysteresisPercent(int param) { (void)param; }
void x52d_config_apply_immediate(const char *section, const char *key) void x52d_config_apply_immediate(const char *section, const char *key)
{ {

View File

@ -91,6 +91,22 @@ CFG(Mouse, CurveFactor, mouse_curve_factor, int, 3)
// Deadzone controls the deadzone range for the thumbstick // Deadzone controls the deadzone range for the thumbstick
CFG(Mouse, Deadzone, mouse_deadzone_factor, int, 0) CFG(Mouse, Deadzone, mouse_deadzone_factor, int, 0)
/**********************************************************************
* Layouts - keyboard layout files (.layout), only valid on Linux
*********************************************************************/
// Directory is the location of the folder containing layout maps
// (e.g. us.layout for DefaultKeymap=us).
CFG(Layouts, Directory, layouts_dir, string, /etc/x52d/layouts.d)
/**********************************************************************
* Keyboard / profile input mapping - only valid on Linux
*********************************************************************/
// DefaultKeymap selects layouts.d/<name>.layout (e.g. us -> us.layout).
CFG(Keyboard, DefaultKeymap, default_keymap, string, us)
// Enabled controls whether keyboard emulation from profiles is active.
CFG(Keyboard, Enabled, keyboard_enabled, bool, true)
/********************************************************************** /**********************************************************************
* Profiles - only valid on Linux * Profiles - only valid on Linux
*********************************************************************/ *********************************************************************/
@ -105,4 +121,8 @@ CFG(Profiles, ClutchEnabled, clutch_enabled, bool, false)
// be held down to remain in clutch mode. // be held down to remain in clutch mode.
CFG(Profiles, ClutchLatched, clutch_latched, bool, false) CFG(Profiles, ClutchLatched, clutch_latched, bool, false)
// AxisHysteresisPercent expands axis band boundaries by this percentage (0-50)
// to reduce chatter at band edges. Profiles may override per-profile.
CFG(Profiles, AxisHysteresisPercent, axis_hysteresis_percent, axis_hysteresis, 0)
#undef CFG #undef CFG

View File

@ -49,6 +49,10 @@ struct x52d_config {
bool clutch_latched; bool clutch_latched;
char profiles_dir[NAME_MAX]; char profiles_dir[NAME_MAX];
char layouts_dir[NAME_MAX];
char default_keymap[NAME_MAX];
bool keyboard_enabled;
int axis_hysteresis_percent;
}; };
/* Callback functions for configuration */ /* Callback functions for configuration */
@ -81,9 +85,13 @@ void x52d_cfg_set_Mouse_ReverseScroll(bool param);
void x52d_cfg_set_Mouse_IsometricMode(bool param); void x52d_cfg_set_Mouse_IsometricMode(bool param);
void x52d_cfg_set_Mouse_CurveFactor(int param); void x52d_cfg_set_Mouse_CurveFactor(int param);
void x52d_cfg_set_Mouse_Deadzone(int param); void x52d_cfg_set_Mouse_Deadzone(int param);
void x52d_cfg_set_Layouts_Directory(char *param);
void x52d_cfg_set_Keyboard_DefaultKeymap(char *param);
void x52d_cfg_set_Keyboard_Enabled(bool param);
void x52d_cfg_set_Profiles_Directory(char* param); void x52d_cfg_set_Profiles_Directory(char* param);
void x52d_cfg_set_Profiles_ClutchEnabled(bool param); void x52d_cfg_set_Profiles_ClutchEnabled(bool param);
void x52d_cfg_set_Profiles_ClutchLatched(bool param); void x52d_cfg_set_Profiles_ClutchLatched(bool param);
void x52d_cfg_set_Profiles_AxisHysteresisPercent(int param);
int x52d_config_process_kv(void *user, const char *section, const char *key, const char *value); int x52d_config_process_kv(void *user, const char *section, const char *key, const char *value);
const char *x52d_config_get_param(struct x52d_config *cfg, const char *section, const char *key); const char *x52d_config_get_param(struct x52d_config *cfg, const char *section, const char *key);

View File

@ -60,6 +60,11 @@ static const char * int_dumper(const char *section, const char *key, struct x52d
return dump; return dump;
} }
static const char * axis_hysteresis_dumper(const char *section, const char *key, struct x52d_config *cfg, size_t offset)
{
return int_dumper(section, key, cfg, offset);
}
static const char * led_dumper(const char *section, const char *key, struct x52d_config *cfg, size_t offset) static const char * led_dumper(const char *section, const char *key, struct x52d_config *cfg, size_t offset)
{ {
CONFIG_PTR(libx52_led_state *, config); CONFIG_PTR(libx52_led_state *, config);

View File

@ -80,6 +80,23 @@ static int int_parser(struct x52d_config *cfg, size_t offset, const char *value)
return 0; return 0;
} }
static int axis_hysteresis_parser(struct x52d_config *cfg, size_t offset, const char *value)
{
int rc;
rc = int_parser(cfg, offset, value);
if (rc != 0) {
return rc;
}
CONFIG_PTR(int *, config);
if (*config < 0 || *config > 50) {
return EINVAL;
}
return 0;
}
static int led_parser(struct x52d_config *cfg, size_t offset, const char *value) static int led_parser(struct x52d_config *cfg, size_t offset, const char *value)
{ {
CONFIG_PTR(libx52_led_state *, config); CONFIG_PTR(libx52_led_state *, config);

View File

@ -15,6 +15,8 @@
#define X52D_SYS_CFG_FILE SYSCONFDIR "/" X52D_APP_NAME "/" X52D_APP_NAME ".conf" #define X52D_SYS_CFG_FILE SYSCONFDIR "/" X52D_APP_NAME "/" X52D_APP_NAME ".conf"
#define X52D_SYS_LAYOUTS_DIR SYSCONFDIR "/" X52D_APP_NAME "/layouts.d"
#define X52D_PID_FILE RUNDIR "/" X52D_APP_NAME ".pid" #define X52D_PID_FILE RUNDIR "/" X52D_APP_NAME ".pid"
#define X52D_SOCK_COMMAND RUNDIR "/" X52D_APP_NAME ".cmd" #define X52D_SOCK_COMMAND RUNDIR "/" X52D_APP_NAME ".cmd"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: libx52 0.3.3\n" "Project-Id-Version: libx52 0.3.3\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
"POT-Creation-Date: 2026-04-01 20:47-0700\n" "POT-Creation-Date: 2026-04-02 23:18-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -752,50 +752,50 @@ msgstr ""
msgid "Error %d saving configuration file: %s" msgid "Error %d saving configuration file: %s"
msgstr "" msgstr ""
#: daemon/x52d_config_dump.c:108 #: daemon/x52d_config_dump.c:113
#, c-format #, c-format
msgid "Unable to save config file %s - code %d: %s" msgid "Unable to save config file %s - code %d: %s"
msgstr "" msgstr ""
#: daemon/x52d_config_dump.c:126 #: daemon/x52d_config_dump.c:131
#, c-format #, c-format
msgid "Failed to dump %s.%s to config file %s" msgid "Failed to dump %s.%s to config file %s"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:172 #: daemon/x52d_config_parser.c:189
#, c-format #, c-format
msgid "Ignoring unknown key '%s.%s'" msgid "Ignoring unknown key '%s.%s'"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:213 #: daemon/x52d_config_parser.c:230
#, c-format #, c-format
msgid "Failed processing configuration file %s - code %d" msgid "Failed processing configuration file %s - code %d"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:243 #: daemon/x52d_config_parser.c:260
msgid "Failed to allocate memory for override structure" msgid "Failed to allocate memory for override structure"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:252 #: daemon/x52d_config_parser.c:269
msgid "Failed to allocate memory for override string" msgid "Failed to allocate memory for override string"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:263 #: daemon/x52d_config_parser.c:280
#, c-format #, c-format
msgid "No section found in override string '%s'" msgid "No section found in override string '%s'"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:277 #: daemon/x52d_config_parser.c:294
#, c-format #, c-format
msgid "No key found in override string '%s'" msgid "No key found in override string '%s'"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:288 #: daemon/x52d_config_parser.c:305
#, c-format #, c-format
msgid "No value found in override string '%s'" msgid "No value found in override string '%s'"
msgstr "" msgstr ""
#: daemon/x52d_config_parser.c:339 #: daemon/x52d_config_parser.c:356
#, c-format #, c-format
msgid "Error processing override '%s.%s=%s'" msgid "Error processing override '%s.%s=%s'"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: libx52 0.2.3\n" "Project-Id-Version: libx52 0.2.3\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/libx52/issues\n"
"POT-Creation-Date: 2026-04-01 20:47-0700\n" "POT-Creation-Date: 2026-04-02 23:18-0700\n"
"PO-Revision-Date: 2026-04-01 20:50-0700\n" "PO-Revision-Date: 2026-04-01 20:50-0700\n"
"Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n" "Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n"
"Language-Team: Dummy Language for testing i18n\n" "Language-Team: Dummy Language for testing i18n\n"
@ -805,50 +805,50 @@ msgstr "Erroray %d ettingsay onfigurationcay efaultsday: %s"
msgid "Error %d saving configuration file: %s" msgid "Error %d saving configuration file: %s"
msgstr "Erroray %d avingsay onfigurationcay ilefay: %s" msgstr "Erroray %d avingsay onfigurationcay ilefay: %s"
#: daemon/x52d_config_dump.c:108 #: daemon/x52d_config_dump.c:113
#, c-format #, c-format
msgid "Unable to save config file %s - code %d: %s" msgid "Unable to save config file %s - code %d: %s"
msgstr "Unableay otay avesay onfigcay ilefay %s - odecay %d: %s" msgstr "Unableay otay avesay onfigcay ilefay %s - odecay %d: %s"
#: daemon/x52d_config_dump.c:126 #: daemon/x52d_config_dump.c:131
#, c-format #, c-format
msgid "Failed to dump %s.%s to config file %s" msgid "Failed to dump %s.%s to config file %s"
msgstr "Ailedfay otay umpday %s.%s otay onfigcay ilefay %s" msgstr "Ailedfay otay umpday %s.%s otay onfigcay ilefay %s"
#: daemon/x52d_config_parser.c:172 #: daemon/x52d_config_parser.c:189
#, c-format #, c-format
msgid "Ignoring unknown key '%s.%s'" msgid "Ignoring unknown key '%s.%s'"
msgstr "Ignoringay unknownay eykay '%s.%s'" msgstr "Ignoringay unknownay eykay '%s.%s'"
#: daemon/x52d_config_parser.c:213 #: daemon/x52d_config_parser.c:230
#, c-format #, c-format
msgid "Failed processing configuration file %s - code %d" msgid "Failed processing configuration file %s - code %d"
msgstr "Ailedfay ocessingpray onfigurationcay ilefay %s - odecay %d" msgstr "Ailedfay ocessingpray onfigurationcay ilefay %s - odecay %d"
#: daemon/x52d_config_parser.c:243 #: daemon/x52d_config_parser.c:260
msgid "Failed to allocate memory for override structure" msgid "Failed to allocate memory for override structure"
msgstr "Ailedfay otay allocateay emorymay orfay overrideay ucturestray" msgstr "Ailedfay otay allocateay emorymay orfay overrideay ucturestray"
#: daemon/x52d_config_parser.c:252 #: daemon/x52d_config_parser.c:269
msgid "Failed to allocate memory for override string" msgid "Failed to allocate memory for override string"
msgstr "Ailedfay otay allocateay emorymay orfay overrideay ingstray" msgstr "Ailedfay otay allocateay emorymay orfay overrideay ingstray"
#: daemon/x52d_config_parser.c:263 #: daemon/x52d_config_parser.c:280
#, c-format #, c-format
msgid "No section found in override string '%s'" msgid "No section found in override string '%s'"
msgstr "Onay ectionsay oundfay inay overrideay ingstray '%s'" msgstr "Onay ectionsay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:277 #: daemon/x52d_config_parser.c:294
#, c-format #, c-format
msgid "No key found in override string '%s'" msgid "No key found in override string '%s'"
msgstr "Onay eykay oundfay inay overrideay ingstray '%s'" msgstr "Onay eykay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:288 #: daemon/x52d_config_parser.c:305
#, c-format #, c-format
msgid "No value found in override string '%s'" msgid "No value found in override string '%s'"
msgstr "Onay aluevay oundfay inay overrideay ingstray '%s'" msgstr "Onay aluevay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:339 #: daemon/x52d_config_parser.c:356
#, c-format #, c-format
msgid "Error processing override '%s.%s=%s'" msgid "Error processing override '%s.%s=%s'"
msgstr "Erroray ocessingpray overriday '%s.%s=%s'" msgstr "Erroray ocessingpray overriday '%s.%s=%s'"