From f6ffa69890a21921ad5199505fbd7dc4333cb6d0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 May 2026 11:18:20 -0700 Subject: [PATCH] Add support for new Steam Controller input report on mobile devices --- .../app/HIDDeviceBLESteamController.java | 42 ++++++------ .../java/org/libsdl/app/HIDDeviceManager.java | 4 +- src/hidapi/android/hid.cpp | 25 +++----- src/hidapi/ios/hid.m | 64 +++++++++---------- src/joystick/hidapi/SDL_hidapi_steam_triton.c | 48 +++++++------- .../hidapi/steam/controller_structs.h | 8 +-- 6 files changed, 93 insertions(+), 98 deletions(-) diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java index e14a11bad1..ec13d0fdd5 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceBLESteamController.java @@ -44,6 +44,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe GattOperation mCurrentOperation = null; private Handler mHandler; private int mProductId = -1; + private int mReportId = 0; + private UUID mInputCharacteristic; private static final int D0G_BLE2_PID = 0x1106; private static final int TRITON_BLE_PID = 0x1303; @@ -57,7 +59,8 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3"); static final UUID inputCharacteristicD0G = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3"); - static final UUID inputCharacteristicTriton = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3"); + static final UUID inputCharacteristicTriton_0x45 = UUID.fromString("100F6C7A-1735-4313-B402-38567131E5F3"); + static final UUID inputCharacteristicTriton_0x47 = UUID.fromString("100F6C7C-1735-4313-B402-38567131E5F3"); static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3"); static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 }; @@ -352,16 +355,21 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe Log.v(TAG, "Found Valve steam controller service " + service.getUuid()); for (BluetoothGattCharacteristic chr : service.getCharacteristics()) { - boolean bShouldStartNotifications = false; - - if (chr.getUuid().equals(inputCharacteristicTriton)) { - Log.v(TAG, "Found Triton input characteristic"); + if (chr.getUuid().equals(inputCharacteristicTriton_0x45)) { + Log.v(TAG, "Found Triton input characteristic 0x45"); mProductId = TRITON_BLE_PID; - bShouldStartNotifications = true; + mReportId = 0x45; + mInputCharacteristic = chr.getUuid(); + } else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) { + Log.v(TAG, "Found Triton input characteristic 0x47"); + mProductId = TRITON_BLE_PID; + mReportId = 0x47; + mInputCharacteristic = chr.getUuid(); } else if (chr.getUuid().equals(inputCharacteristicD0G)) { Log.v(TAG, "Found D0G input characteristic"); mProductId = D0G_BLE2_PID; - bShouldStartNotifications = true; + mReportId = 0x03; + mInputCharacteristic = chr.getUuid(); } else { Pattern reportPattern = Pattern.compile("100F6C([0-9A-Z]{2})", Pattern.CASE_INSENSITIVE); Matcher matcher = reportPattern.matcher(chr.getUuid().toString()); @@ -382,8 +390,10 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe } } } + } - if (bShouldStartNotifications) { + for (BluetoothGattCharacteristic chr : service.getCharacteristics()) { + if (chr.getUuid().equals(mInputCharacteristic)) { // Start notifications BluetoothGattDescriptor cccd = chr.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); if (cccd != null) { @@ -590,7 +600,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe // Only register controller with the native side once it has been fully configured if (!isRegistered()) { Log.v(TAG, "Registering Steam Controller with ID: " + getId()); - mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true); + mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId); setRegistered(); } } @@ -603,7 +613,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe // Enable this for verbose logging of controller input reports //Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue())); - if (characteristic.getUuid().equals(getInputCharacteristic()) && !mFrozen) { + if (characteristic.getUuid().equals(mInputCharacteristic) && !mFrozen) { mHasSeenInputUpdate = true; mManager.HIDDeviceInputReport(getId(), characteristic.getValue()); } @@ -625,7 +635,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe if (getProductId() == TRITON_BLE_PID) { // For Triton we just mark things registered. Log.v(TAG, "Registering Triton Steam Controller with ID: " + getId()); - mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true); + mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true, mReportId); setRegistered(); } else { // For the original controller, we need to manually enter Valve mode. @@ -641,7 +651,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe BluetoothGattCharacteristic chr = descriptor.getCharacteristic(); //Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid()); - if (chr.getUuid().equals(getInputCharacteristic())) { + if (chr.getUuid().equals(mInputCharacteristic)) { mHasEnabledNotifications = true; enableValveMode(); } @@ -698,14 +708,6 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe return mProductId; } - private UUID getInputCharacteristic() { - if (getProductId() == TRITON_BLE_PID) { - return inputCharacteristicTriton; - } else { - return inputCharacteristicD0G; - } - } - @Override public String getSerialNumber() { // This will be read later via feature report by Steam diff --git a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 4b1fa5186d..691416c1c9 100644 --- a/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android-project/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -361,7 +361,7 @@ public class HIDDeviceManager { HIDDeviceUSB device = new HIDDeviceUSB(this, usbDevice, interface_index); int id = device.getId(); mDevicesById.put(id, device); - HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false); + HIDDeviceConnected(id, device.getIdentifier(), device.getVendorId(), device.getProductId(), device.getSerialNumber(), device.getVersion(), device.getManufacturerName(), device.getProductName(), usbInterface.getId(), usbInterface.getInterfaceClass(), usbInterface.getInterfaceSubclass(), usbInterface.getInterfaceProtocol(), false, 0); } } } @@ -688,7 +688,7 @@ public class HIDDeviceManager { private native void HIDDeviceRegisterCallback(); private native void HIDDeviceReleaseCallback(); - native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth); + native void HIDDeviceConnected(int deviceID, String identifier, int vendorId, int productId, String serial_number, int release_number, String manufacturer_string, String product_string, int interface_number, int interface_class, int interface_subclass, int interface_protocol, boolean bBluetooth, int reportID); native void HIDDeviceOpenPending(int deviceID); native void HIDDeviceOpenResult(int deviceID, boolean opened); native void HIDDeviceDisconnected(int deviceID); diff --git a/src/hidapi/android/hid.cpp b/src/hidapi/android/hid.cpp index 3f4f53cdd3..8b6abd97ae 100644 --- a/src/hidapi/android/hid.cpp +++ b/src/hidapi/android/hid.cpp @@ -434,10 +434,11 @@ static void ExceptionCheck( JNIEnv *env, const char *pszClassName, const char *p class CHIDDevice { public: - CHIDDevice( int nDeviceID, hid_device_info *pInfo ) + CHIDDevice( int nDeviceID, hid_device_info *pInfo, int nReportID ) { m_nId = nDeviceID; m_pInfo = pInfo; + m_nReportID = nReportID; // The Bluetooth Steam Controller needs special handling const int VALVE_USB_VID = 0x28DE; @@ -606,14 +607,7 @@ public: size_t nDataLen = buffer.size() > length ? length : buffer.size(); if ( m_bIsBLESteamController ) { - if ( m_pInfo->product_id == TRITON_BLE_PID ) - { - data[0] = 0x45; - } - else - { - data[0] = 0x03; - } + data[0] = m_nReportID; SDL_memcpy( data + 1, buffer.data(), nDataLen ); ++nDataLen; } @@ -788,6 +782,7 @@ private: pthread_mutex_t m_refCountLock = PTHREAD_MUTEX_INITIALIZER; int m_nRefCount = 0; int m_nId = 0; + int m_nReportID = 0; hid_device_info *m_pInfo = nullptr; hid_device *m_pDevice = nullptr; bool m_bIsBLESteamController = false; @@ -837,7 +832,7 @@ extern "C" JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz); extern "C" -JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth ); +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth, jint nReportID ); extern "C" JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, jint nDeviceID); @@ -917,7 +912,7 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallbac } extern "C" -JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth ) +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth, jint nReportID ) { LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface ); @@ -943,7 +938,7 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNI pInfo->bus_type = HID_API_BUS_USB; } - hid_device_ref pDevice( new CHIDDevice( nDeviceID, pInfo ) ); + hid_device_ref pDevice( new CHIDDevice( nDeviceID, pInfo, nReportID ) ); hid_mutex_guard l( &g_DevicesMutex ); hid_device_ref pLast, pCurr; @@ -1423,7 +1418,7 @@ extern "C" JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback)(JNIEnv *env, jobject thiz); extern "C" -JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth ); +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth, jint nReportID ); extern "C" JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, jint nDeviceID); @@ -1454,7 +1449,7 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallbac } extern "C" -JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth ) +JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, jint nDeviceID, jstring sIdentifier, jint nVendorId, jint nProductId, jstring sSerialNumber, jint nReleaseNumber, jstring sManufacturer, jstring sProduct, jint nInterface, jint nInterfaceClass, jint nInterfaceSubclass, jint nInterfaceProtocol, jboolean bBluetooth, jint nReportID ) { LOGV("Stub HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface); } @@ -1495,7 +1490,7 @@ extern "C" JNINativeMethod HIDDeviceManager_tab[8] = { { "HIDDeviceRegisterCallback", "()V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceRegisterCallback) }, { "HIDDeviceReleaseCallback", "()V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceReleaseCallback) }, - { "HIDDeviceConnected", "(ILjava/lang/String;IILjava/lang/String;ILjava/lang/String;Ljava/lang/String;IIIIZ)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected) }, + { "HIDDeviceConnected", "(ILjava/lang/String;IILjava/lang/String;ILjava/lang/String;Ljava/lang/String;IIIIZI)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected) }, { "HIDDeviceOpenPending", "(I)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending) }, { "HIDDeviceOpenResult", "(IZ)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenResult) }, { "HIDDeviceDisconnected", "(I)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceDisconnected) }, diff --git a/src/hidapi/ios/hid.m b/src/hidapi/ios/hid.m index 2c78227b0f..fe7b2e38db 100644 --- a/src/hidapi/ios/hid.m +++ b/src/hidapi/ios/hid.m @@ -78,7 +78,8 @@ typedef uint64_t uint64; // (READ/NOTIFICATIONS) #define VALVE_INPUT_CHAR_0x1106 @"100F6C33-1735-4313-B402-38567131E5F3" -#define VALVE_INPUT_CHAR_0x1303 @"100F6C7A-1735-4313-B402-38567131E5F3" +#define VALVE_INPUT_CHAR_0x1303_0x45 @"100F6C7A-1735-4313-B402-38567131E5F3" +#define VALVE_INPUT_CHAR_0x1303_0x47 @"100F6C7C-1735-4313-B402-38567131E5F3" //  (READ/WRITE) #define VALVE_REPORT_CHAR @"100F6C34-1735-4313-B402-38567131E5F3" @@ -220,6 +221,8 @@ typedef enum } @property (nonatomic, readwrite) uint16_t pid; +@property (nonatomic, readwrite) uint8_t report_id; +@property (nonatomic, readwrite) int report_length; @property (nonatomic, readwrite) bool connected; @property (nonatomic, readwrite) bool ready; @@ -523,7 +526,9 @@ static void process_pending_events(void) if ( self = [super init] ) { self.pid = 0; - _inputReports = NULL; + self.report_id = 0; + self.report_length = 0; + _inputReports = NULL; _outputReports = [[NSMutableDictionary alloc] init]; _connected = NO; _ready = NO; @@ -539,7 +544,9 @@ static void process_pending_events(void) if ( self = [super init] ) { self.pid = 0; - _inputReports = NULL; + self.report_id = 0; + self.report_length = 0; + _inputReports = NULL; _outputReports = [[NSMutableDictionary alloc] init]; _connected = NO; _ready = NO; @@ -583,17 +590,7 @@ static void process_pending_events(void) { if ( RingBuffer_read( _inputReports, dst+1 ) ) { - switch ( self.pid ) - { - case D0G_BLE2_PID: - *dst = 0x03; - break; - case TRITON_BLE_PID: - *dst = 0x45; - break; - default: - abort(); - } + *dst = self.report_id; return _inputReports->_cbElem + 1; } return 0; @@ -603,9 +600,9 @@ static void process_pending_events(void) { if ( self.pid == D0G_BLE2_PID ) { - [_bleSteamController writeValue:[NSData dataWithBytes:data length:length] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse]; - return (int)length; -} + [_bleSteamController writeValue:[NSData dataWithBytes:data length:length] forCharacteristic:_bleCharacteristicReport type:CBCharacteristicWriteWithResponse]; + return (int)length; + } // We need to look up the correct characteristic for this output report if ( length > 0 ) @@ -748,11 +745,22 @@ static void process_pending_events(void) if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR_0x1106]] ) { self.pid = D0G_BLE2_PID; + self.report_id = 0x03; + self.report_length = 19; self.bleCharacteristicInput = aChar; } - else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR_0x1303]] ) + else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR_0x1303_0x45]] ) { self.pid = TRITON_BLE_PID; + self.report_id = 0x45; + self.report_length = 45; + self.bleCharacteristicInput = aChar; + } + else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_INPUT_CHAR_0x1303_0x47]] ) + { + self.pid = TRITON_BLE_PID; + self.report_id = 0x47; + self.report_length = 45; self.bleCharacteristicInput = aChar; } else if ( [aChar.UUID isEqual:[CBUUID UUIDWithString:VALVE_REPORT_CHAR]] ) @@ -789,22 +797,10 @@ static void process_pending_events(void) if ( self.ready == NO ) { self.ready = YES; - if ( _inputReports == NULL ) - { - int cbElem = 0; - switch ( self.pid ) - { - case D0G_BLE2_PID: - cbElem = 19; - break; - case TRITON_BLE_PID: - cbElem = 45; - break; - default: - abort(); - } - _inputReports = RingBuffer_alloc( cbElem ); - } + if ( _inputReports == NULL ) + { + _inputReports = RingBuffer_alloc( self.report_length ); + } HIDBLEManager.sharedInstance.nPendingPairs -= 1; } diff --git a/src/joystick/hidapi/SDL_hidapi_steam_triton.c b/src/joystick/hidapi/SDL_hidapi_steam_triton.c index 92cd1e703e..7cf2845652 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam_triton.c +++ b/src/joystick/hidapi/SDL_hidapi_steam_triton.c @@ -96,7 +96,8 @@ typedef struct { bool connected; bool report_sensors; - Uint32 last_sensor_tick; + Uint16 last_sensor_tick16; + Uint32 last_sensor_tick32; Uint64 sensor_timestamp_ns; Uint64 last_button_state; Uint64 last_lizard_update; @@ -139,7 +140,7 @@ static bool DisableSteamTritonLizardMode(SDL_hid_device *dev) // Triton newer state MTUs are identical until touchpads. Parse them using this routine. // Expects report to be a TritonMTUNoQuat_t, so cast as needed -static void Parse_SteamTriton_HandleGenericState( SDL_DriverSteamTriton_Context* ctx, SDL_Joystick* joystick, Uint64 timestamp, TritonMTUNoQuat_t* pTritonReport ) +static void HIDAPI_DriverSteamTriton_HandleGenericState(SDL_DriverSteamTriton_Context *ctx, SDL_Joystick *joystick, Uint64 timestamp, TritonMTUNoQuat_t *pTritonReport) { if (pTritonReport->buttons != ctx->last_button_state) { Uint8 hat = 0; @@ -213,11 +214,11 @@ static void Parse_SteamTriton_HandleGenericState( SDL_DriverSteamTriton_Context* ctx->last_button_state = pTritonReport->buttons; } - SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (int)pTritonReport->sTriggerLeft * 2 - 32768); SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, (int)pTritonReport->sTriggerRight * 2 - 32768); - SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, + SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, pTritonReport->sLeftStickX); SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, -pTritonReport->sLeftStickY); @@ -228,19 +229,19 @@ static void Parse_SteamTriton_HandleGenericState( SDL_DriverSteamTriton_Context* } static void HIDAPI_DriverSteamTriton_HandleState(SDL_HIDAPI_Device *device, - SDL_Joystick *joystick, - TritonMTUNoQuat_t *pTritonReport) + SDL_Joystick *joystick, + TritonMTUNoQuat_t *pTritonReport) { float values[3]; SDL_DriverSteamTriton_Context *ctx = (SDL_DriverSteamTriton_Context *)device->context; Uint64 timestamp = SDL_GetTicksNS(); - Parse_SteamTriton_HandleGenericState(ctx, joystick, timestamp, pTritonReport); + HIDAPI_DriverSteamTriton_HandleGenericState(ctx, joystick, timestamp, pTritonReport); bool left_touch_down = (pTritonReport->buttons & TRITON_LEFT_TOUCHPAD_TOUCH) ? true : false; bool right_touch_down = (pTritonReport->buttons & TRITON_RIGHT_TOUCHPAD_TOUCH) ? true : false; - if (left_touch_down || ctx->left_touch_down) { + if (left_touch_down || ctx->left_touch_down) { if (left_touch_down) { ctx->left_touch_x = pTritonReport->sLeftPadX / 65536.0f + 0.5f; ctx->left_touch_y = -(float)pTritonReport->sLeftPadY / 65536.0f + 0.5f; @@ -249,7 +250,7 @@ static void HIDAPI_DriverSteamTriton_HandleState(SDL_HIDAPI_Device *device, left_touch_down, ctx->left_touch_x, ctx->left_touch_y, - pTritonReport->ucPressureLeft / 32768.0f); + pTritonReport->unPressureLeft / 32768.0f); ctx->left_touch_down = left_touch_down; } if (right_touch_down || ctx->right_touch_down) { @@ -261,12 +262,12 @@ static void HIDAPI_DriverSteamTriton_HandleState(SDL_HIDAPI_Device *device, right_touch_down, ctx->right_touch_x, ctx->right_touch_y, - pTritonReport->ucPressureRight / 32768.0f); + pTritonReport->unPressureRight / 32768.0f); ctx->right_touch_down = right_touch_down; } - if (ctx->report_sensors && pTritonReport->imu.timestamp != ctx->last_sensor_tick) { - Uint32 delta_us = (pTritonReport->imu.timestamp - ctx->last_sensor_tick); + if (ctx->report_sensors && pTritonReport->imu.timestamp != ctx->last_sensor_tick32) { + Uint32 delta_us = (pTritonReport->imu.timestamp - ctx->last_sensor_tick32); ctx->sensor_timestamp_ns += SDL_US_TO_NS(delta_us); @@ -280,19 +281,19 @@ static void HIDAPI_DriverSteamTriton_HandleState(SDL_HIDAPI_Device *device, values[2] = (-pTritonReport->imu.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp_ns, values, 3); - ctx->last_sensor_tick = pTritonReport->imu.timestamp; + ctx->last_sensor_tick32 = pTritonReport->imu.timestamp; } } -// New Ibex MTU has IMU data in + static void HIDAPI_DriverSteamTriton_HandleState_Timestamp(SDL_HIDAPI_Device *device, - SDL_Joystick *joystick, + SDL_Joystick *joystick, TritonMTUNoQuat32TS_t *pTritonReport) { float values[3]; SDL_DriverSteamTriton_Context *ctx = (SDL_DriverSteamTriton_Context *)device->context; Uint64 timestamp = SDL_GetTicksNS(); - Parse_SteamTriton_HandleGenericState(ctx, joystick, timestamp, (TritonMTUNoQuat_t *) pTritonReport); + HIDAPI_DriverSteamTriton_HandleGenericState(ctx, joystick, timestamp, (TritonMTUNoQuat_t *) pTritonReport); bool left_touch_down = (pTritonReport->buttons & TRITON_LEFT_TOUCHPAD_TOUCH) ? true : false; bool right_touch_down = (pTritonReport->buttons & TRITON_RIGHT_TOUCHPAD_TOUCH) ? true : false; @@ -322,8 +323,9 @@ static void HIDAPI_DriverSteamTriton_HandleState_Timestamp(SDL_HIDAPI_Device *de ctx->right_touch_down = right_touch_down; } - if (ctx->report_sensors && pTritonReport->imu.timestamp != ctx->last_sensor_tick) { - Uint32 delta_us = (pTritonReport->imu.timestamp - ctx->last_sensor_tick); + if (ctx->report_sensors && pTritonReport->imu.timestamp != ctx->last_sensor_tick16) { + // The timestamp is in units of 32 microseconds + Uint32 delta_us = (Uint32)(pTritonReport->imu.timestamp - ctx->last_sensor_tick16) * 32; ctx->sensor_timestamp_ns += SDL_US_TO_NS(delta_us); @@ -337,7 +339,7 @@ static void HIDAPI_DriverSteamTriton_HandleState_Timestamp(SDL_HIDAPI_Device *de values[2] = (-pTritonReport->imu.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; SDL_SendJoystickSensor(timestamp, joystick, SDL_SENSOR_ACCEL, ctx->sensor_timestamp_ns, values, 3); - ctx->last_sensor_tick = pTritonReport->imu.timestamp; + ctx->last_sensor_tick16 = pTritonReport->imu.timestamp; } } @@ -438,8 +440,8 @@ static bool HIDAPI_DriverSteamTriton_IsSupportedDevice( return true; } } else if (SDL_IsJoystickSteamTriton(vendor_id, product_id)) { - return true; - } + return true; + } return false; } @@ -537,7 +539,7 @@ static bool HIDAPI_DriverSteamTriton_UpdateDevice(SDL_HIDAPI_Device *device) HIDAPI_DriverSteamTriton_HandleState_Timestamp(device, joystick, pTritonReport); } break; - case ID_TRITON_BATTERY_STATUS: + case ID_TRITON_BATTERY_STATUS: if (joystick && r >= (1 + sizeof(TritonBatteryStatus_t))) { TritonBatteryStatus_t *pTritonBatteryStatus = (TritonBatteryStatus_t *)&data[1]; HIDAPI_DriverSteamTriton_HandleBatteryStatus(device, joystick, pTritonBatteryStatus); @@ -593,7 +595,7 @@ static bool HIDAPI_DriverSteamTriton_RumbleJoystick(SDL_HIDAPI_Device *device, S Uint8 buffer[HID_RUMBLE_OUTPUT_REPORT_BYTES] = { 0 }; OutputReportMsg *msg = (OutputReportMsg *)(buffer); - msg->report_id = ID_OUT_REPORT_HAPTIC_RUMBLE; + msg->report_id = ID_OUT_REPORT_HAPTIC_RUMBLE; msg->payload.hapticRumble.type = 0; msg->payload.hapticRumble.intensity = 0; msg->payload.hapticRumble.left.speed = low_frequency_rumble; diff --git a/src/joystick/hidapi/steam/controller_structs.h b/src/joystick/hidapi/steam/controller_structs.h index 3f707d7f5b..69c10ed689 100644 --- a/src/joystick/hidapi/steam/controller_structs.h +++ b/src/joystick/hidapi/steam/controller_structs.h @@ -620,11 +620,11 @@ typedef struct short sLeftPadX; short sLeftPadY; - unsigned short ucPressureLeft; + unsigned short unPressureLeft; short sRightPadX; short sRightPadY; - unsigned short ucPressureRight; + unsigned short unPressureRight; TritonMTUIMU_t imu; } TritonMTUFull_t; @@ -641,11 +641,11 @@ typedef struct { short sLeftPadX; short sLeftPadY; - unsigned short ucPressureLeft; + unsigned short unPressureLeft; short sRightPadX; short sRightPadY; - unsigned short ucPressureRight; + unsigned short unPressureRight; TritonMTUIMUNoQuat_t imu; } TritonMTUNoQuat_t;