Refactor and add some documentation (it'll be true soon enough)
This commit is contained in:
parent
4ff4757abc
commit
15b9fa6ac0
3 changed files with 141 additions and 117 deletions
|
@ -1,15 +1,25 @@
|
|||
// The ConfigParser is the main structure you'll interact with when using this package.
|
||||
//
|
||||
// Example usage:
|
||||
// config := &config.ConfigParser{}
|
||||
// config.Parse(<some directory containing YAML files>)
|
||||
// virtualDevices, err := config.CreateVirtualDevices()
|
||||
// physicalDevices, err := config.ConnectVirtualDevices()
|
||||
// modes, err := config.GetModes()
|
||||
// rules, err := config.BuildRules(physicalDevices, virtualDevices, modes)
|
||||
//
|
||||
// nb: there are methods defined on ConfigParser in other files in this package!
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/logger"
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
type ConfigParser struct {
|
||||
|
@ -58,112 +68,3 @@ func (parser *ConfigParser) Parse(directory string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateVirtualDevices will register any configured devices with type = virtual
|
||||
// using /dev/uinput, and return a map of those devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once, unless you want to create duplicate devices for some reason.
|
||||
func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypeVirtual {
|
||||
continue
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("joyful-%s", deviceConfig.Name)
|
||||
device, err := evdev.CreateDevice(
|
||||
name,
|
||||
// TODO: who knows what these should actually be
|
||||
evdev.InputID{
|
||||
BusType: 0x03,
|
||||
Vendor: 0x4711,
|
||||
Product: 0x0816,
|
||||
Version: 1,
|
||||
},
|
||||
map[evdev.EvType][]evdev.EvCode{
|
||||
evdev.EV_KEY: makeButtons(int(deviceConfig.Buttons)),
|
||||
evdev.EV_ABS: makeAxes(int(deviceConfig.Axes)),
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.LogIfError(err, "Failed to create virtual device")
|
||||
continue
|
||||
}
|
||||
|
||||
deviceMap[deviceConfig.Name] = device
|
||||
logger.Log(fmt.Sprintf("Created virtual device '%s'", name))
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
// ConnectPhysicalDevices will create InputDevices corresponding to any registered
|
||||
// devices with type = physical. It will also attempt to acquire exclusive access
|
||||
// to those devices, to prevent the same inputs from being read on multiple devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once.
|
||||
func (parser *ConfigParser) ConnectPhysicalDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypePhysical {
|
||||
continue
|
||||
}
|
||||
|
||||
device, err := evdev.OpenByName(deviceConfig.DeviceName)
|
||||
if err != nil {
|
||||
logger.LogError(err, "Failed to open physical device, skipping. Confirm the device name with 'evlist'. Watch out for spaces.")
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: grab exclusive access to device
|
||||
|
||||
logger.Log(fmt.Sprintf("Connected to '%s' as '%s'", deviceConfig.DeviceName, deviceConfig.Name))
|
||||
deviceMap[deviceConfig.Name] = device
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
func makeButtons(numButtons int) []evdev.EvCode {
|
||||
if numButtons > 56 {
|
||||
numButtons = 56
|
||||
logger.Log("Limiting virtual device buttons to 56")
|
||||
}
|
||||
|
||||
buttons := make([]evdev.EvCode, numButtons)
|
||||
|
||||
startCode := 0x120
|
||||
for i := 0; i < numButtons && i < 16; i++ {
|
||||
buttons[i] = evdev.EvCode(startCode + i)
|
||||
}
|
||||
|
||||
if numButtons > 16 {
|
||||
startCode = 0x2c0
|
||||
for i := 0; i < numButtons-16; i++ {
|
||||
buttons[16+i] = evdev.EvCode(startCode + i)
|
||||
}
|
||||
}
|
||||
|
||||
return buttons
|
||||
}
|
||||
|
||||
func makeAxes(numAxes int) []evdev.EvCode {
|
||||
if numAxes > 8 {
|
||||
numAxes = 8
|
||||
logger.Log("Limiting virtual device axes to 8")
|
||||
}
|
||||
|
||||
axes := make([]evdev.EvCode, numAxes)
|
||||
for i := 0; i < numAxes; i++ {
|
||||
axes[i] = evdev.EvCode(i)
|
||||
}
|
||||
|
||||
return axes
|
||||
}
|
||||
|
|
118
internal/config/devices.go
Normal file
118
internal/config/devices.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/logger"
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
// CreateVirtualDevices will register any configured devices with type = virtual
|
||||
// using /dev/uinput, and return a map of those devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once, unless you want to create duplicate devices for some reason.
|
||||
func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypeVirtual {
|
||||
continue
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("joyful-%s", deviceConfig.Name)
|
||||
device, err := evdev.CreateDevice(
|
||||
name,
|
||||
// TODO: who knows what these should actually be
|
||||
evdev.InputID{
|
||||
BusType: 0x03,
|
||||
Vendor: 0x4711,
|
||||
Product: 0x0816,
|
||||
Version: 1,
|
||||
},
|
||||
map[evdev.EvType][]evdev.EvCode{
|
||||
evdev.EV_KEY: makeButtons(int(deviceConfig.Buttons)),
|
||||
evdev.EV_ABS: makeAxes(int(deviceConfig.Axes)),
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
logger.LogIfError(err, "Failed to create virtual device")
|
||||
continue
|
||||
}
|
||||
|
||||
deviceMap[deviceConfig.Name] = device
|
||||
logger.Log(fmt.Sprintf("Created virtual device '%s'", name))
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
// ConnectPhysicalDevices will create InputDevices corresponding to any registered
|
||||
// devices with type = physical. It will also attempt to acquire exclusive access
|
||||
// to those devices, to prevent the same inputs from being read on multiple devices.
|
||||
//
|
||||
// This function assumes you have already called Parse() on the config directory.
|
||||
//
|
||||
// This function should only be called once.
|
||||
func (parser *ConfigParser) ConnectPhysicalDevices() map[string]*evdev.InputDevice {
|
||||
deviceMap := make(map[string]*evdev.InputDevice)
|
||||
|
||||
for _, deviceConfig := range parser.config.Devices {
|
||||
if strings.ToLower(deviceConfig.Type) != DeviceTypePhysical {
|
||||
continue
|
||||
}
|
||||
|
||||
device, err := evdev.OpenByName(deviceConfig.DeviceName)
|
||||
if err != nil {
|
||||
logger.LogError(err, "Failed to open physical device, skipping. Confirm the device name with 'evlist'. Watch out for spaces.")
|
||||
continue
|
||||
}
|
||||
|
||||
// TODO: grab exclusive access to device (add config option)
|
||||
|
||||
logger.Log(fmt.Sprintf("Connected to '%s' as '%s'", deviceConfig.DeviceName, deviceConfig.Name))
|
||||
deviceMap[deviceConfig.Name] = device
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
func makeButtons(numButtons int) []evdev.EvCode {
|
||||
if numButtons > 56 {
|
||||
numButtons = 56
|
||||
logger.Log("Limiting virtual device buttons to 56")
|
||||
}
|
||||
|
||||
buttons := make([]evdev.EvCode, numButtons)
|
||||
|
||||
startCode := 0x120
|
||||
for i := 0; i < numButtons && i < 16; i++ {
|
||||
buttons[i] = evdev.EvCode(startCode + i)
|
||||
}
|
||||
|
||||
if numButtons > 16 {
|
||||
startCode = 0x2c0
|
||||
for i := 0; i < numButtons-16; i++ {
|
||||
buttons[16+i] = evdev.EvCode(startCode + i)
|
||||
}
|
||||
}
|
||||
|
||||
return buttons
|
||||
}
|
||||
|
||||
func makeAxes(numAxes int) []evdev.EvCode {
|
||||
if numAxes > 8 {
|
||||
numAxes = 8
|
||||
logger.Log("Limiting virtual device axes to 8")
|
||||
}
|
||||
|
||||
axes := make([]evdev.EvCode, numAxes)
|
||||
for i := 0; i < numAxes; i++ {
|
||||
axes[i] = evdev.EvCode(i)
|
||||
}
|
||||
|
||||
return axes
|
||||
}
|
|
@ -9,6 +9,11 @@ import (
|
|||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
// TODO: At some point it would *very likely* make sense to map each rule to all of the physical devices that can
|
||||
// trigger it, and return that instead. Something like a map[*evdev.InputDevice][]mappingrule.MappingRule.
|
||||
// This would speed up rule matching by only checking relevant rules for a given input event.
|
||||
// We could take this further and make it a map[*evdev.InputDevice]map[evdev.InputType]map[evdev.InputCode][]mappingrule.MappingRule
|
||||
// For very large rule-bases this may be helpful for staying performant.
|
||||
func (parser *ConfigParser) BuildRules(pDevs map[string]*evdev.InputDevice, vDevs map[string]*evdev.InputDevice) []mappingrules.MappingRule {
|
||||
rules := make([]mappingrules.MappingRule, 0)
|
||||
|
||||
|
@ -49,8 +54,8 @@ func makeSimpleRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice,
|
|||
MappingRuleBase: mappingrules.MappingRuleBase{
|
||||
Output: output,
|
||||
},
|
||||
Input: input,
|
||||
Name: ruleConfig.Name,
|
||||
Input: input,
|
||||
Name: ruleConfig.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -74,7 +79,7 @@ func makeComboRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice, v
|
|||
Output: output,
|
||||
},
|
||||
Inputs: inputs,
|
||||
State: 0,
|
||||
State: 0,
|
||||
Name: ruleConfig.Name,
|
||||
}, nil
|
||||
}
|
||||
|
@ -94,9 +99,9 @@ func makeLatchedRule(ruleConfig RuleConfig, pDevs map[string]*evdev.InputDevice,
|
|||
MappingRuleBase: mappingrules.MappingRuleBase{
|
||||
Output: output,
|
||||
},
|
||||
Input: input,
|
||||
Name: ruleConfig.Name,
|
||||
State: false,
|
||||
Input: input,
|
||||
Name: ruleConfig.Name,
|
||||
State: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue