src/joystick/windows/SDL_xinputjoystick.c
author Ryan C. Gordon
Tue, 24 Jan 2017 16:18:25 -0500
changeset 10850 c9dc0068b0e7
parent 10737 3406a0f8b041
child 10872 414ace708a6a
permissions -rw-r--r--
configure: report libsamplerate support status.
slouken@8972
     1
/*
slouken@8972
     2
  Simple DirectMedia Layer
slouken@10737
     3
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@8972
     4
slouken@8972
     5
  This software is provided 'as-is', without any express or implied
slouken@8972
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8972
     7
  arising from the use of this software.
slouken@8972
     8
slouken@8972
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8972
    10
  including commercial applications, and to alter it and redistribute it
slouken@8972
    11
  freely, subject to the following restrictions:
slouken@8972
    12
slouken@8972
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8972
    14
     claim that you wrote the original software. If you use this software
slouken@8972
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8972
    16
     appreciated but is not required.
slouken@8972
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8972
    18
     misrepresented as being the original software.
slouken@8972
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8972
    20
*/
slouken@8972
    21
#include "../../SDL_internal.h"
slouken@8972
    22
icculus@9659
    23
#include "../SDL_sysjoystick.h"
icculus@9659
    24
icculus@9658
    25
#if SDL_JOYSTICK_XINPUT
icculus@9658
    26
slouken@8972
    27
#include "SDL_assert.h"
slouken@8972
    28
#include "SDL_hints.h"
slouken@8972
    29
#include "SDL_windowsjoystick_c.h"
slouken@8972
    30
#include "SDL_xinputjoystick_c.h"
slouken@8972
    31
slouken@8972
    32
/*
slouken@8972
    33
 * Internal stuff.
slouken@8972
    34
 */
slouken@8972
    35
static SDL_bool s_bXInputEnabled = SDL_TRUE;
slouken@8972
    36
slouken@8972
    37
slouken@8972
    38
static SDL_bool
slouken@8972
    39
SDL_XInputUseOldJoystickMapping()
slouken@8972
    40
{
dludwig@10697
    41
#ifdef __WINRT__
dludwig@10697
    42
    /* TODO: remove this __WINRT__ block, but only after integrating with UWP/WinRT's HID API */
dludwig@10697
    43
    return SDL_TRUE;
dludwig@10697
    44
#else
slouken@8972
    45
    static int s_XInputUseOldJoystickMapping = -1;
slouken@8972
    46
    if (s_XInputUseOldJoystickMapping < 0) {
slouken@10499
    47
        s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE);
slouken@8972
    48
    }
slouken@8972
    49
    return (s_XInputUseOldJoystickMapping > 0);
dludwig@10697
    50
#endif
slouken@8972
    51
}
slouken@8972
    52
slouken@8972
    53
SDL_bool SDL_XINPUT_Enabled(void)
slouken@8972
    54
{
slouken@8972
    55
    return s_bXInputEnabled;
slouken@8972
    56
}
slouken@8972
    57
slouken@8972
    58
int
slouken@8972
    59
SDL_XINPUT_JoystickInit(void)
slouken@8972
    60
{
slouken@10499
    61
    s_bXInputEnabled = SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE);
slouken@8972
    62
slouken@8972
    63
    if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
slouken@8972
    64
        s_bXInputEnabled = SDL_FALSE;  /* oh well. */
slouken@8972
    65
    }
slouken@8972
    66
    return 0;
slouken@8972
    67
}
slouken@8972
    68
slouken@8972
    69
static char *
slouken@8972
    70
GetXInputName(const Uint8 userid, BYTE SubType)
slouken@8972
    71
{
slouken@8972
    72
    char name[32];
slouken@8972
    73
slouken@8972
    74
    if (SDL_XInputUseOldJoystickMapping()) {
slouken@8972
    75
        SDL_snprintf(name, sizeof(name), "X360 Controller #%u", 1 + userid);
slouken@8972
    76
    } else {
slouken@8972
    77
        switch (SubType) {
slouken@8972
    78
        case XINPUT_DEVSUBTYPE_GAMEPAD:
slouken@8972
    79
            SDL_snprintf(name, sizeof(name), "XInput Controller #%u", 1 + userid);
slouken@8972
    80
            break;
slouken@8972
    81
        case XINPUT_DEVSUBTYPE_WHEEL:
slouken@8972
    82
            SDL_snprintf(name, sizeof(name), "XInput Wheel #%u", 1 + userid);
slouken@8972
    83
            break;
slouken@8972
    84
        case XINPUT_DEVSUBTYPE_ARCADE_STICK:
slouken@8972
    85
            SDL_snprintf(name, sizeof(name), "XInput ArcadeStick #%u", 1 + userid);
slouken@8972
    86
            break;
slouken@8972
    87
        case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
slouken@8972
    88
            SDL_snprintf(name, sizeof(name), "XInput FlightStick #%u", 1 + userid);
slouken@8972
    89
            break;
slouken@8972
    90
        case XINPUT_DEVSUBTYPE_DANCE_PAD:
slouken@8972
    91
            SDL_snprintf(name, sizeof(name), "XInput DancePad #%u", 1 + userid);
slouken@8972
    92
            break;
slouken@8972
    93
        case XINPUT_DEVSUBTYPE_GUITAR:
slouken@8972
    94
        case XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE:
slouken@8972
    95
        case XINPUT_DEVSUBTYPE_GUITAR_BASS:
slouken@8972
    96
            SDL_snprintf(name, sizeof(name), "XInput Guitar #%u", 1 + userid);
slouken@8972
    97
            break;
slouken@8972
    98
        case XINPUT_DEVSUBTYPE_DRUM_KIT:
slouken@8972
    99
            SDL_snprintf(name, sizeof(name), "XInput DrumKit #%u", 1 + userid);
slouken@8972
   100
            break;
slouken@8972
   101
        case XINPUT_DEVSUBTYPE_ARCADE_PAD:
slouken@8972
   102
            SDL_snprintf(name, sizeof(name), "XInput ArcadePad #%u", 1 + userid);
slouken@8972
   103
            break;
slouken@8972
   104
        default:
slouken@8972
   105
            SDL_snprintf(name, sizeof(name), "XInput Device #%u", 1 + userid);
slouken@8972
   106
            break;
slouken@8972
   107
        }
slouken@8972
   108
    }
slouken@8972
   109
    return SDL_strdup(name);
slouken@8972
   110
}
slouken@8972
   111
slouken@10648
   112
/* We can't really tell what device is being used for XInput, but we can guess
slouken@10648
   113
   and we'll be correct for the case where only one device is connected.
slouken@10648
   114
 */
slouken@8972
   115
static void
slouken@10648
   116
GuessXInputDevice(UINT device_index, Uint16 *pVID, Uint16 *pPID, Uint16 *pVersion)
slouken@10648
   117
{
dludwig@10697
   118
#ifndef __WINRT__   /* TODO: remove this ifndef __WINRT__ block, but only after integrating with UWP/WinRT's HID API */
dludwig@10697
   119
slouken@10648
   120
    PRAWINPUTDEVICELIST devices = NULL;
slouken@10648
   121
    UINT i, found_count = 0, device_count = 0;
slouken@10648
   122
slouken@10648
   123
    if ((GetRawInputDeviceList(NULL, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) || (!device_count)) {
slouken@10648
   124
        return;  /* oh well. */
slouken@10648
   125
    }
slouken@10648
   126
slouken@10648
   127
    devices = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * device_count);
slouken@10648
   128
    if (devices == NULL) {
slouken@10648
   129
        return;
slouken@10648
   130
    }
slouken@10648
   131
slouken@10648
   132
    if (GetRawInputDeviceList(devices, &device_count, sizeof(RAWINPUTDEVICELIST)) == -1) {
slouken@10648
   133
        SDL_free(devices);
slouken@10648
   134
        return;  /* oh well. */
slouken@10648
   135
    }
slouken@10648
   136
slouken@10648
   137
    for (i = 0; i < device_count; i++) {
slouken@10648
   138
        RID_DEVICE_INFO rdi;
slouken@10648
   139
        char devName[128];
slouken@10648
   140
        UINT rdiSize = sizeof(rdi);
slouken@10648
   141
        UINT nameSize = SDL_arraysize(devName);
slouken@10648
   142
slouken@10648
   143
        rdi.cbSize = sizeof(rdi);
slouken@10648
   144
        if ((devices[i].dwType == RIM_TYPEHID) &&
slouken@10648
   145
            (GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) &&
slouken@10648
   146
            (GetRawInputDeviceInfoA(devices[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) &&
slouken@10648
   147
            (SDL_strstr(devName, "IG_") != NULL)) {
slouken@10648
   148
            *pVID = (Uint16)rdi.hid.dwVendorId;
slouken@10648
   149
            *pPID = (Uint16)rdi.hid.dwProductId;
slouken@10648
   150
            *pVersion = (Uint16)rdi.hid.dwVersionNumber;
slouken@10648
   151
slouken@10648
   152
            if (found_count++ == device_index) {
slouken@10648
   153
                /* We don't really know the order of the devices relative to XInput,
slouken@10648
   154
                   but we'll guess that this is the correct one
slouken@10648
   155
                 */
slouken@10648
   156
                break;
slouken@10648
   157
            }
slouken@10648
   158
        }
slouken@10648
   159
    }
slouken@10648
   160
    SDL_free(devices);
dludwig@10697
   161
#endif  /* ifndef __WINRT__ */
slouken@10648
   162
}
slouken@10648
   163
slouken@10648
   164
static void
slouken@10648
   165
AddXInputDevice(Uint8 userid, BYTE SubType, JoyStick_DeviceData **pContext)
slouken@8972
   166
{
slouken@8972
   167
    JoyStick_DeviceData *pPrevJoystick = NULL;
slouken@8972
   168
    JoyStick_DeviceData *pNewJoystick = *pContext;
slouken@8972
   169
slouken@8972
   170
    if (SDL_XInputUseOldJoystickMapping() && SubType != XINPUT_DEVSUBTYPE_GAMEPAD)
slouken@8972
   171
        return;
slouken@8972
   172
slouken@8972
   173
    if (SubType == XINPUT_DEVSUBTYPE_UNKNOWN)
slouken@8972
   174
        return;
slouken@8972
   175
slouken@8972
   176
    while (pNewJoystick) {
slouken@8972
   177
        if (pNewJoystick->bXInputDevice && (pNewJoystick->XInputUserId == userid) && (pNewJoystick->SubType == SubType)) {
slouken@8972
   178
            /* if we are replacing the front of the list then update it */
slouken@8972
   179
            if (pNewJoystick == *pContext) {
slouken@8972
   180
                *pContext = pNewJoystick->pNext;
slouken@8972
   181
            } else if (pPrevJoystick) {
slouken@8972
   182
                pPrevJoystick->pNext = pNewJoystick->pNext;
slouken@8972
   183
            }
slouken@8972
   184
slouken@8972
   185
            pNewJoystick->pNext = SYS_Joystick;
slouken@8972
   186
            SYS_Joystick = pNewJoystick;
slouken@8972
   187
            return;   /* already in the list. */
slouken@8972
   188
        }
slouken@8972
   189
slouken@8972
   190
        pPrevJoystick = pNewJoystick;
slouken@8972
   191
        pNewJoystick = pNewJoystick->pNext;
slouken@8972
   192
    }
slouken@8972
   193
slouken@8972
   194
    pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData));
slouken@8972
   195
    if (!pNewJoystick) {
slouken@8972
   196
        return; /* better luck next time? */
slouken@8972
   197
    }
slouken@8972
   198
    SDL_zerop(pNewJoystick);
slouken@8972
   199
slouken@8972
   200
    pNewJoystick->joystickname = GetXInputName(userid, SubType);
slouken@8972
   201
    if (!pNewJoystick->joystickname) {
slouken@8972
   202
        SDL_free(pNewJoystick);
slouken@8972
   203
        return; /* better luck next time? */
slouken@8972
   204
    }
slouken@8972
   205
slouken@8972
   206
    pNewJoystick->bXInputDevice = SDL_TRUE;
slouken@8972
   207
    if (SDL_XInputUseOldJoystickMapping()) {
slouken@8972
   208
        SDL_zero(pNewJoystick->guid);
slouken@8972
   209
    } else {
slouken@10648
   210
        const Uint16 BUS_USB = 0x03;
slouken@10648
   211
        Uint16 vendor = 0;
slouken@10648
   212
        Uint16 product = 0;
slouken@10648
   213
        Uint16 version = 0;
slouken@10648
   214
        Uint16 *guid16 = (Uint16 *)pNewJoystick->guid.data;
slouken@10648
   215
slouken@10648
   216
        GuessXInputDevice(userid, &vendor, &product, &version);
slouken@10648
   217
slouken@10648
   218
        *guid16++ = SDL_SwapLE16(BUS_USB);
slouken@10648
   219
        *guid16++ = 0;
slouken@10648
   220
        *guid16++ = SDL_SwapLE16(vendor);
slouken@10648
   221
        *guid16++ = 0;
slouken@10648
   222
        *guid16++ = SDL_SwapLE16(product);
slouken@10648
   223
        *guid16++ = 0;
slouken@10648
   224
        *guid16++ = SDL_SwapLE16(version);
slouken@10648
   225
        *guid16++ = 0;
slouken@10648
   226
slouken@10648
   227
        /* Note that this is an XInput device and what subtype it is */
slouken@10648
   228
        pNewJoystick->guid.data[14] = 'x';
slouken@10648
   229
        pNewJoystick->guid.data[15] = SubType;
slouken@8972
   230
    }
slouken@8972
   231
    pNewJoystick->SubType = SubType;
slouken@8972
   232
    pNewJoystick->XInputUserId = userid;
slouken@8972
   233
    SDL_SYS_AddJoystickDevice(pNewJoystick);
slouken@8972
   234
}
slouken@8972
   235
slouken@8972
   236
void
slouken@8972
   237
SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
slouken@8972
   238
{
slouken@8972
   239
    int iuserid;
slouken@8972
   240
slouken@8972
   241
    if (!s_bXInputEnabled) {
slouken@8972
   242
        return;
slouken@8972
   243
    }
slouken@8972
   244
slouken@8972
   245
    /* iterate in reverse, so these are in the final list in ascending numeric order. */
slouken@8972
   246
    for (iuserid = XUSER_MAX_COUNT - 1; iuserid >= 0; iuserid--) {
slouken@8972
   247
        const Uint8 userid = (Uint8)iuserid;
slouken@8972
   248
        XINPUT_CAPABILITIES capabilities;
slouken@8972
   249
        if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) {
slouken@8972
   250
            AddXInputDevice(userid, capabilities.SubType, pContext);
slouken@8972
   251
        }
slouken@8972
   252
    }
slouken@8972
   253
}
slouken@8972
   254
slouken@8972
   255
int
slouken@8972
   256
SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
slouken@8972
   257
{
slouken@8972
   258
    const Uint8 userId = joystickdevice->XInputUserId;
slouken@8972
   259
    XINPUT_CAPABILITIES capabilities;
slouken@8972
   260
    XINPUT_VIBRATION state;
slouken@8972
   261
slouken@8972
   262
    SDL_assert(s_bXInputEnabled);
slouken@8972
   263
    SDL_assert(XINPUTGETCAPABILITIES);
slouken@8972
   264
    SDL_assert(XINPUTSETSTATE);
slouken@8972
   265
    SDL_assert(userId < XUSER_MAX_COUNT);
slouken@8972
   266
slouken@8972
   267
    joystick->hwdata->bXInputDevice = SDL_TRUE;
slouken@8972
   268
slouken@8972
   269
    if (XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities) != ERROR_SUCCESS) {
slouken@8972
   270
        SDL_free(joystick->hwdata);
slouken@8972
   271
        joystick->hwdata = NULL;
slouken@8972
   272
        return SDL_SetError("Failed to obtain XInput device capabilities. Device disconnected?");
slouken@8972
   273
    }
slouken@8972
   274
    SDL_zero(state);
slouken@8972
   275
    joystick->hwdata->bXInputHaptic = (XINPUTSETSTATE(userId, &state) == ERROR_SUCCESS);
slouken@8972
   276
    joystick->hwdata->userid = userId;
slouken@8972
   277
slouken@8972
   278
    /* The XInput API has a hard coded button/axis mapping, so we just match it */
slouken@8972
   279
    if (SDL_XInputUseOldJoystickMapping()) {
slouken@8972
   280
        joystick->naxes = 6;
slouken@8972
   281
        joystick->nbuttons = 15;
slouken@8972
   282
    } else {
slouken@8972
   283
        joystick->naxes = 6;
slouken@8972
   284
        joystick->nbuttons = 11;
slouken@8972
   285
        joystick->nhats = 1;
slouken@8972
   286
    }
slouken@8972
   287
    return 0;
slouken@8972
   288
}
slouken@8972
   289
slouken@9884
   290
static void 
dludwig@9918
   291
UpdateXInputJoystickBatteryInformation(SDL_Joystick * joystick, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
slouken@9884
   292
{
slouken@9884
   293
    if ( pBatteryInformation->BatteryType != BATTERY_TYPE_UNKNOWN )
slouken@9884
   294
    {
slouken@9884
   295
        SDL_JoystickPowerLevel ePowerLevel = SDL_JOYSTICK_POWER_UNKNOWN;
slouken@9884
   296
        if (pBatteryInformation->BatteryType == BATTERY_TYPE_WIRED) {
slouken@9884
   297
            ePowerLevel = SDL_JOYSTICK_POWER_WIRED;
slouken@9884
   298
        } else {
slouken@9884
   299
            switch ( pBatteryInformation->BatteryLevel )
slouken@9884
   300
            {
slouken@9884
   301
            case BATTERY_LEVEL_EMPTY:
slouken@9884
   302
                ePowerLevel = SDL_JOYSTICK_POWER_EMPTY;
slouken@9884
   303
                break;
slouken@9884
   304
            case BATTERY_LEVEL_LOW:
slouken@9884
   305
                ePowerLevel = SDL_JOYSTICK_POWER_LOW;
slouken@9884
   306
                break;
slouken@9884
   307
            case BATTERY_LEVEL_MEDIUM:
slouken@9884
   308
                ePowerLevel = SDL_JOYSTICK_POWER_MEDIUM;
slouken@9884
   309
                break;
slouken@9884
   310
            default:
slouken@9884
   311
            case BATTERY_LEVEL_FULL:
slouken@9884
   312
                ePowerLevel = SDL_JOYSTICK_POWER_FULL;
slouken@9884
   313
                break;
slouken@9884
   314
            }
slouken@9884
   315
        }
slouken@9884
   316
slouken@9884
   317
        SDL_PrivateJoystickBatteryLevel( joystick, ePowerLevel );
slouken@9884
   318
    }
slouken@9884
   319
}
slouken@9884
   320
slouken@8972
   321
static void
dludwig@9918
   322
UpdateXInputJoystickState_OLD(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
slouken@8972
   323
{
slouken@8972
   324
    static WORD s_XInputButtons[] = {
slouken@8972
   325
        XINPUT_GAMEPAD_DPAD_UP, XINPUT_GAMEPAD_DPAD_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, XINPUT_GAMEPAD_DPAD_RIGHT,
slouken@8972
   326
        XINPUT_GAMEPAD_START, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
slouken@8972
   327
        XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER,
slouken@8972
   328
        XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
slouken@8972
   329
        XINPUT_GAMEPAD_GUIDE
slouken@8972
   330
    };
slouken@8972
   331
    WORD wButtons = pXInputState->Gamepad.wButtons;
slouken@8972
   332
    Uint8 button;
slouken@8972
   333
slouken@8972
   334
    SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
slouken@8972
   335
    SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
slouken@8972
   336
    SDL_PrivateJoystickAxis(joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX);
slouken@8972
   337
    SDL_PrivateJoystickAxis(joystick, 3, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
slouken@8972
   338
    SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
slouken@8972
   339
    SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
slouken@8972
   340
slouken@8972
   341
    for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
slouken@8972
   342
        SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
slouken@8972
   343
    }
slouken@9884
   344
slouken@9884
   345
    UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
slouken@8972
   346
}
slouken@8972
   347
slouken@8972
   348
static void
dludwig@9918
   349
UpdateXInputJoystickState(SDL_Joystick * joystick, XINPUT_STATE_EX *pXInputState, XINPUT_BATTERY_INFORMATION_EX *pBatteryInformation)
slouken@8972
   350
{
slouken@8972
   351
    static WORD s_XInputButtons[] = {
slouken@8972
   352
        XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, XINPUT_GAMEPAD_X, XINPUT_GAMEPAD_Y,
slouken@8972
   353
        XINPUT_GAMEPAD_LEFT_SHOULDER, XINPUT_GAMEPAD_RIGHT_SHOULDER, XINPUT_GAMEPAD_BACK, XINPUT_GAMEPAD_START,
slouken@8972
   354
        XINPUT_GAMEPAD_LEFT_THUMB, XINPUT_GAMEPAD_RIGHT_THUMB,
slouken@8972
   355
        XINPUT_GAMEPAD_GUIDE
slouken@8972
   356
    };
slouken@8972
   357
    WORD wButtons = pXInputState->Gamepad.wButtons;
slouken@8972
   358
    Uint8 button;
slouken@8972
   359
    Uint8 hat = SDL_HAT_CENTERED;
slouken@8972
   360
slouken@8972
   361
    SDL_PrivateJoystickAxis(joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX);
slouken@8972
   362
    SDL_PrivateJoystickAxis(joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)));
slouken@8972
   363
    SDL_PrivateJoystickAxis(joystick, 2, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger * 65535 / 255) - 32768));
slouken@8972
   364
    SDL_PrivateJoystickAxis(joystick, 3, (Sint16)pXInputState->Gamepad.sThumbRX);
slouken@8972
   365
    SDL_PrivateJoystickAxis(joystick, 4, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbRY)));
slouken@8972
   366
    SDL_PrivateJoystickAxis(joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger * 65535 / 255) - 32768));
slouken@8972
   367
slouken@8972
   368
    for (button = 0; button < SDL_arraysize(s_XInputButtons); ++button) {
slouken@8972
   369
        SDL_PrivateJoystickButton(joystick, button, (wButtons & s_XInputButtons[button]) ? SDL_PRESSED : SDL_RELEASED);
slouken@8972
   370
    }
slouken@8972
   371
slouken@8972
   372
    if (wButtons & XINPUT_GAMEPAD_DPAD_UP) {
slouken@8972
   373
        hat |= SDL_HAT_UP;
slouken@8972
   374
    }
slouken@8972
   375
    if (wButtons & XINPUT_GAMEPAD_DPAD_DOWN) {
slouken@8972
   376
        hat |= SDL_HAT_DOWN;
slouken@8972
   377
    }
slouken@8972
   378
    if (wButtons & XINPUT_GAMEPAD_DPAD_LEFT) {
slouken@8972
   379
        hat |= SDL_HAT_LEFT;
slouken@8972
   380
    }
slouken@8972
   381
    if (wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) {
slouken@8972
   382
        hat |= SDL_HAT_RIGHT;
slouken@8972
   383
    }
slouken@8972
   384
    SDL_PrivateJoystickHat(joystick, 0, hat);
slouken@9884
   385
slouken@9884
   386
    UpdateXInputJoystickBatteryInformation( joystick, pBatteryInformation );
slouken@8972
   387
}
slouken@8972
   388
slouken@8972
   389
void
slouken@8972
   390
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
slouken@8972
   391
{
slouken@8972
   392
    HRESULT result;
slouken@8972
   393
    XINPUT_STATE_EX XInputState;
dludwig@9918
   394
    XINPUT_BATTERY_INFORMATION_EX XBatteryInformation;
slouken@8972
   395
slouken@8972
   396
    if (!XINPUTGETSTATE)
slouken@8972
   397
        return;
slouken@8972
   398
slouken@8972
   399
    result = XINPUTGETSTATE(joystick->hwdata->userid, &XInputState);
slouken@8972
   400
    if (result == ERROR_DEVICE_NOT_CONNECTED) {
slouken@8972
   401
        joystick->hwdata->send_remove_event = SDL_TRUE;
slouken@8972
   402
        joystick->hwdata->removed = SDL_TRUE;
slouken@8972
   403
        return;
slouken@8972
   404
    }
slouken@8972
   405
slouken@9884
   406
    SDL_zero( XBatteryInformation );
slouken@9884
   407
    if ( XINPUTGETBATTERYINFORMATION )
slouken@9884
   408
    {
slouken@9884
   409
        result = XINPUTGETBATTERYINFORMATION( joystick->hwdata->userid, BATTERY_DEVTYPE_GAMEPAD, &XBatteryInformation );
slouken@9884
   410
    }
slouken@9884
   411
slouken@8972
   412
    /* only fire events if the data changed from last time */
slouken@8972
   413
    if (XInputState.dwPacketNumber && XInputState.dwPacketNumber != joystick->hwdata->dwPacketNumber) {
slouken@8972
   414
        if (SDL_XInputUseOldJoystickMapping()) {
slouken@9884
   415
            UpdateXInputJoystickState_OLD(joystick, &XInputState, &XBatteryInformation);
slouken@8972
   416
        } else {
slouken@9884
   417
            UpdateXInputJoystickState(joystick, &XInputState, &XBatteryInformation);
slouken@8972
   418
        }
slouken@8972
   419
        joystick->hwdata->dwPacketNumber = XInputState.dwPacketNumber;
slouken@8972
   420
    }
slouken@8972
   421
}
slouken@8972
   422
slouken@8972
   423
void
slouken@8972
   424
SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
slouken@8972
   425
{
slouken@8972
   426
}
slouken@8972
   427
slouken@8972
   428
void
slouken@8972
   429
SDL_XINPUT_JoystickQuit(void)
slouken@8972
   430
{
slouken@8972
   431
    if (s_bXInputEnabled) {
slouken@8972
   432
        WIN_UnloadXInputDLL();
slouken@8972
   433
    }
slouken@8972
   434
}
slouken@8972
   435
slouken@8972
   436
SDL_bool
slouken@8972
   437
SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
slouken@8972
   438
{
slouken@8972
   439
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   440
    int index;
slouken@8972
   441
slouken@8972
   442
    for (index = device_index; index > 0; index--)
slouken@8972
   443
        device = device->pNext;
slouken@8972
   444
slouken@10074
   445
    return device->bXInputDevice;
slouken@8972
   446
}
slouken@8972
   447
slouken@8972
   448
#else /* !SDL_JOYSTICK_XINPUT */
slouken@8972
   449
icculus@9660
   450
typedef struct JoyStick_DeviceData JoyStick_DeviceData;
slouken@8972
   451
slouken@8972
   452
SDL_bool SDL_XINPUT_Enabled(void)
slouken@8972
   453
{
slouken@8972
   454
    return SDL_FALSE;
slouken@8972
   455
}
slouken@8972
   456
slouken@8972
   457
int
slouken@8972
   458
SDL_XINPUT_JoystickInit(void)
slouken@8972
   459
{
slouken@8972
   460
    return 0;
slouken@8972
   461
}
slouken@8972
   462
slouken@8972
   463
void
slouken@8972
   464
SDL_XINPUT_JoystickDetect(JoyStick_DeviceData **pContext)
slouken@8972
   465
{
slouken@8972
   466
}
slouken@8972
   467
slouken@8972
   468
int
slouken@8972
   469
SDL_XINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice)
slouken@8972
   470
{
slouken@8972
   471
    return SDL_Unsupported();
slouken@8972
   472
}
slouken@8972
   473
slouken@8972
   474
void
slouken@8972
   475
SDL_XINPUT_JoystickUpdate(SDL_Joystick * joystick)
slouken@8972
   476
{
slouken@8972
   477
}
slouken@8972
   478
slouken@8972
   479
void
slouken@8972
   480
SDL_XINPUT_JoystickClose(SDL_Joystick * joystick)
slouken@8972
   481
{
slouken@8972
   482
}
slouken@8972
   483
slouken@8972
   484
void
slouken@8972
   485
SDL_XINPUT_JoystickQuit(void)
slouken@8972
   486
{
slouken@8972
   487
}
slouken@8972
   488
slouken@8972
   489
#endif /* SDL_JOYSTICK_XINPUT */
slouken@8972
   490
slouken@8972
   491
/* vi: set ts=4 sw=4 expandtab: */