conjure-os/lib/inputs/joystick.go

199 lines
3.8 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 {
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
// Enumerate all matching devices
devices := hid.Enumerate(vendorID, productID)
if len(devices) == 0 {
fmt.Printf("Device with VID:PID %04X:%04X not found", vendorID, productID)
return
}
for _, d := range devices {
fmt.Printf("Found: %s - VID:%04X PID:%04X\n", d.Product, d.VendorID, d.ProductID)
}
// Open the first matching device
for i, deviceDetected := range devices {
fmt.Printf("device %d detected\n", i)
device, err := deviceDetected.Open()
if err != nil {
fmt.Printf("Failed to open device: %v", err)
return
}
defer device.Close()
controller := Controller{Device: device}
fmt.Println("Reading data... Press Ctrl+C to exit")
buf := make([]byte, 32) // Adjust size if needed
for {
state, err := controller.ReadState(buf)
if err != nil {
fmt.Printf("Read error: %v", err)
return
}
if state.Buttons != 0 || state.Joystick.X != 127 || state.Joystick.Y != 127 {
fmt.Printf("State changed on device %d\n", i)
onStateChange(*state)
}
}
}
fmt.Println("Out")
// Open the joystick device file
// file, err := os.Open("/dev/input/js0")
// if err != nil {
// fmt.Println("Error opening joystick:", err)
// return
// }
// defer file.Close()
// // Continuously read joystick events
// for {
// var e JoystickEvent
// err := binary.Read(file, binary.LittleEndian, &e)
// if err != nil {
// fmt.Println("Error reading joystick event:", err)
// return
// }
// // Handle the event
// handleJoystickEvent(e)
// // Sleep to avoid flooding output
// time.Sleep(10 * time.Millisecond)
// }
}
// 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)
}
}