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@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;
On 11/19/2018 06:29 PM, Brendan McGrath wrote:
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@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.
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
Here's the commit from Proton that removed the masquerade. Native xinput wasn't something I had thought of. That could be why it's there.
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput requires it. Our built-in xinput is good enough now, though, so let's keep the real VID/PID. This lets applications match setupapi devices with dinput devices, see:
"XInput and DirectInput" https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
On Tue, Nov 20, 2018 at 12:53:21PM +1100, Brendan McGrath wrote:
Here's the commit from Proton that removed the masquerade. Native xinput wasn't something I had thought of. That could be why it's there.
Oh yeah, I remember that now. I wonder if the right answer isn't just to apply that same change to Wine.
Andrew
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput requires it. Our built-in xinput is good enough now, though, so let's keep the real VID/PID. This lets applications match setupapi devices with dinput devices, see:
"XInput and DirectInput" https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
It looks to me like Elite is doing exactly what is described in your link - so that change fixes my problem. So I'm happy to ditch this patch in favour of that.
On 21 November 2018 12:56:31 am AEDT, Andrew Eikum aeikum@codeweavers.com wrote:
On Tue, Nov 20, 2018 at 12:53:21PM +1100, Brendan McGrath wrote:
Here's the commit from Proton that removed the masquerade. Native
xinput
wasn't something I had thought of. That could be why it's there.
Oh yeah, I remember that now. I wonder if the right answer isn't just to apply that same change to Wine.
Andrew
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput
requires
it. Our built-in xinput is good enough now, though, so let's keep
the
real VID/PID. This lets applications match setupapi devices with
dinput
devices, see:
"XInput and DirectInput"
https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and
play.
To match Windows functionality would be to remove the masquerade
(as
Proton has). That would fix my problem - but potentially create an
issue
for other games that are dependant on this masquerade (although I'm
not
familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it
default
to use the real VID and PID. Then it matches Windows but there is
still
an option for those who need the masquerade (and they can choose
the
device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the
approach
we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should
fix
it to work.
At the same time, as regards your original problem, we should
look
to rewrite the dinput joystick code on top of Wine's HID stack,
so
that it will report the same VID/PID as xinput does. I believe
Aric
is working on some patches to this effect ;-)
As original author of the code I do believe it was to support native XInput.
If our builtin XInput is good enough then this change is just fine.
-aric
On 11/20/18 7:56 AM, Andrew Eikum wrote:
On Tue, Nov 20, 2018 at 12:53:21PM +1100, Brendan McGrath wrote:
Here's the commit from Proton that removed the masquerade. Native xinput wasn't something I had thought of. That could be why it's there.
Oh yeah, I remember that now. I wonder if the right answer isn't just to apply that same change to Wine.
Andrew
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput requires it. Our built-in xinput is good enough now, though, so let's keep the real VID/PID. This lets applications match setupapi devices with dinput devices, see:
"XInput and DirectInput" https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
Thanks for the confirmation Aric.
So what's the procedure for getting Andrew's commit in to the wine master repo? Is there something I should be doing? (I'm hoping to see it in 3.21).
On 21/11/18 6:30 am, Aric Stewart wrote:
As original author of the code I do believe it was to support native XInput.
If our builtin XInput is good enough then this change is just fine.
-aric
On 11/20/18 7:56 AM, Andrew Eikum wrote:
On Tue, Nov 20, 2018 at 12:53:21PM +1100, Brendan McGrath wrote:
Here's the commit from Proton that removed the masquerade. Native xinput wasn't something I had thought of. That could be why it's there.
Oh yeah, I remember that now. I wonder if the right answer isn't just to apply that same change to Wine.
Andrew
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput requires it. Our built-in xinput is good enough now, though, so let's keep the real VID/PID. This lets applications match setupapi devices with dinput devices, see:
"XInput and DirectInput" https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)
On Thu, Nov 22, 2018 at 05:59:39AM +1100, Brendan McGrath wrote:
Thanks for the confirmation Aric.
So what's the procedure for getting Andrew's commit in to the wine master repo? Is there something I should be doing? (I'm hoping to see it in 3.21).
I can send it on Monday when I'm back in the office, or you can send it any time. I don't care if you put my name in the From or just take ownership of it.
It might be nice to add the VID/PID registry overrides like you had planned, so users could maybe go back to using native xinput with the override. I don't know if there's any demand for that, though.
Andrew
On 21/11/18 6:30 am, Aric Stewart wrote:
As original author of the code I do believe it was to support native XInput.
If our builtin XInput is good enough then this change is just fine.
-aric
On 11/20/18 7:56 AM, Andrew Eikum wrote:
On Tue, Nov 20, 2018 at 12:53:21PM +1100, Brendan McGrath wrote:
Here's the commit from Proton that removed the masquerade. Native xinput wasn't something I had thought of. That could be why it's there.
Oh yeah, I remember that now. I wonder if the right answer isn't just to apply that same change to Wine.
Andrew
commit 4d49baf4566d8343055424467bad5e2958390103 Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Aug 3 12:36:21 2018 -0500
winebus: Don't override real VID/PID for controllers
It's unclear what this was useful for, possibly native xinput requires it. Our built-in xinput is good enough now, though, so let's keep the real VID/PID. This lets applications match setupapi devices with dinput devices, see:
"XInput and DirectInput" https://docs.microsoft.com/en-us/windows/desktop/xinput/xinput-and-directinp...
On 20/11/18 12:37 pm, Brendan McGrath wrote:
I'm not a fan of the registry hack either - it should be plug and play.
To match Windows functionality would be to remove the masquerade (as Proton has). That would fix my problem - but potentially create an issue for other games that are dependant on this masquerade (although I'm not familiar with the reasons behind its inclusion).
Perhaps a compromise is to keep this registry hack but have it default to use the real VID and PID. Then it matches Windows but there is still an option for those who need the masquerade (and they can choose the device to which they masquerade).
On 20/11/18 12:17 pm, Zebediah Figura wrote:
Be that as it may, I'm not sure that a registry hack is the approach we want to take. If the game doesn't work with controllers that don't report themselves as gamepads, but should, then we should fix it to work.
At the same time, as regards your original problem, we should look to rewrite the dinput joystick code on top of Wine's HID stack, so that it will report the same VID/PID as xinput does. I believe Aric is working on some patches to this effect ;-)