From 37b87f79fbd88cae1b730f73c83bfbff9f8c13f6 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 23 Dec 2024 12:55:25 -0800
Subject: [PATCH] Fixed Bluetooth Steam Controller detection on iOS and Android
---
.../app/HIDDeviceBLESteamController.java | 2 +-
.../java/org/libsdl/app/HIDDeviceManager.java | 4 ++--
src/hidapi/android/hid.cpp | 18 +++++++++++++-----
src/hidapi/ios/hid.m | 1 +
src/joystick/hidapi/SDL_hidapi_steam.c | 4 ++++
5 files changed, 21 insertions(+), 8 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 a7b85d0cf8575..d2dc0d2309601 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
@@ -470,7 +470,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);
+ mManager.HIDDeviceConnected(getId(), getIdentifier(), getVendorId(), getProductId(), getSerialNumber(), getVersion(), getManufacturerName(), getProductName(), 0, 0, 0, 0, true);
setRegistered();
}
}
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 fe791432ffdad..37d80ca06b32a 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
@@ -355,7 +355,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());
+ 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);
}
}
}
@@ -679,7 +679,7 @@ public 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);
+ 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 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 da6a78c67a26d..1e43aa73f1d12 100644
--- a/src/hidapi/android/hid.cpp
+++ b/src/hidapi/android/hid.cpp
@@ -810,7 +810,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, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol );
+JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol, bool bBluetooth );
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
@@ -890,7 +890,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, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol )
+JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol, bool bBluetooth )
{
LOGV( "HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface );
@@ -907,6 +907,14 @@ JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNI
pInfo->interface_class = nInterfaceClass;
pInfo->interface_subclass = nInterfaceSubclass;
pInfo->interface_protocol = nInterfaceProtocol;
+ if ( bBluetooth )
+ {
+ pInfo->bus_type = HID_API_BUS_BLUETOOTH;
+ }
+ else
+ {
+ pInfo->bus_type = HID_API_BUS_USB;
+ }
hid_device_ref<CHIDDevice> pDevice( new CHIDDevice( nDeviceID, pInfo ) );
@@ -1388,7 +1396,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, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol );
+JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol, bool bBluetooth );
extern "C"
JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceOpenPending)(JNIEnv *env, jobject thiz, int nDeviceID);
@@ -1419,7 +1427,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, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol )
+JNIEXPORT void JNICALL HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected)(JNIEnv *env, jobject thiz, int nDeviceID, jstring sIdentifier, int nVendorId, int nProductId, jstring sSerialNumber, int nReleaseNumber, jstring sManufacturer, jstring sProduct, int nInterface, int nInterfaceClass, int nInterfaceSubclass, int nInterfaceProtocol, bool bBluetooth )
{
LOGV("Stub HIDDeviceConnected() id=%d VID/PID = %.4x/%.4x, interface %d\n", nDeviceID, nVendorId, nProductId, nInterface);
}
@@ -1460,7 +1468,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;IIII)V", (void*)HID_DEVICE_MANAGER_JAVA_INTERFACE(HIDDeviceConnected) },
+ { "HIDDeviceConnected", "(ILjava/lang/String;IILjava/lang/String;ILjava/lang/String;Ljava/lang/String;IIIIZ)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 bfa375c18b657..d0a8b54d240ac 100644
--- a/src/hidapi/ios/hid.m
+++ b/src/hidapi/ios/hid.m
@@ -853,6 +853,7 @@ int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
device_info->product_id = D0G_BLE2_PID;
device_info->product_string = wcsdup( L"Steam Controller" );
device_info->manufacturer_string = wcsdup( L"Valve Corporation" );
+ device_info->bus_type = HID_API_BUS_BLUETOOTH;
return device_info;
}
diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c
index d05344f5e3c21..43e958761a7b0 100644
--- a/src/joystick/hidapi/SDL_hidapi_steam.c
+++ b/src/joystick/hidapi/SDL_hidapi_steam.c
@@ -1038,6 +1038,10 @@ static bool HIDAPI_DriverSteam_IsSupportedDevice(SDL_HIDAPI_Device *device, cons
return false;
}
+ if (device->is_bluetooth) {
+ return true;
+ }
+
if (IsDongle(product_id)) {
if (interface_number >= 1 && interface_number <= 4) {
// This is one of the wireless controller interfaces