Skip to content

Commit

Permalink
HACK: win32u: Report underlying VID/PID in Steam Input hooks emulation.
Browse files Browse the repository at this point in the history
CW-Bug-Id: #23185
  • Loading branch information
rbernon committed Jan 11, 2024
1 parent 2e778c6 commit f9a2920
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions dlls/win32u/rawinput.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,30 @@ UINT WINAPI NtUserGetRawInputDeviceList( RAWINPUTDEVICELIST *device_list, UINT *
return count;
}

static BOOL steam_input_get_vid_pid( UINT slot, UINT16 *vid, UINT16 *pid )
{
const char *info = getenv( "SteamVirtualGamepadInfo" );
char buffer[256];
UINT current;
FILE *file;

TRACE( "reading SteamVirtualGamepadInfo %s\n", debugstr_a(info) );

if (!info || !(file = fopen( info, "r" ))) return FALSE;
while (fscanf( file, "%255[^\n]\n", buffer ) == 1)
{
if (sscanf( buffer, "[slot %d]", &current )) continue;
if (current < slot) continue;
if (current > slot) break;
if (sscanf( buffer, "VID=0x%hx", vid )) continue;
if (sscanf( buffer, "PID=0x%hx", pid )) continue;
}

fclose( file );

return TRUE;
}

/**********************************************************************
* NtUserGetRawInputDeviceInfo (win32u.@)
*/
Expand Down Expand Up @@ -590,9 +614,11 @@ UINT WINAPI NtUserGetRawInputDeviceInfo( HANDLE handle, UINT command, void *data
buffer[size] = 0;
if (sscanf( buffer, "%02u", &slot ) != 1) slot = 0;

/* FIXME: Return the actual underlying device VID / PID somehow */
vid = 0x045e;
pid = 0x028e;
if (!steam_input_get_vid_pid( slot, &vid, &pid ))

This comment has been minimized.

Copy link
@slouken

slouken Jan 11, 2024

The VID/PID will change here at runtime if the user switches controller slots in the Steam UI. Is that okay at this level?

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

From Proton perspective the pipe path we return here has no real existence and we patch it back in 43ccabd to open the actual Steam Virtual Controller HID device instead if it is accessed.

Then, this also means that we might return different paths here for the same device if the file has been modified since the last call. This might be an issue if the client expects hotplug messages between changes? Does SDL expect them on the Windows side to refresh its slot numbers and info?

Regarding hotplugging, we still rely and follow the SDL Linux backend for that, and it's not 100% clear to me how switching slots is translated there. For instance, how does swapping two controllers looks like on the Linux SDL client level?

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

I understand that with SDL 2.30 we will actually need to call SDL_GameControllerGetSteamHandle because all the joystick info that we will get is from the underlying controller, and we won't see 28de:11ff devices anymore, right?

This comment has been minimized.

Copy link
@slouken

slouken Jan 11, 2024

No, nothing has changed on the Linux side, you'll still see 28de:11ff devices, and a controller slot swap is still transparent the Linux applications. The only thing that changes is the contents of the SteamVirtualGamepadInfo file. SDL has code to watch for changes to that file and generates the appropriate events for the application.

For Win32 applications, you want to make sure the slot is getting passed through all the ways SDL expects it, so it can look up the appropriate information in SteamVirtualGamepadInfo, but otherwise I don't think anything else has to change.

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

But for instance with a Sony controller, I understand that after libsdl-org/SDL@7bb0e83#diff-bce2446f1952efee9da1abe943d6cc1636bd219deabf59164f8c9ee3e5b700e2L2995 the VID returned by SDL_JoystickGetVendor will be 0x054c and not 0x28de anymore?

This comment has been minimized.

Copy link
@slouken

slouken Jan 11, 2024

That's correct. If you want to disable SDL's interpretation of that data, you can call:
SDL_SetHint("SteamVirtualGamepadInfo", "");

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

Alright, thanks!

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

Although, one potential issue with this is that it might break old Proton versions that expect the Steam Virtual controller VID/PID to identify them.

This comment has been minimized.

Copy link
@slouken

slouken Jan 11, 2024

What's the impact of that?

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 11, 2024

Author Collaborator

It would stop exposing the Steam controllers as XBox controllers and instead expose them with the underlying VID/PID. Which would probably break things with Sony controllers for which games often have specific code to handle them through their proprietary HID protocol, but also perhaps unknown other consequences with other models.

This comment has been minimized.

Copy link
@rbernon

rbernon Jan 12, 2024

Author Collaborator

That's correct. If you want to disable SDL's interpretation of that data, you can call: SDL_SetHint("SteamVirtualGamepadInfo", "");

Not an issue but just a note that we'll anyway have to do that on the Linux backend side because otherwise we can't find out the slot number the controller is bound to anymore as the returned name will otherwise be from read from the file.

This comment has been minimized.

Copy link
@slouken

slouken Jan 12, 2024

Okay, the current public client sets that environment variable for all game launches, but I'll change that to "SteamVirtualGamepadInfo_Proton" when launching games under Proton.

{
vid = 0x045e;
pid = 0x028e;
}

size = snprintf( buffer, ARRAY_SIZE(buffer), "\\\\.\\pipe\\HID#VID_045E&PID_028E&IG_00#%04X&%04X", vid, pid );
if ((tmpW = wcschr( device->path + 29, '&' )))
Expand Down

0 comments on commit f9a2920

Please sign in to comment.