118 lines
3.1 KiB
Go
118 lines
3.1 KiB
Go
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
|
|
}
|