Fix combo rules and add some example config.

This commit is contained in:
Anna Rose Wiggins 2025-07-02 14:53:52 -04:00
parent 428749a519
commit a5b59bf39e
6 changed files with 93 additions and 6 deletions

11
examples/devices.yml Normal file
View file

@ -0,0 +1,11 @@
devices:
- name: main
type: virtual
buttons: 56
axes: 8
- name: right-stick
type: physical
device_name: VIRPIL Controls 20220407 R-VPC Stick MT-50CM2
- name: left-stick
type: physical
device_name: VIRPIL Controls 20220407 L-VPC Stick MT-50CM2

70
examples/rules.yml Normal file
View file

@ -0,0 +1,70 @@
rules:
# A simple 1:1 mapping of 2 inputs
- name: basic mapping
type: simple
input:
device: right-stick
button: BTN_BASE6
output:
device: main
button: BTN_BASE6
# A couple of axis mappings
- name: x axis
type: simple
input:
device: right-stick
axis: ABS_X
output:
device: main
axis: ABS_X
- name: y axis
type: simple
input:
device: right-stick
axis: ABS_Y
output:
device: main
axis: ABS_Y
# 3-stage trigger for a VPC Constellation Alpha
# This only sends a trigger input when the
# flip trigger is pulled all the way in *and* the inner trigger
# is activated
- name: 3 stage trigger
type: combo
inputs:
- device: right-stick
button: BTN_TRIGGER
inverted: true
- device: right-stick
button: BTN_THUMB
- device: right-stick
button: BTN_THUMB2
output:
device: main
button: BTN_TRIGGER
# Of course, BTN_TRIGGER above is unnecessary, because on the Constellation Alpha
# it's impossible to press BTN_THUMB without disabling BTN_TRIGGER. So this is a
# simpler form of the same rule for the left stick
- name: 2 stage trigger
type: combo
inputs:
- device: left-stick
button: BTN_THUMB
- device: left-stick
button: BTN_THUMB2
output:
device: main
button: BTN_THUMB
# You can use the same input in multiple rules. Be careful with this!
# In this example we use the same 2-stage guard, but trigger an additional output
# when the final stage of the VPC's trigger is depressed
- name: alternate 2 stage trigger
type: combo
inputs:
- device: left-stick
button: BTN_THUMB
- device: left-stick
button: BTN_TOP
output:
device: main
button: BTN_THUMB2

View file

@ -21,6 +21,7 @@ func makeSimpleRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice,
return &mappingrules.SimpleMappingRule{
Input: input,
Output: output,
Name: ruleConfig.Name,
}, nil
}
@ -42,6 +43,7 @@ func makeComboRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, v
return &mappingrules.ComboMappingRule{
Inputs: inputs,
Output: output,
Name: ruleConfig.Name,
}, nil
}
@ -61,6 +63,7 @@ func makeRuleTarget(targetConfig RuleTargetConfig, devs map[string]*evdev.InputD
}
ruleTarget.Type = eventType
ruleTarget.Code = eventCode
ruleTarget.Inverted = targetConfig.Inverted
return ruleTarget, nil
}

View file

@ -10,7 +10,7 @@ func Log(msg string) {
}
func Logf(msg string, params ...interface{}) {
fmt.Printf(msg, params...)
fmt.Printf(msg+"\n", params...)
}
func LogError(err error, msg string) {

View file

@ -27,16 +27,16 @@ func valueFromTarget(rule RuleTarget, event *evdev.InputEvent) int32 {
value = 0
}
case evdev.EV_ABS:
// TODO: how would we invert axes?
logger.Logf("STUB: Inverting axes is not yet implemented.")
default:
logger.Logf("Inverted rule for unknown event type '%d'. Not inverting value\n", event.Type)
logger.Logf("Inverted rule for unknown event type '%d'. Not inverting value", event.Type)
}
}
return value
}
func (rule SimpleMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.InputEvent) *evdev.InputEvent {
func (rule *SimpleMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.InputEvent) *evdev.InputEvent {
if device != rule.Input.Device ||
event.Code != rule.Input.Code {
return nil
@ -45,7 +45,7 @@ func (rule SimpleMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev
return eventFromTarget(rule.Output, valueFromTarget(rule.Input, event))
}
func (rule ComboMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.InputEvent) *evdev.InputEvent {
func (rule *ComboMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.InputEvent) *evdev.InputEvent {
// Check each of the inputs, and if we find a match, proceed
var match *RuleTarget
for _, input := range rule.Inputs {
@ -63,12 +63,13 @@ func (rule ComboMappingRule) MatchEvent(device *evdev.InputDevice, event *evdev.
inputValue := valueFromTarget(*match, event)
oldState := rule.State
if inputValue == 0 {
rule.State--
rule.State = max(rule.State-1, 0)
}
if inputValue == 1 {
rule.State++
}
targetState := len(rule.Inputs)
if oldState == targetState-1 && rule.State == targetState {
return eventFromTarget(rule.Output, 1)
}

View file

@ -10,12 +10,14 @@ type MappingRule interface {
type SimpleMappingRule struct {
Input RuleTarget
Output RuleTarget
Name string
}
// A Combo Mapping Rule can require multiple physical button presses for a single output button
type ComboMappingRule struct {
Inputs []RuleTarget
Output RuleTarget
Name string
State int
}