From de62ed65c392626bc4d5182a0b07df320a581cca Mon Sep 17 00:00:00 2001 From: AhmedAmrNabil Date: Sun, 28 Jun 2026 04:43:33 +0300 Subject: [PATCH] feat(ds4): add updateFlags byte for output callback --- device/dualshock4/device.go | 1 + device/dualshock4/dualshock4_test.go | 4 +++- device/dualshock4/state.go | 19 +++++++++++-------- lib/viiper/dualshock4.go | 11 ++++++++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/device/dualshock4/device.go b/device/dualshock4/device.go index b48934d..29976dc 100644 --- a/device/dualshock4/device.go +++ b/device/dualshock4/device.go @@ -262,6 +262,7 @@ var featureGetHandlers = map[byte]func(*DualShock4) []byte{ func parseOutputReport(data []byte) OutputState { return OutputState{ + UpdateFlags: data[1], RumbleSmall: data[4], RumbleLarge: data[5], LedRed: data[6], diff --git a/device/dualshock4/dualshock4_test.go b/device/dualshock4/dualshock4_test.go index 30fe2fc..59d7a6e 100644 --- a/device/dualshock4/dualshock4_test.go +++ b/device/dualshock4/dualshock4_test.go @@ -397,6 +397,7 @@ func TestFeedback(t *testing.T) { { name: "off", outputState: dualshock4.OutputState{ + UpdateFlags: 0, RumbleSmall: 0, RumbleLarge: 0, LedRed: 0, @@ -410,6 +411,7 @@ func TestFeedback(t *testing.T) { { name: "rumble + led + flash", outputState: dualshock4.OutputState{ + UpdateFlags: 0x07, RumbleSmall: 0x12, RumbleLarge: 0xFE, LedRed: 0x01, @@ -418,7 +420,7 @@ func TestFeedback(t *testing.T) { FlashOn: 0x04, FlashOff: 0x05, }, - outPacket: []byte{0x05, 0x00, 0x00, 0x00, 0x12, 0xFE, 0x01, 0x02, 0x03, 0x04, 0x05}, + outPacket: []byte{0x05, 0x03, 0x00, 0x00, 0x12, 0xFE, 0x01, 0x02, 0x03, 0x04, 0x05}, }, } diff --git a/device/dualshock4/state.go b/device/dualshock4/state.go index ab58151..d0c88f5 100644 --- a/device/dualshock4/state.go +++ b/device/dualshock4/state.go @@ -99,6 +99,7 @@ func (s *InputState) UnmarshalBinary(data []byte) error { // nolint // viiper:wire dualshock4 s2c rumbleSmall:u8 rumbleLarge:u8 ledRed:u8 ledGreen:u8 ledBlue:u8 flashOn:u8 flashOff:u8 type OutputState struct { + UpdateFlags uint8 // (bit 0: rumble, bit 1: led, bit 2: flash) RumbleSmall uint8 // (0-255) RumbleLarge uint8 // (0-255) LedRed uint8 // (0-255) @@ -110,6 +111,7 @@ type OutputState struct { func (f *OutputState) MarshalBinary() ([]byte, error) { return []byte{ + f.UpdateFlags, f.RumbleSmall, f.RumbleLarge, f.LedRed, @@ -121,16 +123,17 @@ func (f *OutputState) MarshalBinary() ([]byte, error) { } func (f *OutputState) UnmarshalBinary(data []byte) error { - if len(data) < 7 { + if len(data) < 8 { return io.ErrUnexpectedEOF } - f.RumbleSmall = data[0] - f.RumbleLarge = data[1] - f.LedRed = data[2] - f.LedGreen = data[3] - f.LedBlue = data[4] - f.FlashOn = data[5] - f.FlashOff = data[6] + f.UpdateFlags = data[0] + f.RumbleSmall = data[1] + f.RumbleLarge = data[2] + f.LedRed = data[3] + f.LedGreen = data[4] + f.LedBlue = data[5] + f.FlashOn = data[6] + f.FlashOff = data[7] return nil } diff --git a/lib/viiper/dualshock4.go b/lib/viiper/dualshock4.go index c5122a3..db22c02 100644 --- a/lib/viiper/dualshock4.go +++ b/lib/viiper/dualshock4.go @@ -33,6 +33,10 @@ typedef uintptr_t DS4DeviceHandle; #define DS4_DPAD_UP_LEFT 0x07u #define DS4_DPAD_NEUTRAL 0x08u +#define DS4_OUTPUT_UPDATE_RUMBLE 0x01u +#define DS4_OUTPUT_UPDATE_LED 0x02u +#define DS4_OUTPUT_UPDATE_FLASH 0x04u + typedef struct { int8_t LX; int8_t LY; @@ -64,10 +68,10 @@ typedef struct { double BatteryVoltage; // 0 = use default } DS4MetaState; -typedef void (*DS4OutputCallback)(DS4DeviceHandle handle, uint8_t rumbleSmall, uint8_t rumbleLarge, uint8_t ledRed, uint8_t ledGreen, uint8_t ledBlue, uint8_t flashOn, uint8_t flashOff); +typedef void (*DS4OutputCallback)(DS4DeviceHandle handle,uint8_t updateFlags, uint8_t rumbleSmall, uint8_t rumbleLarge, uint8_t ledRed, uint8_t ledGreen, uint8_t ledBlue, uint8_t flashOn, uint8_t flashOff); -static void viiper_call_ds4_output(DS4OutputCallback fn, DS4DeviceHandle handle, uint8_t rumbleSmall, uint8_t rumbleLarge, uint8_t ledRed, uint8_t ledGreen, uint8_t ledBlue, uint8_t flashOn, uint8_t flashOff) { - fn(handle, rumbleSmall, rumbleLarge, ledRed, ledGreen, ledBlue, flashOn, flashOff); +static void viiper_call_ds4_output(DS4OutputCallback fn, DS4DeviceHandle handle,uint8_t updateFlags, uint8_t rumbleSmall, uint8_t rumbleLarge, uint8_t ledRed, uint8_t ledGreen, uint8_t ledBlue, uint8_t flashOn, uint8_t flashOff) { + fn(handle, updateFlags, rumbleSmall, rumbleLarge, ledRed, ledGreen, ledBlue, flashOn, flashOff); } */ @@ -238,6 +242,7 @@ func SetDS4OutputCallback(handle C.DS4DeviceHandle, cb C.DS4OutputCallback) bool } ds4device.SetOutputCallback(func(out dualshock4.OutputState) { C.viiper_call_ds4_output(cb, handle, + C.uint8_t(out.UpdateFlags), C.uint8_t(out.RumbleSmall), C.uint8_t(out.RumbleLarge), C.uint8_t(out.LedRed),