Allow all buttons and axes on virtual devices to be specified by either number or an explicit list. (#5)
Reviewed-on: #5 Co-authored-by: Anna Rose Wiggins <annabunches@gmail.com> Co-committed-by: Anna Rose Wiggins <annabunches@gmail.com>
This commit is contained in:
parent
712dcdbc07
commit
6ef0cbd07c
11 changed files with 1114 additions and 130 deletions
|
@ -23,6 +23,12 @@ func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice
|
|||
}
|
||||
|
||||
name := fmt.Sprintf("joyful-%s", deviceConfig.Name)
|
||||
capabilities := map[evdev.EvType][]evdev.EvCode{
|
||||
evdev.EV_KEY: makeButtons(deviceConfig.NumButtons, deviceConfig.Buttons),
|
||||
evdev.EV_ABS: makeAxes(deviceConfig.NumAxes, deviceConfig.Axes),
|
||||
evdev.EV_REL: makeRelativeAxes(deviceConfig.NumRelativeAxes, deviceConfig.RelativeAxes),
|
||||
}
|
||||
|
||||
device, err := evdev.CreateDevice(
|
||||
name,
|
||||
// TODO: who knows what these should actually be
|
||||
|
@ -32,11 +38,7 @@ func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice
|
|||
Product: 0x0816,
|
||||
Version: 1,
|
||||
},
|
||||
map[evdev.EvType][]evdev.EvCode{
|
||||
evdev.EV_KEY: makeButtons(int(deviceConfig.Buttons)),
|
||||
evdev.EV_ABS: makeAxes(int(deviceConfig.Axes)),
|
||||
evdev.EV_REL: makeRelativeAxes(deviceConfig.RelativeAxes),
|
||||
},
|
||||
capabilities,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
|
@ -45,7 +47,13 @@ func (parser *ConfigParser) CreateVirtualDevices() map[string]*evdev.InputDevice
|
|||
}
|
||||
|
||||
deviceMap[deviceConfig.Name] = device
|
||||
logger.Log(fmt.Sprintf("Created virtual device '%s'", name))
|
||||
logger.Log(fmt.Sprintf(
|
||||
"Created virtual device '%s' with %d buttons, %d axes, and %d relative axes",
|
||||
name,
|
||||
len(capabilities[evdev.EV_KEY]),
|
||||
len(capabilities[evdev.EV_ABS]),
|
||||
len(capabilities[evdev.EV_REL]),
|
||||
))
|
||||
}
|
||||
|
||||
return deviceMap
|
||||
|
@ -81,12 +89,31 @@ func (parser *ConfigParser) ConnectPhysicalDevices() map[string]*evdev.InputDevi
|
|||
return deviceMap
|
||||
}
|
||||
|
||||
func makeButtons(numButtons int) []evdev.EvCode {
|
||||
// TODO: these functions have a lot of duplication; we need to figure out how to refactor it cleanly
|
||||
// without losing logging context...
|
||||
func makeButtons(numButtons int, buttonList []string) []evdev.EvCode {
|
||||
if numButtons > 0 && len(buttonList) > 0 {
|
||||
logger.Log("'num_buttons' and 'buttons' both specified, ignoring 'num_buttons'")
|
||||
}
|
||||
|
||||
if numButtons > VirtualDeviceMaxButtons {
|
||||
numButtons = VirtualDeviceMaxButtons
|
||||
logger.Logf("Limiting virtual device buttons to %d", VirtualDeviceMaxButtons)
|
||||
}
|
||||
|
||||
if len(buttonList) > 0 {
|
||||
buttons := make([]evdev.EvCode, 0, len(buttonList))
|
||||
for _, codeStr := range buttonList {
|
||||
code, err := parseCode(codeStr, "BTN")
|
||||
if err != nil {
|
||||
logger.LogError(err, "Failed to create button, skipping")
|
||||
continue
|
||||
}
|
||||
buttons = append(buttons, code)
|
||||
}
|
||||
return buttons
|
||||
}
|
||||
|
||||
buttons := make([]evdev.EvCode, numButtons)
|
||||
|
||||
startCode := 0x120
|
||||
|
@ -104,7 +131,24 @@ func makeButtons(numButtons int) []evdev.EvCode {
|
|||
return buttons
|
||||
}
|
||||
|
||||
func makeAxes(numAxes int) []evdev.EvCode {
|
||||
func makeAxes(numAxes int, axisList []string) []evdev.EvCode {
|
||||
if numAxes > 0 && len(axisList) > 0 {
|
||||
logger.Log("'num_axes' and 'axes' both specified, ignoring 'num_axes'")
|
||||
}
|
||||
|
||||
if len(axisList) > 0 {
|
||||
axes := make([]evdev.EvCode, 0, len(axisList))
|
||||
for _, codeStr := range axisList {
|
||||
code, err := parseCode(codeStr, "ABS")
|
||||
if err != nil {
|
||||
logger.LogError(err, "Failed to create axis, skipping")
|
||||
continue
|
||||
}
|
||||
axes = append(axes, code)
|
||||
}
|
||||
return axes
|
||||
}
|
||||
|
||||
if numAxes > 8 {
|
||||
numAxes = 8
|
||||
logger.Log("Limiting virtual device axes to 8")
|
||||
|
@ -118,19 +162,33 @@ func makeAxes(numAxes int) []evdev.EvCode {
|
|||
return axes
|
||||
}
|
||||
|
||||
func makeRelativeAxes(axes []string) []evdev.EvCode {
|
||||
codes := make([]evdev.EvCode, 0)
|
||||
|
||||
for _, axis := range axes {
|
||||
code, ok := evdev.RELFromString[axis]
|
||||
|
||||
if !ok {
|
||||
logger.Logf("Relative axis '%s' invalid. Skipping.", axis)
|
||||
continue
|
||||
}
|
||||
|
||||
codes = append(codes, code)
|
||||
func makeRelativeAxes(numAxes int, axisList []string) []evdev.EvCode {
|
||||
if numAxes > 0 && len(axisList) > 0 {
|
||||
logger.Log("'num_rel_axes' and 'rel_axes' both specified, ignoring 'num_rel_axes'")
|
||||
}
|
||||
|
||||
return codes
|
||||
if len(axisList) > 0 {
|
||||
axes := make([]evdev.EvCode, 0, len(axisList))
|
||||
for _, codeStr := range axisList {
|
||||
code, err := parseCode(codeStr, "REL")
|
||||
if err != nil {
|
||||
logger.LogError(err, "Failed to create axis, skipping")
|
||||
continue
|
||||
}
|
||||
axes = append(axes, code)
|
||||
}
|
||||
return axes
|
||||
}
|
||||
|
||||
if numAxes > 10 {
|
||||
numAxes = 10
|
||||
logger.Log("Limiting virtual device relative axes to 10")
|
||||
}
|
||||
|
||||
axes := make([]evdev.EvCode, numAxes)
|
||||
for i := 0; i < numAxes; i++ {
|
||||
axes[i] = evdev.EvCode(i)
|
||||
}
|
||||
|
||||
return axes
|
||||
}
|
||||
|
|
|
@ -15,9 +15,38 @@ func TestRunnerDevicesConfig(t *testing.T) {
|
|||
suite.Run(t, new(DevicesConfigTests))
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeButtons() {
|
||||
t.Run("Maximum buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons, []string{})
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("Truncated buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons+1, []string{})
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("16 buttons", func() {
|
||||
buttons := makeButtons(16, []string{})
|
||||
t.Equal(16, len(buttons))
|
||||
t.Contains(buttons, evdev.EvCode(evdev.BTN_DEAD))
|
||||
t.NotContains(buttons, evdev.EvCode(evdev.BTN_TRIGGER_HAPPY))
|
||||
})
|
||||
|
||||
t.Run("Explicit buttons", func() {
|
||||
buttonConfig := []string{"BTN_THUMB", "top", "btn_top2", "0x2fe", "0x300", "15"}
|
||||
buttons := makeButtons(0, buttonConfig)
|
||||
t.Equal(len(buttonConfig), len(buttons))
|
||||
t.Contains(buttons, evdev.EvCode(0x2fe))
|
||||
t.Contains(buttons, evdev.EvCode(0x300))
|
||||
t.Contains(buttons, evdev.EvCode(evdev.BTN_TOP))
|
||||
t.Contains(buttons, evdev.EvCode(evdev.BTN_DEAD))
|
||||
})
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeAxes() {
|
||||
t.Run("8 axes", func() {
|
||||
axes := makeAxes(8)
|
||||
axes := makeAxes(8, []string{})
|
||||
t.Equal(8, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Y))
|
||||
|
@ -30,34 +59,61 @@ func (t *DevicesConfigTests) TestMakeAxes() {
|
|||
})
|
||||
|
||||
t.Run("9 axes is truncated", func() {
|
||||
axes := makeAxes(9)
|
||||
axes := makeAxes(9, []string{})
|
||||
t.Equal(8, len(axes))
|
||||
})
|
||||
|
||||
t.Run("3 axes", func() {
|
||||
axes := makeAxes(3)
|
||||
axes := makeAxes(3, []string{})
|
||||
t.Equal(3, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Z))
|
||||
})
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeButtons() {
|
||||
t.Run("Maximum buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons)
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("Truncated buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons + 1)
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("16 buttons", func() {
|
||||
buttons := makeButtons(16)
|
||||
t.Equal(16, len(buttons))
|
||||
t.Contains(buttons, evdev.EvCode(evdev.BTN_DEAD))
|
||||
t.NotContains(buttons, evdev.EvCode(evdev.BTN_TRIGGER_HAPPY))
|
||||
t.Run("4 explicit axis", func() {
|
||||
axes := makeAxes(0, []string{"x", "y", "throttle", "rudder"})
|
||||
t.Equal(4, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_THROTTLE))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_RUDDER))
|
||||
})
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeRelativeAxes() {
|
||||
t.Run("10 axes", func() {
|
||||
axes := makeRelativeAxes(10, []string{})
|
||||
t.Equal(10, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_MISC))
|
||||
})
|
||||
|
||||
t.Run("11 axes", func() {
|
||||
axes := makeRelativeAxes(11, []string{})
|
||||
t.Equal(10, len(axes))
|
||||
})
|
||||
|
||||
t.Run("3 axes", func() {
|
||||
axes := makeRelativeAxes(3, []string{})
|
||||
t.Equal(3, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_Z))
|
||||
})
|
||||
|
||||
t.Run("1 explicit axis", func() {
|
||||
axes := makeRelativeAxes(0, []string{"wheel"})
|
||||
t.Equal(1, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_WHEEL))
|
||||
})
|
||||
|
||||
t.Run("4 explicit axis", func() {
|
||||
axes := makeRelativeAxes(0, []string{"x", "y", "wheel", "hwheel"})
|
||||
t.Equal(4, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_WHEEL))
|
||||
t.Contains(axes, evdev.EvCode(evdev.REL_HWHEEL))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -16,13 +16,16 @@ type Config struct {
|
|||
}
|
||||
|
||||
type DeviceConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
Type string `yaml:"type"`
|
||||
DeviceName string `yaml:"device_name,omitempty"`
|
||||
Uuid string `yaml:"uuid,omitempty"`
|
||||
Buttons int `yaml:"buttons,omitempty"`
|
||||
Axes int `yaml:"axes,omitempty"`
|
||||
RelativeAxes []string `yaml:"rel_axes,omitempty"`
|
||||
Name string `yaml:"name"`
|
||||
Type string `yaml:"type"`
|
||||
DeviceName string `yaml:"device_name,omitempty"`
|
||||
Uuid string `yaml:"uuid,omitempty"`
|
||||
NumButtons int `yaml:"num_buttons,omitempty"`
|
||||
NumAxes int `yaml:"num_axes,omitempty"`
|
||||
NumRelativeAxes int `yaml:"num_rel_axes"`
|
||||
Buttons []string `yaml:"buttons,omitempty"`
|
||||
Axes []string `yaml:"axes,omitempty"`
|
||||
RelativeAxes []string `yaml:"rel_axes,omitempty"`
|
||||
}
|
||||
|
||||
type RuleConfig struct {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue