conjure-os/lib/inputs/joystick.go
2025-07-19 19:58:57 +00:00

173 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package inputs
import (
"fmt"
"github.com/karalabe/hid"
)
type JoystickEvent struct {
Time uint32 // Event timestamp in milliseconds
Value int16 // Value of the event (button press or axis movement)
Type uint8 // Event type (button or axis)
Number uint8 // Axis/button number
}
const (
JS_EVENT_BUTTON = 0x01 // Button pressed/released
JS_EVENT_AXIS = 0x02 // Joystick moved
JS_EVENT_INIT = 0x80 // Initial state of device
)
type Controller struct {
Device *hid.Device
}
func (c *Controller) ReadState(buf []byte) (*ControllerState, error) {
_, err := c.Device.Read(buf)
if err != nil {
return nil, err
}
x := buf[0] // Horizontal axis (0255)
y := buf[1] // Vertical axis (0255)
buttons := buf[6] // Buttons as bitfield
state := ControllerState{
Joystick: Vec2B{x, y},
Buttons: buttons,
}
return &state, nil
}
type Vec2B struct {
X byte `json:"x"`
Y byte `json:"y"`
}
type ControllerState struct {
Id int `json:"id"`
Joystick Vec2B `json:"joystick"`
Buttons byte `json:"buttons"`
}
type ConjureControllerButton int
const (
ButtonPower ConjureControllerButton = iota //0
ButtonStart
Button1
Button2
Button3
ButtonA
ButtonB
ButtonC // 7
)
var ConjureControllerButtons = []ConjureControllerButton{
ButtonStart,
ButtonPower,
Button1,
Button2,
Button3,
ButtonA,
ButtonB,
ButtonC,
}
func (s ConjureControllerButton) String() string {
switch s {
case ButtonA:
return "ButtonA"
case ButtonB:
return "ButtonB"
case ButtonC:
return "ButtonC"
case Button1:
return "Button1"
case Button2:
return "Button2"
case Button3:
return "Button3"
case ButtonStart:
return "ButtonStart"
case ButtonPower:
return "ButtonPower"
default:
return "Unknown"
}
}
func Start(onStateChange func(ControllerState)) {
fmt.Println("Opening devices")
const vendorID = 0x0079
const productID = 0x0006
devices := hid.Enumerate(vendorID, productID)
if len(devices) == 0 {
fmt.Printf("Device with VID:PID %04X:%04X not found\n", vendorID, productID)
return
}
for i, d := range devices {
fmt.Printf("Found device %d: %s - VID:%04X PID:%04X\n", i, d.Product, d.VendorID, d.ProductID)
go func(i int, d hid.DeviceInfo) {
device, err := d.Open()
if err != nil {
fmt.Printf("Failed to open device %d: %v\n", i, err)
return
}
defer device.Close()
controller := Controller{Device: device}
buf := make([]byte, 32)
fmt.Printf("Reading data from device %d... Press Ctrl+C to exit\n", i)
for {
state, err := controller.ReadState(buf)
if err != nil {
fmt.Printf("Read error on device %d: %v\n", i, err)
return
}
state.Id = i
// TODO Samuel please fix help me
if (state.Buttons != 0 || state.Joystick.X != 127 || state.Joystick.Y != 127) && !(state.Id == 1 && state.Buttons == 128 && state.Joystick.X == 127 && state.Joystick.Y == 127) {
// fmt.Printf("Id: %d - %d buttons ", state.Id, state.Buttons)
onStateChange(*state)
}
}
}(i, d)
}
// Prevent the function from exiting
select {}
}
// handleJoystickEvent processes joystick events.
func handleJoystickEvent(e JoystickEvent) {
if e.Type&JS_EVENT_INIT != 0 {
// Ignore initial state events
return
}
if e.Type&JS_EVENT_BUTTON != 0 {
if e.Value == 1 {
fmt.Printf("Button %d pressed\n", e.Number)
} else {
fmt.Printf("Button %d released\n", e.Number)
}
}
if e.Type&JS_EVENT_AXIS != 0 {
fmt.Printf("Axis %d moved to %d\n", e.Number, e.Value)
}
}