Procházet zdrojové kódy

Detect steam virtual gamepads more accurately on macOS

tmkk před 1 týdnem
rodič
revize
bbcc205de9

+ 16 - 1
src/hidapi/mac/hid.c

@@ -573,6 +573,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev,
 {
 	unsigned short dev_vid;
 	unsigned short dev_pid;
+	unsigned short dev_version;
 	int BUF_LEN = 256;
 	wchar_t buf[BUF_LEN];
 	CFTypeRef transport_prop;
@@ -593,6 +594,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev,
 
 	dev_vid = get_vendor_id(dev);
 	dev_pid = get_product_id(dev);
+	dev_version = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
 
 #ifdef HIDAPI_IGNORE_DEVICE
 	/* See if there are any devices we should skip in enumeration */
@@ -602,6 +604,19 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev,
 	}
 #endif
 
+#ifdef HIDAPI_USING_SDL_RUNTIME
+	if (IOHIDDeviceGetProperty(dev, CFSTR(kIOHIDVirtualHIDevice)) == kCFBooleanTrue) {
+		/* Steam virtual gamepads always have kIOHIDVirtualHIDevice property unlike real devices */
+		if (SDL_IsJoystickSteamVirtualGamepad(dev_vid, dev_pid, dev_version)) {
+			const char *allow_steam_virtual_gamepad = SDL_getenv_unsafe("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD");
+			if (!SDL_GetStringBoolean(allow_steam_virtual_gamepad, false)) {
+				free(cur_dev);
+				return NULL;
+			}
+		}
+	}
+#endif
+
 	cur_dev->usage_page = usage_page;
 	cur_dev->usage = usage;
 
@@ -649,7 +664,7 @@ static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev,
 	cur_dev->product_id = dev_pid;
 
 	/* Release Number */
-	cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
+	cur_dev->release_number = dev_version;
 
 	/* Interface Number.
 	 * We can only retrieve the interface number for USB HID devices.

+ 6 - 0
src/joystick/SDL_gamepad.c

@@ -3256,6 +3256,11 @@ bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version
         }
     }
 
+#ifdef SDL_PLATFORM_MACOS
+    // On macOS do nothing here since we detect Steam virtual gamepads
+    // in IOKit HID backends to ensure accuracy.
+    // See joystick/darwin/SDL_iokitjoystick.c and hidapi/mac/hid.c.
+#else
     const char *hint = SDL_getenv_unsafe("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD");
     bool allow_steam_virtual_gamepad = SDL_GetStringBoolean(hint, false);
 #ifdef SDL_PLATFORM_WIN32
@@ -3271,6 +3276,7 @@ bool SDL_ShouldIgnoreGamepad(Uint16 vendor_id, Uint16 product_id, Uint16 version
     if (SDL_IsJoystickSteamVirtualGamepad(vendor_id, product_id, version)) {
         return !allow_steam_virtual_gamepad;
     }
+#endif
 
     if (SDL_allowed_gamepads.num_included_entries > 0) {
         if (SDL_VIDPIDInList(vendor_id, product_id, &SDL_allowed_gamepads)) {

+ 11 - 0
src/joystick/darwin/SDL_iokitjoystick.c

@@ -28,6 +28,7 @@
 #include "../hidapi/SDL_hidapijoystick_c.h"
 #include "../../haptic/darwin/SDL_syshaptic_c.h" // For haptic hot plugging
 #include "../usb_ids.h"
+#include "../../SDL_hints_c.h"
 #include <IOKit/IOKitLib.h>
 
 #define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
@@ -515,6 +516,16 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice)
         return false;
     }
 
+    if (IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVirtualHIDevice)) == kCFBooleanTrue) {
+        // Steam virtual gamepads always have kIOHIDVirtualHIDevice property unlike real devices
+        if (SDL_IsJoystickSteamVirtualGamepad(vendor, product, version)) {
+            const char *allow_steam_virtual_gamepad = SDL_getenv_unsafe("SDL_GAMECONTROLLER_ALLOW_STEAM_VIRTUAL_GAMEPAD");
+            if (!SDL_GetStringBoolean(allow_steam_virtual_gamepad, false)) {
+                return false;
+            }
+        }
+    }
+
     // get device name
     refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDManufacturerKey));
     if ((!refCF) || (!CFStringGetCString(refCF, manufacturer_string, sizeof(manufacturer_string), kCFStringEncodingUTF8))) {