From 05d140a128c50427ebcd30d00cf89eabb79fdc41 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 28 May 2026 11:18:20 -0700
Subject: [PATCH] Add support for new Steam Controller input report on mobile
devices
(cherry picked from commit f6ffa69890a21921ad5199505fbd7dc4333cb6d0)
---
.../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 e14a11bad1b3e..ec13d0fdd5a67 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 @@ private boolean probeService(HIDDeviceBLESteamController controller) {
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;
+ mReportId = 0x45;
+ mInputCharacteristic = chr.getUuid();
+ } else if (chr.getUuid().equals(inputCharacteristicTriton_0x47)) {
+ Log.v(TAG, "Found Triton input characteristic 0x47");
mProductId = TRITON_BLE_PID;
- bShouldStartNotifications = true;
+ 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 @@ private boolean probeService(HIDDeviceBLESteamController controller) {
}
}
}
+ }
- 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 @@ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristi
// 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 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris
// 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 @@ private void enableValveMode()
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 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri
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 @@ public int getProductId() {
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 4b1fa5186d64d..691416c1c92cd 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 @@ private void connectHIDDeviceUSB(UsbDevice usbDevice) {
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 @@ void closeDevice(int deviceID) {
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 3f4f53cdd377e..8b6abd97aeca6 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 @@ class CHIDDevice
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 @@ class CHIDDevice
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<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );
+ hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo, nReportID ) );
hid_mutex_guard l( &g_DevicesMutex );
hid_device_ref<CHIDDevice> 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 2c78227b0ffe5..fe7b2e38dba3f 100644
--- a/src/hidapi/ios/hid.m
+++ b/src/hidapi/ios/hid.m
@@ -78,7 +78,8 @@
// (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 @@ @interface HIDBLEDevice : NSObject <CBPeripheralDelegate>
}
@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 @@ - (id)init
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 @@ - (id)initWithPeripheral:(CBPeripheral *)peripheral
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 @@ - (size_t)read_input_report:(uint8_t *)dst
{
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 @@ - (int)send_report:(const uint8_t *)data length:(size_t)length
{
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 @@ - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForServi
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 @@ - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(C
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 6468c4885757b..4d8d8238b7fed 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam_triton.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam_triton.c
@@ -100,7 +100,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;
@@ -143,7 +144,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;
@@ -217,11 +218,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);
@@ -232,19 +233,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;
@@ -253,7 +254,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) {
@@ -265,12 +266,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);
@@ -284,19 +285,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;
@@ -326,8 +327,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);
@@ -341,7 +343,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;
}
}
@@ -442,8 +444,8 @@ static bool HIDAPI_DriverSteamTriton_IsSupportedDevice(
return true;
}
} else if (SDL_IsJoystickSteamTriton(vendor_id, product_id)) {
- return true;
- }
+ return true;
+ }
return false;
}
@@ -541,7 +543,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);
@@ -592,7 +594,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 3f707d7f5b4c1..69c10ed689f5b 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;