Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Impossible to distinguish dinput Bluetooth controllers with same PID/VID on Windows #13520

Open
nfp0 opened this issue Jan 21, 2022 · 20 comments

Comments

@nfp0
Copy link
Contributor

nfp0 commented Jan 21, 2022

Description

All (my) Bluetooth gamepads on Windows dinput report the name input_device = "Wireless Gamepad" when creating autoconfigs on Retroarch.
On udev on Linux, their correct name is detected, such as "MD/Gen Control Pad" and "SNES Controller" for the Nintendo Switch Online Mega Drive/Genesis and SNES controllers, respectively.
The problem is these controllers share the same VID and PID, so they conflict on dinput because they both report "Wireless Gamepad" there, so they can't be distinguished on the autoconfig files.

Is it possible for dinput to detect the device name the same way udev does?

These official replicas from the SNES and Mega Drive/Genesis controllers are bound to become popular for retro gaming as soon as stock arrives but will be incorrectly mapped by Retroarch's autoconfig system on Windows.

More discussion about this happened on this pull request:
libretro/retroarch-joypad-autoconfig#818

Expected behavior

Both controllers get auto-configured properly, distinguished by their device name, like on udev on Linux.

Actual behavior

The controllers currently can't be distinguished in dinput even though they have different Bluetooth names.

Version/Commit

  • RetroArch: 1.9.14

Environment information

  • OS: Windows 10
@golivax
Copy link

golivax commented Jun 4, 2023

Any hopes of getting this addressed? I have this exact same problem :-(

@nfp0
Copy link
Contributor Author

nfp0 commented Jun 4, 2023

It's not the perfect solution, but one workaround you can use is to let the controllers get the "wrong" config, as they currently do, and then do core or console specific overrides, then use each console with their natural controller.

@golivax
Copy link

golivax commented Jun 4, 2023

Thanks @nfp0! That's precisely the solution that I am currently using. I ended up (i) modifying the Snes autoconfig file to include bindings for the Screenshot, Home, and Mode buttons (present in the Genesis controller) and (ii) performed input mapping overrides in the Genesis GX core to make things work as desired with the Genesis controller. So it works, but it is not an optimal solution...

@nfp0
Copy link
Contributor Author

nfp0 commented Jun 5, 2023

I ended up (i) modifying the Snes autoconfig file to include bindings for the Screenshot, Home, and Mode buttons

Yeah, I did the same. I use ZR for Home.

It's a shame it doesn't work on Windows, because on Linux the controllers get correctly identified and mapped, which is what I've been using.

@geogolem
Copy link

geogolem commented Mar 7, 2024

Its so strange.. because Windows and the registry do report the names of the devices as
MD/Gen Control Pan
SNES Controller

but retroarch just detects the name as Wireless Gamepad

EDIT: and reading through here: libretro/retroarch-joypad-autoconfig#760 (comment)

it seems that this has already been discussed...

I ended up (i) modifying the Snes autoconfig file to include bindings for the Screenshot, Home, and Mode buttons

Yeah, I did the same. I use ZR for Home.

It's a shame it doesn't work on Windows, because on Linux the controllers get correctly identified and mapped, which is what I've been using.

The fact that this is possible on Linux means it must be possible somehow on Windows...

EDIT2: A little digging around and I found this discussion:
#8857

I found it interesting the discussion regarding the various names corresponding to devices etc. Just wanted to note that the "Friendly Name" is for example SNES Controller whilst the "Bus Reported Name" is Wireless Gamepad for these devices.

Specifically of interest is the comment here: #8857 (comment)

he specifically asks what would need to be done in retroarchs autoconfig to differentiate between these devices and also Bluetooth name which may also be relavent...

maybe it is related.. not sure.. just thought I would share since it might be useful.

@nfp0
Copy link
Contributor Author

nfp0 commented Mar 7, 2024

@geogolem Interesting find. I had created this issue because I never found those you linked back there.
It seems it's possible for RetroArch to query the "Friendly Name" on Windows and use that similarly to how we do on Linux with udev.
There doesn't seem to have been any work towards that though, but the possibility is there.

As for the autoconfig repository, it would work the same as it does with udev on Linux. First it tries to match the VID/PID, and if it can't find them, or if it ties with multiple matches, you can then match by the input_device value.
So I don't think any changes are needed other than adding that value to the affected controllers' autoconfig file.

@geogolem
Copy link

geogolem commented Mar 7, 2024

@geogolem Interesting find. I had created this issue because I never found those you linked back there. It seems it's possible for RetroArch to query the "Friendly Name" on Windows and use that similarly to how we do on Linux with udev. There doesn't seem to have been any work towards that though, but the possibility is there.

As for the autoconfig repository, it would work the same as it does with udev on Linux. First it tries to match the VID/PID, and if it can't find them, or if it ties with multiple matches, you can then match by the input_device value. So I don't think any changes are needed other than adding that value to the affected controllers' autoconfig file.

the friendly name is referenced in the dinput code:

g_pads[g_joypad_cnt].joy_friendly_name,

but only the name is referenced during the check:

autoconfig_handle->device_info.name))

maybe changing this to display_name will do the trick? but im not totally clear what is going on with input_autoconfigure_connect

   input_autoconfigure_connect(
         g_pads[g_joypad_cnt].joy_name,
         g_pads[g_joypad_cnt].joy_friendly_name,
         dinput_joypad.ident,
         g_joypad_cnt,
         g_pads[g_joypad_cnt].vid,
         g_pads[g_joypad_cnt].pid);
bool input_autoconfigure_connect(
      const char *name,
      const char *display_name,
      const char *driver,
      unsigned port,
      unsigned vid,
      unsigned pid);

bool input_autoconfigure_connect(

I do notice that later on autoconfig_handle->device_info.display_name is written with device_display_name from the autoconfig file... and then used to display the message..
but I'm guessing this issue isn't too difficult to solve if someone who knew the code well enough looked at it maybe.. Unfortunately it doesn't seem to be that high of a priority....

@hizzlekizzle
Copy link
Contributor

It's not that it's low-priority, it's just that people work on what they want to work on when they want to work on it (i.e., things that are bugging them personally right that minute), and nobody is an expert on every little thing in RetroArch (it's a huge, complex codebase), so if you've started digging into it, you're probably about as knowledgeable as anyone else on it. That is, anyone else who wanted to tackle this would have to go through the exact same research process you're going through, so if you care enough to deal with it, you're already the best person for the job :)

@nfp0
Copy link
Contributor Author

nfp0 commented Mar 7, 2024

@geogolem Yeah, looking superficially, this might not be too hard to implement at all.

I echo what @hizzlekizzle said and was actually going to suggest you to give it a try on your side. Do not be afraid to break stuff, and create a PR with your work even if it's incomplete. Sometimes that is enough to get the ball rolling and some more experienced dev to pay attention to it and provide the finishing touches.

@geogolem
Copy link

geogolem commented Mar 7, 2024

@geogolem Yeah, looking superficially, this might not be too hard to implement at all.

I echo what @hizzlekizzle said and was actually going to suggest you to give it a try on your side. Do not be afraid to break stuff, and create a PR with your work even if it's incomplete. Sometimes that is enough to get the ball rolling and some more experienced dev to pay attention to it and provide the finishing touches.

ive actually been investigating it for most of the day today.. lol. I got the dev environment setup, I can build.
Unfortunately both the name and friendly name are "Wireless Gamepad" so that doesn't help.. however, I am pretty sure the name we are looking for is "Bluetooth Friendly Name".. so I am looking into somehow mapping the dInput Device back to the bluetooth device to get this name to compare but I'm having some difficulty figuring out the bluetooth stuff.. but I am working on it..

I'm pretty sure if i could figure out the bluetooth stuff.. i could make some progress..

@nfp0
Copy link
Contributor Author

nfp0 commented Mar 7, 2024

Unfortunately both the name and friendly name are "Wireless Gamepad" so that doesn't help..

@geogolem
Oh I see, that was too good to be true 😆

What is this "Bluetooth Friendly Name" you talk about? Keep in mind I think RetroArch doesn't interact with the Bluetooth stack directly in any way. But correct me if I'm wrong.

@golivax
Copy link

golivax commented Mar 7, 2024 via email

@geogolem
Copy link

geogolem commented Mar 7, 2024

Unfortunately both the name and friendly name are "Wireless Gamepad" so that doesn't help..

@geogolem Oh I see, that was too good to be true 😆

What is this "Bluetooth Friendly Name" you talk about? Keep in mind I think RetroArch doesn't interact with the Bluetooth stack directly in any way. But correct me if I'm wrong.

that seems to be what im finding... at least on Windows anyway.... I don't know if Bluetooth Name and Bluetooth Friendly name are the same thing ... but given that retroarch doesn't interact with Bluetooth directly I'm having a hard time (and I also am just inexperienced/ dont really know what I am talking about"... one thing that is a available is a Product GUID ..

Basically this is the structure/data that is available:

typedef struct DIDEVICEINSTANCE {
    DWORD dwSize;
    GUID guidInstance;
    GUID guidProduct;
    DWORD dwDevType;
    TCHAR tszInstanceName[MAX_PATH];
    TCHAR tszProductName[MAX_PATH];
    GUID guidFFDriver;
    WORD wUsagePage;
    WORD wUsage;
} DIDEVICEINSTANCE, *LPDIDEVICEINSTANCE;

taken from: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ee416610(v=vs.85)

guidProduct
Unique identifier for the product. This identifier is established by the manufacturer of the device.

I'm just going to see if the guidProduct is the same for all SNES NSO controllers, and different from the MD 6 button NSO controller.. (I dont have the 3 button version to test)...
if that is the case, then adding some kind of check for the product GUID might solve the problem... I'll report back with what I find..

EDIT: --> well again both the MD 6 button and SNES controllers share the same product GUID..
The GUIDInstance of course will be unique to each device (but not class of device)... however, if someone knows how to basically query Windows for all the bluetooth devices.. then identify which bluetooth device corresponds to the instanceGUID they might be able to then get the bluetooth name or bluetooth friendly name which if we can somehow obtain would solve the problem...

@geogolem
Copy link

geogolem commented Mar 7, 2024

Just my 2 cents: One nice workaround I found last year was to simply download the latest SDL release from SDL's GitHub. Next, just replace SDL2.dll from Retroarch (which is super old) with the newly downloaded one. Then choose SDL as the controller driver inside RetroArch (instead of xinput of whatever you're using). Then everything just works - you only need to do the button mapping. As of today, SDL2 offers basically full compatibility with NSO controllers. It can distinguish between SNES and Genesis controllers, rumble works for N64, etc. All is good out of the box! Now, I'm not sure if the new DLL breaks anything else, but I haven't had any problems with it in the past 6 months or so.

I am going to give this a shot... I suppose you woudnt even need to map if there were SDL autoconfig files created for these controllers too, right?

@golivax
Copy link

golivax commented Mar 7, 2024 via email

@geogolem
Copy link

geogolem commented Mar 7, 2024

Cool! I'm almost sure I had to remap for N64, even though an auto config file existed. It's been a while...

So I got the most recent SDL2.dll and followed your instructions... It does indeed detect the difference between the SNES and 6buttonMD controller; however, I cannot get the extra 3 buttons (x, y, z) on the 6 button megadrive controller to work at all..

Another benefit is that the led lights on the controllers dont cycle anymore but instead settle on the light indicating the port the controller is mapped to.

Any suggestions for the 6 buttons MD controller?

-- one thing to note is that the controller is being detected as: Nintendo SEGA Genesis Controller

which may be the issue.. Maybe SDL is just viewing this as the regular NIntendo SEGA Genesis Controller and not the 6 button version...
in theory they still don't need to differentiate between the 2.. they jsut need to enable/map the other 3 buttons which wont be able to be used by the 3 button version...

@golivax
Copy link

golivax commented Mar 7, 2024 via email

@geogolem
Copy link

geogolem commented Mar 7, 2024

Oh, I only have the 3 button American version. So never got to try the 6 button one, sorry 😞

Thats OK -- at least it works for most games etc..
I opened an issue over at SDL for this here: libsdl-org/SDL#9223
and then I did some investigation and think I have a fix for it - but I need to figure out how to build SDL and test it out....

@nfp0
Copy link
Contributor Author

nfp0 commented Mar 8, 2024

It's great to know that the up to date SDL has full support for all the NSO controllers. Even rumble for the N64!
If it also supports reading the joystick calibrations from the NSO controllers, then that's perfect (the Linux driver does).

Any RetroArch dev knows if there's any particular reason why RetroArch uses such an outdated version? If nothing breaks, it would be great to get it up to date.

@golivax
Copy link

golivax commented Apr 28, 2024

@geogolem Recent release of SDL now supports NSO 6 Button Genesis/Mega Drive controller: https://github.com/libsdl-org/SDL/releases/tag/release-2.30.2 :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants