[PATCH v2] winebus.sys: Allow XBOX Masquerade to be turned off

Brendan McGrath brendan at redmandi.com
Mon Nov 19 18:29:44 CST 2018


Elite Dangerous appears to iterate input devices via
DInput and will only defer to XInput if there is a
HID device with a matching VID and PID.

The current behaviour of the SDLBUS is to masquerade
any controller as an XBOX controller. This causes
Elite Dangerous to treat any other type of contoller
as a Joystick.

This patch allows this masquerading behaviour to be
switched off via two REG_DWORD registry entries under
HKLM\System\CurrentControlSet\Services\SDLJOY:
- 'Controller VID'
- 'Controller PID'

0 - Turns it off (so it uses the real VID and PID)

Any other value will define the value used in the masquerade.

If the values are missing, the default behaviour is to leave
it as is (i.e an XBOX controller).

Signed-off-by: Brendan McGrath <brendan at redmandi.com>
---
Changes since v2:
  - allow VID and PID to be defined (as well as switched off)
  - use the existing SDLJOY registry entry

I'm using a Logitech F310 gamepad. SDL recognises it as a controller
but Elite Dangerous ignores it (due to the masquerade).

At the moment, if 'Map Controllers' is set to '1' - the
VID and PID is hard-coded to be an XBOX controller (I'm not familiar with
the history to understand why that is - but I suspect for better game support).

So I would say the device is able to be programmatically recognised by using the
the SDL_IsGameController API. But this is currently only used when 'Map Controllers' is set
to '1' and thus the real VID and PID values are lost (note that Proton does not have this
masquerade thus the controller is working).

When I set 'Map Controllers' to '0' - the correct VID and PID are added, but not as
a gamepad (it uses an 'IM' entry instead of 'IG'). So again Elite Dangerous ignores the entry.

This is because my controller reports 11 buttons where as the code expects a gamepad to report
14 or more.

I changed it to look for 10 and a hat and this worked - but the mapping was all wrong. This
is an approach I could explore further - but I feel the SDL_IsGameController approach is already
working - but for the masquerade.

 dlls/winebus.sys/bus_sdl.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/dlls/winebus.sys/bus_sdl.c b/dlls/winebus.sys/bus_sdl.c
index 6b2b28e8c90..86e652faa14 100644
--- a/dlls/winebus.sys/bus_sdl.c
+++ b/dlls/winebus.sys/bus_sdl.c
@@ -84,6 +84,8 @@ static DRIVER_OBJECT *sdl_driver_obj = NULL;
 static const WCHAR sdl_busidW[] = {'S','D','L','J','O','Y',0};
 
 static DWORD map_controllers = 0;
+static DWORD controller_vid = 0;
+static DWORD controller_pid = 0;
 
 #include "initguid.h"
 DEFINE_GUID(GUID_DEVCLASS_SDL, 0x463d60b5,0x802b,0x4bb2,0x8f,0xdb,0x7d,0xa9,0xb9,0x96,0x04,0xd8);
@@ -820,9 +822,9 @@ static void try_add_device(SDL_JoystickID index)
     id = pSDL_JoystickInstanceID(joystick);
     if (controller)
     {
-        vid = VID_MICROSOFT;
-        pid = PID_XBOX_CONTROLLERS[3];
-        version = 0x01;
+        vid = (controller_vid) ? controller_vid : pSDL_JoystickGetVendor(joystick);
+        pid = (controller_pid) ? controller_pid : pSDL_JoystickGetProduct(joystick);
+        version = (controller_vid || controller_pid) ? 0x01 : pSDL_JoystickGetProductVersion(joystick);
     }
     else
     {
@@ -935,7 +937,11 @@ void sdl_driver_unload( void )
 NTSTATUS WINAPI sdl_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_path)
 {
     static const WCHAR controller_modeW[] = {'M','a','p',' ','C','o','n','t','r','o','l','l','e','r','s',0};
+    static const WCHAR controller_vid_valueW[] = {'C','o','n','t','r','o','l','l','e','r',' ','V','I','D',0};
+    static const WCHAR controller_pid_valueW[] = {'C','o','n','t','r','o','l','l','e','r',' ','P','I','D',0};
     static const UNICODE_STRING controller_mode = {sizeof(controller_modeW) - sizeof(WCHAR), sizeof(controller_modeW), (WCHAR*)controller_modeW};
+    static const UNICODE_STRING controller_vid_value = {sizeof(controller_vid_valueW) - sizeof(WCHAR), sizeof(controller_vid_valueW), (WCHAR*)controller_vid_valueW};
+    static const UNICODE_STRING controller_pid_value = {sizeof(controller_pid_valueW) - sizeof(WCHAR), sizeof(controller_pid_valueW), (WCHAR*)controller_pid_valueW};
 
     HANDLE events[2];
     DWORD result;
@@ -993,6 +999,8 @@ NTSTATUS WINAPI sdl_driver_init(DRIVER_OBJECT *driver, UNICODE_STRING *registry_
     driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = hid_internal_dispatch;
 
     map_controllers = check_bus_option(registry_path, &controller_mode, 1);
+    controller_vid = check_bus_option(registry_path, &controller_vid_value, VID_MICROSOFT);
+    controller_pid = check_bus_option(registry_path, &controller_pid_value, PID_XBOX_CONTROLLERS[3]);
 
     if (!(events[0] = CreateEventW(NULL, TRUE, FALSE, NULL)))
         goto error;
-- 
2.17.1




More information about the wine-devel mailing list