Mac and Linux SDL2 binary snapshots
Edward Rudd
2021-06-15 dec7875a6e23212021e4d9080330a42832dfe02a
source/src/joystick/windows/SDL_dinputjoystick.c
@@ -26,6 +26,7 @@
#include "SDL_windowsjoystick_c.h"
#include "SDL_dinputjoystick_c.h"
#include "SDL_rawinputjoystick_c.h"
#include "SDL_xinputjoystick_c.h"
#include "../hidapi/SDL_hidapijoystick_c.h"
@@ -228,10 +229,6 @@
static int
SetDIerror(const char *function, HRESULT code)
{
    /*
    return SDL_SetError("%s() [%s]: %s", function,
    DXGetErrorString9A(code), DXGetErrorDescription9A(code));
    */
    return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code);
}
@@ -244,7 +241,7 @@
static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } };
static SDL_bool
WIN_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
WIN_IsXInputDevice(const WCHAR *name, const GUID* pGuidProductFromDirectInput)
{
    IWbemLocator*           pIWbemLocator = NULL;
    IEnumWbemClassObject*   pEnumDevices = NULL;
@@ -258,6 +255,17 @@
    UINT                    iDevice = 0;
    VARIANT                 var;
    HRESULT                 hr;
    if (!SDL_XINPUT_Enabled()) {
        return SDL_FALSE;
    }
    if (SDL_wcsstr(name, L" XINPUT ") != NULL) {
        /* This is a duplicate interface for a controller that will show up with XInput,
           e.g. Xbox One Elite Series 2 in Bluetooth mode.
         */
        return SDL_TRUE;
    }
    SDL_zeroa(pDevices);
@@ -363,12 +371,19 @@
#endif /* 0 */
static SDL_bool
SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
SDL_IsXInputDevice(const WCHAR *name, const GUID* pGuidProductFromDirectInput)
{
    UINT i;
    if (!SDL_XINPUT_Enabled()) {
        return SDL_FALSE;
    }
    if (SDL_wcsstr(name, L" XINPUT ") != NULL) {
        /* This is a duplicate interface for a controller that will show up with XInput,
           e.g. Xbox One Elite Series 2 in Bluetooth mode.
         */
        return SDL_TRUE;
    }
    if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) {
@@ -404,7 +419,7 @@
    for (i = 0; i < SDL_RawDevListCount; i++) {
        RID_DEVICE_INFO rdi;
        char devName[128];
        char devName[MAX_PATH];
        UINT rdiSize = sizeof(rdi);
        UINT nameSize = SDL_arraysize(devName);
@@ -490,7 +505,7 @@
    coinitialized = SDL_TRUE;
    result = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
        &IID_IDirectInput8, (LPVOID)&dinput);
        &IID_IDirectInput8, (LPVOID *)&dinput);
    if (FAILED(result)) {
        return SetDIerror("CoCreateInstance", result);
@@ -499,11 +514,15 @@
    /* Because we used CoCreateInstance, we need to Initialize it, first. */
    instance = GetModuleHandle(NULL);
    if (instance == NULL) {
        IDirectInput8_Release(dinput);
        dinput = NULL;
        return SDL_SetError("GetModuleHandle() failed with error code %lu.", GetLastError());
    }
    result = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
    if (FAILED(result)) {
        IDirectInput8_Release(dinput);
        dinput = NULL;
        return SetDIerror("IDirectInput::Initialize", result);
    }
    return 0;
@@ -521,7 +540,7 @@
    Uint16 product = 0;
    Uint16 version = 0;
    WCHAR hidPath[MAX_PATH];
    const char *name;
    char *name;
    if (devtype == DI8DEVTYPE_SUPPLEMENTAL) {
        /* Add any supplemental devices that should be ignored here */
@@ -539,7 +558,7 @@
        }
    }
    if (SDL_IsXInputDevice(&pdidInstance->guidProduct)) {
    if (SDL_IsXInputDevice(pdidInstance->tszProductName, &pdidInstance->guidProduct)) {
        return DIENUM_CONTINUE;  /* ignore XInput devices here, keep going. */
    }
@@ -586,8 +605,8 @@
                pPrevJoystick->pNext = pNewJoystick->pNext;
            }
            // Update with new guid/etc, if it has changed
            pNewJoystick->dxdevice = *pdidInstance;
            /* Update with new guid/etc, if it has changed */
            SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
            pNewJoystick->pNext = SYS_Joystick;
            SYS_Joystick = pNewJoystick;
@@ -609,12 +628,22 @@
    SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE));
    SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data));
    guid16 = (Uint16 *)pNewJoystick->guid.data;
    if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
        vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
        product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
        version = 0;
    }
    name = WIN_StringToUTF8(pdidInstance->tszProductName);
    pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name);
    SDL_free(name);
    if (!pNewJoystick->joystickname) {
        SDL_free(pNewJoystick);
        return DIENUM_CONTINUE; /* better luck next time? */
    }
    guid16 = (Uint16 *)pNewJoystick->guid.data;
    if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
        *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB);
        *guid16++ = 0;
        *guid16++ = SDL_SwapLE16(vendor);
@@ -629,26 +658,6 @@
        SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4);
    }
    name = SDL_GetCustomJoystickName(vendor, product);
    if (name) {
        pNewJoystick->joystickname = SDL_strdup(name);
    } else {
        pNewJoystick->joystickname = WIN_StringToUTF8(pdidInstance->tszProductName);
    }
    if (!pNewJoystick->joystickname) {
        SDL_free(pNewJoystick);
        return DIENUM_CONTINUE; /* better luck next time? */
    }
    if (SDL_strstr(pNewJoystick->joystickname, " XINPUT ") != NULL) {
        /* This is a duplicate interface for a controller that will show up with XInput,
           e.g. Xbox One Elite Series 2 in Bluetooth mode.
         */
        SDL_free(pNewJoystick->joystickname);
        SDL_free(pNewJoystick);
        return DIENUM_CONTINUE;
    }
    if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) {
        SDL_free(pNewJoystick->joystickname);
        SDL_free(pNewJoystick);
@@ -659,6 +668,14 @@
    if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
        /* The HIDAPI driver is taking care of this device */
        SDL_free(pNewJoystick->joystickname);
        SDL_free(pNewJoystick);
        return DIENUM_CONTINUE;
    }
#endif
#ifdef SDL_JOYSTICK_RAWINPUT
    if (RAWINPUT_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) {
        /* The RAWINPUT driver is taking care of this device */
        SDL_free(pNewJoystick);
        return DIENUM_CONTINUE;
    }
@@ -679,6 +696,51 @@
        SDL_RawDevList = NULL;
    }
    SDL_RawDevListCount = 0;
}
typedef struct
{
    Uint16 vendor;
    Uint16 product;
    Uint16 version;
    SDL_bool present;
} EnumJoystickPresentData;
static BOOL CALLBACK
EnumJoystickPresentCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
{
    EnumJoystickPresentData *data = (EnumJoystickPresentData *)pContext;
    Uint16 vendor = 0;
    Uint16 product = 0;
    Uint16 version = 0;
    if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) {
        vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1);
        product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1);
        if (data->vendor == vendor && data->product == product && data->version == version) {
            data->present = SDL_TRUE;
            return DIENUM_STOP;
        }
    }
    return DIENUM_CONTINUE;
}
SDL_bool
SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
{
    EnumJoystickPresentData data;
    if (dinput == NULL) {
        return SDL_FALSE;
    }
    data.vendor = vendor;
    data.product = product;
    data.version = version;
    data.present = SDL_FALSE;
    IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY);
    return data.present;
}
static BOOL CALLBACK
@@ -1244,6 +1306,12 @@
{
}
SDL_bool
SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version)
{
    return SDL_FALSE;
}
int
SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
{