207 lines
4.0 KiB
Go
207 lines
4.0 KiB
Go
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() error {
|
||
buf := make([]byte, 64)
|
||
_, err := c.Device.Read(buf)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
|
||
fmt.Printf("Joystick: X=%d Y=%d Buttons=%08b\n", buf[0], buf[1], buf[6])
|
||
return nil
|
||
}
|
||
|
||
type Vec2B struct {
|
||
X, Y byte
|
||
}
|
||
|
||
type ControllerState struct {
|
||
joystick Vec2B
|
||
buttons byte
|
||
}
|
||
|
||
type ConjureControllerButton int
|
||
|
||
const (
|
||
ButtonA ConjureControllerButton = iota //0
|
||
ButtonB
|
||
ButtonC
|
||
|
||
Button1
|
||
Button2
|
||
Button3
|
||
|
||
ButtonStart
|
||
ButtonPower // 7
|
||
)
|
||
|
||
var ConjureControllerButtons = []ConjureControllerButton{
|
||
ButtonA,
|
||
ButtonB,
|
||
ButtonC,
|
||
|
||
Button1,
|
||
Button2,
|
||
Button3,
|
||
|
||
ButtonStart,
|
||
ButtonPower,
|
||
}
|
||
|
||
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(any)) {
|
||
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
|
||
device, err := devices[0].Open()
|
||
if err != nil {
|
||
fmt.Printf("Failed to open device: %v", err)
|
||
return
|
||
}
|
||
defer device.Close()
|
||
|
||
fmt.Println("Reading data... Press Ctrl+C to exit")
|
||
|
||
buf := make([]byte, 32) // Adjust size if needed
|
||
for {
|
||
_, err := device.Read(buf)
|
||
if err != nil {
|
||
fmt.Printf("Read error: %v", err)
|
||
return
|
||
}
|
||
|
||
// For debugging: print raw data
|
||
// fmt.Printf("Raw: % X\n", buf[:n])
|
||
|
||
// Example: decode joystick + button state
|
||
x := buf[0] // Horizontal axis (0–255)
|
||
y := buf[1] // Vertical axis (0–255)
|
||
buttons := buf[6] // Buttons as bitfield
|
||
state := ControllerState{
|
||
joystick: Vec2B{x, y},
|
||
buttons: buttons,
|
||
}
|
||
|
||
// fmt.Printf("Joystick X: %d, Y: %d, Buttons: %08b\n", x, y, buttons)
|
||
|
||
if buttons != 0 {
|
||
for _, button := range ConjureControllerButtons {
|
||
if buttons&(1<<button) != 0 {
|
||
fmt.Printf("Button %s pressed\n", (button + 1).String())
|
||
}
|
||
}
|
||
onStateChange(state)
|
||
fmt.Printf("Button was pressed! %d\n", buttons)
|
||
}
|
||
|
||
if x != 127 || y != 127 {
|
||
onStateChange(state)
|
||
fmt.Printf("Joystick moved! %d - %d\n", x, y)
|
||
}
|
||
}
|
||
|
||
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)
|
||
}
|
||
}
|