microsoft / DirectXTK

The DirectX Tool Kit (aka DirectXTK) is a collection of helper classes for writing DirectX 11.x code in C++
https://walbourn.github.io/directxtk/
MIT License
2.57k stars 510 forks source link

VID and PID #169

Closed ahmed-t-mpc closed 5 years ago

ahmed-t-mpc commented 5 years ago

Hi, could you please make the API expose the Vendor ID and Product ID controller information ?

walbourn commented 5 years ago

This information is not exposed by the XINPUT API, which is the design surface for GamePad. It's also not exposed by Windows.Gaming.Input.

What's your reason for wanting this information?

ahmed-t-mpc commented 5 years ago

Hi. We're exclusively developing for Windows 10 desktop (not uwp) and need this info to customize our controls mapping ui according to the physical controller plugged in. Isn't it possible to get it from Windows.Gaming.Input's RawGameController (https://docs.microsoft.com/en-us/uwp/api/windows.gaming.input.rawgamecontroller) ? I admit I don't really understand ABI::Windows::Gaming::Input nor what it really exposes from Windows.Gaming.Input...

ahmed-t-mpc commented 5 years ago

Do you think you can do something about this ?

walbourn commented 5 years ago

As I said, XINPUT doesn't provide VID/PID by design. It might be possible to cross-correlate it with DirectInput (as indicated in this article) but that wouldn't work for UWP. In WGI it does have a VID/PID value but I'm not sure how to correlate a gamepad with a raw game controller.

Again, I guess my main question is still : What do you want to do with this information? I.e. why do you need it for your scenario?

ahmed-t-mpc commented 5 years ago

Again, I guess my main question is still : What do you want to do with this information? I.e. why do you need it for your scenario?

My use is that I need a way to display to the user, on a specific screen, the names of their controller's buttons as they appear on the controller. Not A, B, X, Y, etc. all the time but, instead, the labels that are actually printed on the controller, be it a logitech gamepad, a flightstick or a steering wheel. They don't all have the same number of buttons nor the same button labels.

For that I need to differentiate between controllers according to their VID and PID, do I not ? And then, for each controller, I would fetch the right button labels inside my own maintained database of VID/PID. Of course, at the beginning, my DB will have entries for only a limited number of products. Does this make sense ?

walbourn commented 5 years ago

Generally speaking when using the XINPUT API, the only information you key off for layout hints would be the gamepadType value coming back from Capabilities (which in XINPUT is the XInputGetCapabilities return structure). You then use the 'most common layout' which for gamepads is the Xbox Common Controller gamepad--artwork can be found here. Kind of the point of XINPUT was to move away from the "every controller looks different" usage problem that plagued DirectInput.

If you need something more sophisticated, you probably should write your own input manager rather than make use of my abstraction.

walbourn commented 5 years ago

Note that it's technically possible with the Windows 10 (16299) or later version of Windows.Gaming.Input to get the VID/PID via RawGameController, but this information is not surfaced by any version of XINPUT.

To do this for WGI, you'd do basically the same pattern I do here but use FromGameController to get to a RawGameController and then call HardwareVendorId / HardwareProductId

ahmed-t-mpc commented 5 years ago

Note that it's technically possible with the Windows 10 (16299) or later version of Windows.Gaming.Input to get the VID/PID via RawGameController, but this information is not surfaced by any version of XINPUT.

To do this for WGI, you'd do basically the same pattern I do here but use FromGameController to get to a RawGameController and then call HardwareVendorId / HardwareProductId

Since we're exclusively developing for W10 desktop, that's exactly what we ended up doing, Chuck. Thanks.

walbourn commented 5 years ago

Implemented this in the master branch with this commit

DJm00n commented 2 years ago

Hi @walbourn! Maybe you can use hidden func XInputGetCapabilitiesEx from XInput 1.4 (comes with Windows 8 and up):

typedef struct _XINPUT_CAPABILITIES_EX
{
    XINPUT_CAPABILITIES Capabilities;
    WORD VendorId;
    WORD ProductId;
    WORD VersionNumber;
    WORD unk1;
    DWORD unk2;
} XINPUT_CAPABILITIES_EX, *PXINPUT_CAPABILITIES_EX;

// XInputGetCapabilitiesEx hidden function is available since Windows 8 version of XInput1_4.dll
DWORD XInputGetCapabilitiesEx(DWORD dwUserIndex, PXINPUT_CAPABILITIES_EX pCapabilitiesEx)
{
    DWORD(WINAPI* XInputGetCapabilitiesExFunc)(DWORD unk1, DWORD dwUserIndex, DWORD dwFlags, PXINPUT_CAPABILITIES_EX pCapabilities);
    XInputGetCapabilitiesExFunc = reinterpret_cast<decltype(XInputGetCapabilitiesExFunc)>(::GetProcAddress(::GetModuleHandleW(L"XInput1_4.dll"), (LPCSTR)108));

    if (!XInputGetCapabilitiesExFunc)
        return ERROR_INVALID_FUNCTION;

    return XInputGetCapabilitiesExFunc(1, dwUserIndex, 0, pCapabilitiesEx);
}

....
XINPUT_CAPABILITIES_EX caps {0};

XInputGetCapabilitiesEx(m_UserIndex, &caps);

// Fixup for Wireless Xbox 360 Controller
if (caps.ProductId == 0 && caps.Capabilities.Flags & /*XINPUT_CAPS_WIRELESS*/0x0002)
{
    caps.VendorId = 0x045E;
    caps.ProductId = 0x02A1;
}

m_VendorId = caps.VendorId;
m_ProductId = caps.ProductId;

// Known controller VID/PID list: https://github.com/libsdl-org/SDL/blob/main/src/joystick/controller_type.h

https://gist.github.com/DJm00n/0f0563702f6cf01e8812ebc760a78cf1#file-xinputgetcapabilitiesex-cpp

What do you think?

walbourn commented 2 years ago

Using an undocumented private API is always tricky long-term because of potential appcompat issues. I'll think about it some more before I commit either way.

Also note that there are a number of legacy Xbox 360 Wireless VID/PID values, although that's probably "good enough" for many scenarios. It also won't detect the difference between Xbox 360 Wireless and Xbox One Wireless.

Note that GameInput on PC will solve this problem officially as it includes VID/PID information.

DJm00n commented 2 years ago

GameInput on PC

unfortunately seems we can't use it just yet. @walbourn do you know when it will be available for PC use?

NOTE: PC support (including earlier versions of Windows) will be available in an upcoming Windows SDK.

https://docs.microsoft.com/en-us/gaming/gdk/_content/gc/input/overviews/input-overview

walbourn commented 1 year ago

Follow-up: GameInput supports PC in Game Development Kit June 2022 or later.