From 6cdaeaaae1d864c59ce010d7abb24a7dc0d21fad Mon Sep 17 00:00:00 2001 From: Karel Tucek Date: Mon, 9 Feb 2026 14:02:53 +0100 Subject: [PATCH 1/2] Add missing secondary role settings to user config (version 14) Serialize 4 new secondary role advanced strategy fields that were previously only settable via macro set commands: TriggerByMouse, AcceptTriggersFromSameHalf, MinimumHoldTime, and TimeoutType. Also reinterpret TriggeringEvent as UInt8 (was Bool) to support the None value, and add NoOp to the TimeoutAction enum. Co-Authored-By: Claude Opus 4.6 --- right/src/config_parser/parse_config.c | 32 +++++++++++++++++++++++++- right/src/config_parser/parse_config.h | 1 + scripts/package.json | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/right/src/config_parser/parse_config.c b/right/src/config_parser/parse_config.c index 934565eb8..83ec28afa 100644 --- a/right/src/config_parser/parse_config.c +++ b/right/src/config_parser/parse_config.c @@ -185,12 +185,21 @@ parser_error_t parseConfig(config_buffer_t *buffer) bool secondaryRoles_AdvancedStrategyDoubletapToPrimary = Cfg.SecondaryRoles_AdvancedStrategyDoubletapToPrimary; serialized_secondary_role_action_type_t secondaryRoles_AdvancedStrategyTimeoutAction = SerializedSecondaryRoleActionType_Secondary; + bool secondaryRoles_AdvancedStrategyTriggerByMouse = Cfg.SecondaryRoles_AdvancedStrategyTriggerByMouse; + bool secondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf = Cfg.SecondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf; + uint8_t secondaryRoles_AdvancedStrategyMinimumHoldTime = Cfg.SecondaryRoles_AdvancedStrategyMinimumHoldTime; + secondary_role_timeout_type_t secondaryRoles_AdvancedStrategyTimeoutType = Cfg.SecondaryRoles_AdvancedStrategyTimeoutType; + if (DataModelVersion.major >= 7) { secondaryRoles_Strategy = ReadUInt8(buffer); ATTR_UNUSED uint16_t secondaryRoles_AdvancedStrategyDoubletapTimeout = ReadUInt16(buffer); secondaryRoles_AdvancedStrategyTimeout = ReadUInt16(buffer); secondaryRoles_AdvancedStrategySafetyMargin = ReadInt16(buffer); - secondaryRoles_AdvancedStrategyTriggeringEvent = ReadBool(buffer) ? SecondaryRoleTriggeringEvent_Release : SecondaryRoleTriggeringEvent_Press; + if (DataModelVersion.major >= 14) { + secondaryRoles_AdvancedStrategyTriggeringEvent = ReadUInt8(buffer); + } else { + secondaryRoles_AdvancedStrategyTriggeringEvent = ReadBool(buffer) ? SecondaryRoleTriggeringEvent_Release : SecondaryRoleTriggeringEvent_Press; + } secondaryRoles_AdvancedStrategyDoubletapToPrimary = ReadBool(buffer); secondaryRoles_AdvancedStrategyTimeoutAction = ReadUInt8(buffer); @@ -243,6 +252,15 @@ parser_error_t parseConfig(config_buffer_t *buffer) batteryChargingMode = ReadUInt8(buffer); } + // Version 14: + + if (DataModelVersion.major >= 14) { + secondaryRoles_AdvancedStrategyTriggerByMouse = ReadBool(buffer); + secondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf = ReadBool(buffer); + secondaryRoles_AdvancedStrategyMinimumHoldTime = ReadUInt8(buffer); + secondaryRoles_AdvancedStrategyTimeoutType = ReadUInt8(buffer); + } + // HostConnection configuration if (VERSION_AT_LEAST(DataModelVersion, 8, 1, 0)) { @@ -356,6 +374,9 @@ parser_error_t parseConfig(config_buffer_t *buffer) case SerializedSecondaryRoleActionType_Secondary: Cfg.SecondaryRoles_AdvancedStrategyTimeoutAction = SecondaryRoleState_Secondary; break; + case SerializedSecondaryRoleActionType_NoOp: + Cfg.SecondaryRoles_AdvancedStrategyTimeoutAction = SecondaryRoleState_NoOp; + break; default: ConfigParser_Error(buffer, "Invalid secondary role action type: %u", secondaryRoles_AdvancedStrategyTimeoutAction); return ParserError_InvalidSecondaryRoleActionType; @@ -369,6 +390,15 @@ parser_error_t parseConfig(config_buffer_t *buffer) Cfg.KeystrokeDelay = keystrokeDelay; } + // Version 14 + + if (DataModelVersion.major >= 14) { + Cfg.SecondaryRoles_AdvancedStrategyTriggerByMouse = secondaryRoles_AdvancedStrategyTriggerByMouse; + Cfg.SecondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf = secondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf; + Cfg.SecondaryRoles_AdvancedStrategyMinimumHoldTime = secondaryRoles_AdvancedStrategyMinimumHoldTime; + Cfg.SecondaryRoles_AdvancedStrategyTimeoutType = secondaryRoles_AdvancedStrategyTimeoutType; + } + // Version 8 diff --git a/right/src/config_parser/parse_config.h b/right/src/config_parser/parse_config.h index 7342925c3..7be8fe61d 100644 --- a/right/src/config_parser/parse_config.h +++ b/right/src/config_parser/parse_config.h @@ -46,6 +46,7 @@ typedef enum { SerializedSecondaryRoleActionType_Primary, SerializedSecondaryRoleActionType_Secondary, + SerializedSecondaryRoleActionType_NoOp, } serialized_secondary_role_action_type_t; typedef enum { diff --git a/scripts/package.json b/scripts/package.json index c153ffb4a..783b9a777 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -22,7 +22,7 @@ "deviceProtocolVersion": "4.17.0", "moduleProtocolVersion": "4.3.0", "dongleProtocolVersion": "1.0.2", - "userConfigVersion": "13.0.0", + "userConfigVersion": "14.0.0", "hardwareConfigVersion": "1.0.0", "smartMacrosVersion": "3.13.0", "devices": [ From d47c3a0561c068f97e981b88d184bd849e6676be Mon Sep 17 00:00:00 2001 From: Karel Tucek Date: Mon, 9 Feb 2026 14:27:59 +0100 Subject: [PATCH 2/2] ParseConfig: use explicit serialization enums for secondary roles. --- right/src/config_parser/parse_config.c | 37 +++++++++++++++++++------- right/src/config_parser/parse_config.h | 13 +++++++++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/right/src/config_parser/parse_config.c b/right/src/config_parser/parse_config.c index 83ec28afa..4456be6df 100644 --- a/right/src/config_parser/parse_config.c +++ b/right/src/config_parser/parse_config.c @@ -181,25 +181,21 @@ parser_error_t parseConfig(config_buffer_t *buffer) secondary_role_strategy_t secondaryRoles_Strategy = SecondaryRoleStrategy_Simple; uint16_t secondaryRoles_AdvancedStrategyTimeout = Cfg.SecondaryRoles_AdvancedStrategyTimeout; int16_t secondaryRoles_AdvancedStrategySafetyMargin = Cfg.SecondaryRoles_AdvancedStrategySafetyMargin; - secondary_role_triggering_event_t secondaryRoles_AdvancedStrategyTriggeringEvent = Cfg.SecondaryRoles_AdvancedStrategyTriggeringEvent; + serialized_secondary_role_triggering_event_t secondaryRoles_AdvancedStrategyTriggeringEvent = SerializedSecondaryRoleTriggeringEvent_Release; bool secondaryRoles_AdvancedStrategyDoubletapToPrimary = Cfg.SecondaryRoles_AdvancedStrategyDoubletapToPrimary; serialized_secondary_role_action_type_t secondaryRoles_AdvancedStrategyTimeoutAction = SerializedSecondaryRoleActionType_Secondary; bool secondaryRoles_AdvancedStrategyTriggerByMouse = Cfg.SecondaryRoles_AdvancedStrategyTriggerByMouse; bool secondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf = Cfg.SecondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf; uint8_t secondaryRoles_AdvancedStrategyMinimumHoldTime = Cfg.SecondaryRoles_AdvancedStrategyMinimumHoldTime; - secondary_role_timeout_type_t secondaryRoles_AdvancedStrategyTimeoutType = Cfg.SecondaryRoles_AdvancedStrategyTimeoutType; + serialized_secondary_role_timeout_type_t secondaryRoles_AdvancedStrategyTimeoutType = SerializedSecondaryRoleTimeoutType_Active; if (DataModelVersion.major >= 7) { secondaryRoles_Strategy = ReadUInt8(buffer); ATTR_UNUSED uint16_t secondaryRoles_AdvancedStrategyDoubletapTimeout = ReadUInt16(buffer); secondaryRoles_AdvancedStrategyTimeout = ReadUInt16(buffer); secondaryRoles_AdvancedStrategySafetyMargin = ReadInt16(buffer); - if (DataModelVersion.major >= 14) { - secondaryRoles_AdvancedStrategyTriggeringEvent = ReadUInt8(buffer); - } else { - secondaryRoles_AdvancedStrategyTriggeringEvent = ReadBool(buffer) ? SecondaryRoleTriggeringEvent_Release : SecondaryRoleTriggeringEvent_Press; - } + secondaryRoles_AdvancedStrategyTriggeringEvent = ReadUInt8(buffer); secondaryRoles_AdvancedStrategyDoubletapToPrimary = ReadBool(buffer); secondaryRoles_AdvancedStrategyTimeoutAction = ReadUInt8(buffer); @@ -365,7 +361,20 @@ parser_error_t parseConfig(config_buffer_t *buffer) Cfg.SecondaryRoles_Strategy = secondaryRoles_Strategy; Cfg.SecondaryRoles_AdvancedStrategyTimeout = secondaryRoles_AdvancedStrategyTimeout; Cfg.SecondaryRoles_AdvancedStrategySafetyMargin = secondaryRoles_AdvancedStrategySafetyMargin; - Cfg.SecondaryRoles_AdvancedStrategyTriggeringEvent = secondaryRoles_AdvancedStrategyTriggeringEvent; + switch (secondaryRoles_AdvancedStrategyTriggeringEvent) { + case SerializedSecondaryRoleTriggeringEvent_Press: + Cfg.SecondaryRoles_AdvancedStrategyTriggeringEvent = SecondaryRoleTriggeringEvent_Press; + break; + case SerializedSecondaryRoleTriggeringEvent_Release: + Cfg.SecondaryRoles_AdvancedStrategyTriggeringEvent = SecondaryRoleTriggeringEvent_Release; + break; + case SerializedSecondaryRoleTriggeringEvent_None: + Cfg.SecondaryRoles_AdvancedStrategyTriggeringEvent = SecondaryRoleTriggeringEvent_None; + break; + default: + ConfigParser_Error(buffer, "Invalid secondary role triggering event: %u", secondaryRoles_AdvancedStrategyTriggeringEvent); + return ParserError_InvalidSecondaryRoleTriggeringEvent; + } Cfg.SecondaryRoles_AdvancedStrategyDoubletapToPrimary = secondaryRoles_AdvancedStrategyDoubletapToPrimary; switch (secondaryRoles_AdvancedStrategyTimeoutAction) { case SerializedSecondaryRoleActionType_Primary: @@ -396,7 +405,17 @@ parser_error_t parseConfig(config_buffer_t *buffer) Cfg.SecondaryRoles_AdvancedStrategyTriggerByMouse = secondaryRoles_AdvancedStrategyTriggerByMouse; Cfg.SecondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf = secondaryRoles_AdvancedStrategyAcceptTriggersFromSameHalf; Cfg.SecondaryRoles_AdvancedStrategyMinimumHoldTime = secondaryRoles_AdvancedStrategyMinimumHoldTime; - Cfg.SecondaryRoles_AdvancedStrategyTimeoutType = secondaryRoles_AdvancedStrategyTimeoutType; + switch (secondaryRoles_AdvancedStrategyTimeoutType) { + case SerializedSecondaryRoleTimeoutType_Active: + Cfg.SecondaryRoles_AdvancedStrategyTimeoutType = SecondaryRoleTimeoutType_Active; + break; + case SerializedSecondaryRoleTimeoutType_Passive: + Cfg.SecondaryRoles_AdvancedStrategyTimeoutType = SecondaryRoleTimeoutType_Passive; + break; + default: + ConfigParser_Error(buffer, "Invalid secondary role timeout type: %u", secondaryRoles_AdvancedStrategyTimeoutType); + return ParserError_InvalidSecondaryRoleTimeoutType; + } } // Version 8 diff --git a/right/src/config_parser/parse_config.h b/right/src/config_parser/parse_config.h index 7be8fe61d..243d7cd7a 100644 --- a/right/src/config_parser/parse_config.h +++ b/right/src/config_parser/parse_config.h @@ -41,6 +41,8 @@ ParserError_InvalidHostConnectionId = 21, ParserError_InvalidSerializedOtherAction = 22, ParserError_ConfigVersionTooNew = 23, + ParserError_InvalidSecondaryRoleTriggeringEvent = 24, + ParserError_InvalidSecondaryRoleTimeoutType = 25, } parser_error_t; typedef enum { @@ -49,6 +51,17 @@ SerializedSecondaryRoleActionType_NoOp, } serialized_secondary_role_action_type_t; + typedef enum { + SerializedSecondaryRoleTriggeringEvent_Press, + SerializedSecondaryRoleTriggeringEvent_Release, + SerializedSecondaryRoleTriggeringEvent_None, + } serialized_secondary_role_triggering_event_t; + + typedef enum { + SerializedSecondaryRoleTimeoutType_Active, + SerializedSecondaryRoleTimeoutType_Passive, + } serialized_secondary_role_timeout_type_t; + typedef enum { SerializedChargingMode_Full = 0, SerializedChargingMode_StationaryMode = 1,