From 8549f36c8f48d7451453961dd59bed6dfe7140db Mon Sep 17 00:00:00 2001 From: Anna Rose Wiggins Date: Fri, 27 Jun 2025 22:03:01 -0400 Subject: [PATCH] Working example code with 3-button combo. --- cmd/joyful/main.go | 123 ++++++++++++++++++++------ internal/virtualdevice/eventbuffer.go | 43 +++++++++ 2 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 internal/virtualdevice/eventbuffer.go diff --git a/cmd/joyful/main.go b/cmd/joyful/main.go index 8c21b09..408fecd 100644 --- a/cmd/joyful/main.go +++ b/cmd/joyful/main.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "syscall" + "os" "time" "git.annabunches.net/annabunches/joyful/internal/virtualdevice" @@ -10,9 +10,6 @@ import ( ) func main() { - // Check for and destroy any existing joyful devices - virtualdevice.CleanupStaleVirtualDevices() - // STUB: parse virtual device config // STUB: parse mapping config @@ -41,34 +38,93 @@ func main() { }, }, ) - if err != nil { - fmt.Printf("Failed to create vDevice: %s", err.Error()) - } + fatalIfError(err, "Failed to create virtual device") - location, err := vDevice.PhysicalLocation() - if err != nil { - fmt.Printf("Couldn't get virtual device location: %s\n", err.Error()) - } - fmt.Printf("Device created as %s. Press Ctrl+C to quit and destroy the device.\n", location) + buffer := virtualdevice.NewEventBuffer(vDevice) + + name, err := vDevice.Name() + if err != nil { + name = "Unknown" + } + fmt.Printf("Virtual device created as %s.\n", name) + + pDevice, err := evdev.Open("/dev/input/event12") + fatalIfError(err, "Couldn't open physical device") + + name, err = pDevice.Name() + if err != nil { + name = "Unknown" + } + fmt.Printf("Connected to physical device %s\n", name) + + var combo int32 = 0 - var value int32 = 1 for { - eventTime := syscall.NsecToTimeval(int64(time.Now().Nanosecond())) + last := combo - vDevice.WriteOne(&evdev.InputEvent{ - Time: eventTime, - Type: evdev.EV_KEY, - Code: evdev.BTN_TRIGGER, - Value: value, - }) + event, err := pDevice.ReadOne() + logIfError(err, "Error while reading event") - if value == 0 { - value = 1 - } else { - value = 0 + // FIXME: test code + for event.Code != evdev.SYN_REPORT { + if event.Type == evdev.EV_KEY { + switch event.Code { + case evdev.BTN_TRIGGER: + if event.Value == 0 { + fmt.Println("Trigger 0") + combo++ + } + if event.Value == 1 { + fmt.Println("Trigger 1") + combo-- + } + + case evdev.BTN_THUMB: + if event.Value == 0 { + fmt.Println("Thumb 0") + combo-- + } + if event.Value == 1 { + fmt.Println("Thumb 1") + combo++ + } + + case evdev.BTN_THUMB2: + if event.Value == 0 { + fmt.Println("Thumb2 0") + combo-- + } + if event.Value == 1 { + fmt.Println("Thumb2 1") + combo++ + } + + } + } + + event, err = pDevice.ReadOne() + logIfError(err, "Error while reading event") } - time.Sleep(1 * time.Second) + if combo > last && combo == 3 { + buffer.AddEvent(&evdev.InputEvent{ + Type: evdev.EV_KEY, + Code: evdev.BTN_TRIGGER, + Value: 1, + }) + } + if combo < last && combo == 2 { + buffer.AddEvent(&evdev.InputEvent{ + Type: evdev.EV_KEY, + Code: evdev.BTN_TRIGGER, + Value: 0, + }) + } + + buffer.SendEvents() + // FIXME: end test code + + time.Sleep(1 * time.Millisecond) } } @@ -88,3 +144,20 @@ func jsButtons() []evdev.EvCode { return buttons } + +func logIfError(err error, msg string) { + if err == nil { + return + } + + fmt.Printf("%s: %s\n", msg, err.Error()) +} + +func fatalIfError(err error, msg string) { + if err == nil { + return + } + + logIfError(err, msg) + os.Exit(1) +} diff --git a/internal/virtualdevice/eventbuffer.go b/internal/virtualdevice/eventbuffer.go new file mode 100644 index 0000000..8279fff --- /dev/null +++ b/internal/virtualdevice/eventbuffer.go @@ -0,0 +1,43 @@ +// Code to manage sending events on the Virtual Device +package virtualdevice + +import ( + "syscall" + "time" + + "github.com/holoplot/go-evdev" +) + +type EventBuffer struct { + events []*evdev.InputEvent + device *evdev.InputDevice +} + +func NewEventBuffer(device *evdev.InputDevice) *EventBuffer { + return &EventBuffer{ + events: make([]*evdev.InputEvent, 0), + device: device, + } +} + +func (buffer *EventBuffer) AddEvent(event *evdev.InputEvent) { + buffer.events = append(buffer.events, event) +} + +func (buffer *EventBuffer) SendEvents() { + eventTime := syscall.NsecToTimeval(int64(time.Now().Nanosecond())) + + for i := 0; i < len(buffer.events); i++ { + buffer.events[i].Time = eventTime + buffer.device.WriteOne(buffer.events[i]) + } + + buffer.device.WriteOne(&evdev.InputEvent{ + Time: eventTime, + Type: evdev.EV_SYN, + Code: evdev.SYN_REPORT, + Value: 0, + }) + + buffer.events = make([]*evdev.InputEvent, 0) +}