src/joystick/windows/SDL_windowsjoystick.c
author Ryan C. Gordon
Tue, 12 Apr 2016 16:45:10 -0400
changeset 10146 471eb08040ce
parent 9998 f67cf37e9cd4
child 10147 ddbdc9c1b92f
permissions -rw-r--r--
threads: Move SDL's own thread creation to a new internal API.

This allows us to set an explicit stack size (overriding the system default
and the global hint an app might have set), and remove all the macro salsa
for dealing with _beginthreadex and such, as internal threads always set those
to NULL anyhow.

I've taken some guesses on reasonable (and tiny!) stack sizes for our
internal threads, but some of these might turn out to be too small in
practice and need an increase. Most of them are simple functions, though.
slouken@8972
     1
/*
slouken@8972
     2
  Simple DirectMedia Layer
slouken@9998
     3
  Copyright (C) 1997-2016 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
slouken@8972
    23
#if SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT
slouken@8972
    24
slouken@8972
    25
/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
slouken@8972
    26
 * A. Formiga's WINMM driver.
slouken@8972
    27
 *
slouken@8972
    28
 * Hats and sliders are completely untested; the app I'm writing this for mostly
slouken@8972
    29
 * doesn't use them and I don't own any joysticks with them.
slouken@8972
    30
 *
slouken@8972
    31
 * We don't bother to use event notification here.  It doesn't seem to work
slouken@8972
    32
 * with polled devices, and it's fine to call IDirectInputDevice8_GetDeviceData and
slouken@8972
    33
 * let it return 0 events. */
slouken@8972
    34
slouken@8972
    35
#include "SDL_error.h"
slouken@8972
    36
#include "SDL_assert.h"
slouken@8972
    37
#include "SDL_events.h"
slouken@8972
    38
#include "SDL_timer.h"
slouken@8972
    39
#include "SDL_mutex.h"
slouken@8972
    40
#include "SDL_events.h"
slouken@8972
    41
#include "SDL_hints.h"
slouken@8972
    42
#include "SDL_joystick.h"
slouken@8972
    43
#include "../SDL_sysjoystick.h"
icculus@10146
    44
#include "../thread/SDL_systhread.h"
slouken@8972
    45
#if !SDL_EVENTS_DISABLED
slouken@8972
    46
#include "../../events/SDL_events_c.h"
slouken@8972
    47
#endif
slouken@8972
    48
#include "../../core/windows/SDL_windows.h"
dludwig@9166
    49
#if !defined(__WINRT__)
slouken@8972
    50
#include <dbt.h>
dludwig@9166
    51
#endif
slouken@8972
    52
slouken@8972
    53
#define INITGUID /* Only set here, if set twice will cause mingw32 to break. */
slouken@8972
    54
#include "SDL_windowsjoystick_c.h"
slouken@8972
    55
#include "SDL_dinputjoystick_c.h"
slouken@8972
    56
#include "SDL_xinputjoystick_c.h"
slouken@8972
    57
slouken@8972
    58
#include "../../haptic/windows/SDL_dinputhaptic_c.h"    /* For haptic hot plugging */
slouken@8972
    59
#include "../../haptic/windows/SDL_xinputhaptic_c.h"    /* For haptic hot plugging */
slouken@8972
    60
slouken@8972
    61
slouken@8988
    62
#ifndef DEVICE_NOTIFY_WINDOW_HANDLE
slouken@8988
    63
#define DEVICE_NOTIFY_WINDOW_HANDLE 0x00000000
slouken@8988
    64
#endif
slouken@8988
    65
slouken@8972
    66
/* local variables */
slouken@8972
    67
static SDL_bool s_bDeviceAdded = SDL_FALSE;
slouken@8972
    68
static SDL_bool s_bDeviceRemoved = SDL_FALSE;
slouken@8972
    69
static SDL_JoystickID s_nInstanceID = -1;
slouken@8972
    70
static SDL_cond *s_condJoystickThread = NULL;
slouken@8972
    71
static SDL_mutex *s_mutexJoyStickEnum = NULL;
slouken@8972
    72
static SDL_Thread *s_threadJoystick = NULL;
slouken@8972
    73
static SDL_bool s_bJoystickThreadQuit = SDL_FALSE;
slouken@8972
    74
slouken@8972
    75
JoyStick_DeviceData *SYS_Joystick;    /* array to hold joystick ID values */
slouken@8972
    76
slouken@8972
    77
static SDL_bool s_bWindowsDeviceChanged = SDL_FALSE;
slouken@8972
    78
slouken@8972
    79
#ifdef __WINRT__
slouken@8972
    80
slouken@8972
    81
typedef struct
slouken@8972
    82
{
slouken@8972
    83
    int unused;
slouken@8972
    84
} SDL_DeviceNotificationData;
slouken@8972
    85
slouken@8972
    86
static void
slouken@8972
    87
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
    88
{
slouken@8972
    89
}
slouken@8972
    90
slouken@8972
    91
static int
slouken@8972
    92
SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
    93
{
slouken@8972
    94
    return 0;
slouken@8972
    95
}
slouken@8972
    96
slouken@8972
    97
static void
slouken@8972
    98
SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
    99
{
slouken@8972
   100
}
slouken@8972
   101
slouken@8972
   102
#else /* !__WINRT__ */
slouken@8972
   103
slouken@8972
   104
typedef struct
slouken@8972
   105
{
slouken@8972
   106
    HRESULT coinitialized;
slouken@8972
   107
    WNDCLASSEX wincl;
slouken@8972
   108
    HWND messageWindow;
slouken@8972
   109
    HDEVNOTIFY hNotify;
slouken@8972
   110
} SDL_DeviceNotificationData;
slouken@8972
   111
slouken@8972
   112
slouken@8972
   113
/* windowproc for our joystick detect thread message only window, to detect any USB device addition/removal */
slouken@8972
   114
static LRESULT CALLBACK
slouken@8972
   115
SDL_PrivateJoystickDetectProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
slouken@8972
   116
{
slouken@8972
   117
    switch (message) {
slouken@8972
   118
    case WM_DEVICECHANGE:
slouken@8972
   119
        switch (wParam) {
slouken@8972
   120
        case DBT_DEVICEARRIVAL:
slouken@8972
   121
            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
slouken@8972
   122
                s_bWindowsDeviceChanged = SDL_TRUE;
slouken@8972
   123
            }
slouken@8972
   124
            break;
slouken@8972
   125
        case DBT_DEVICEREMOVECOMPLETE:
slouken@8972
   126
            if (((DEV_BROADCAST_HDR*)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
slouken@8972
   127
                s_bWindowsDeviceChanged = SDL_TRUE;
slouken@8972
   128
            }
slouken@8972
   129
            break;
slouken@8972
   130
        }
slouken@8972
   131
        return 0;
slouken@8972
   132
    }
slouken@8972
   133
slouken@8972
   134
    return DefWindowProc (hwnd, message, wParam, lParam);
slouken@8972
   135
}
slouken@8972
   136
slouken@8972
   137
static void
slouken@8972
   138
SDL_CleanupDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
   139
{
slouken@8972
   140
    if (data->hNotify)
slouken@8972
   141
        UnregisterDeviceNotification(data->hNotify);
slouken@8972
   142
slouken@8972
   143
    if (data->messageWindow)
slouken@8972
   144
        DestroyWindow(data->messageWindow);
slouken@8972
   145
slouken@8972
   146
    UnregisterClass(data->wincl.lpszClassName, data->wincl.hInstance);
slouken@8972
   147
slouken@8972
   148
    if (data->coinitialized == S_OK) {
slouken@8972
   149
        WIN_CoUninitialize();
slouken@8972
   150
    }
slouken@8972
   151
}
slouken@8972
   152
slouken@8972
   153
static int
slouken@8972
   154
SDL_CreateDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
   155
{
slouken@8972
   156
    DEV_BROADCAST_DEVICEINTERFACE dbh;
slouken@8972
   157
    GUID GUID_DEVINTERFACE_HID = { 0x4D1E55B2L, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };
slouken@8972
   158
slouken@8972
   159
    SDL_zerop(data);
slouken@8972
   160
slouken@8972
   161
    data->coinitialized = WIN_CoInitialize();
slouken@8972
   162
slouken@8972
   163
    data->wincl.hInstance = GetModuleHandle(NULL);
slouken@8972
   164
    data->wincl.lpszClassName = L"Message";
slouken@8972
   165
    data->wincl.lpfnWndProc = SDL_PrivateJoystickDetectProc;      /* This function is called by windows */
slouken@8972
   166
    data->wincl.cbSize = sizeof (WNDCLASSEX);
slouken@8972
   167
slouken@8972
   168
    if (!RegisterClassEx(&data->wincl)) {
slouken@8972
   169
        WIN_SetError("Failed to create register class for joystick autodetect");
slouken@8972
   170
        SDL_CleanupDeviceNotification(data);
slouken@8972
   171
        return -1;
slouken@8972
   172
    }
slouken@8972
   173
slouken@8972
   174
    data->messageWindow = (HWND)CreateWindowEx(0,  L"Message", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
slouken@8972
   175
    if (!data->messageWindow) {
slouken@8972
   176
        WIN_SetError("Failed to create message window for joystick autodetect");
slouken@8972
   177
        SDL_CleanupDeviceNotification(data);
slouken@8972
   178
        return -1;
slouken@8972
   179
    }
slouken@8972
   180
slouken@8972
   181
    SDL_zero(dbh);
slouken@8972
   182
    dbh.dbcc_size = sizeof(dbh);
slouken@8972
   183
    dbh.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
slouken@8972
   184
    dbh.dbcc_classguid = GUID_DEVINTERFACE_HID;
slouken@8972
   185
slouken@8972
   186
    data->hNotify = RegisterDeviceNotification(data->messageWindow, &dbh, DEVICE_NOTIFY_WINDOW_HANDLE);
slouken@8972
   187
    if (!data->hNotify) {
slouken@8972
   188
        WIN_SetError("Failed to create notify device for joystick autodetect");
slouken@8972
   189
        SDL_CleanupDeviceNotification(data);
slouken@8972
   190
        return -1;
slouken@8972
   191
    }
slouken@8972
   192
    return 0;
slouken@8972
   193
}
slouken@8972
   194
slouken@8972
   195
static void
slouken@8972
   196
SDL_CheckDeviceNotification(SDL_DeviceNotificationData *data)
slouken@8972
   197
{
slouken@8972
   198
    MSG msg;
slouken@8972
   199
slouken@8972
   200
    if (!data->messageWindow) {
slouken@8972
   201
        return;
slouken@8972
   202
    }
slouken@8972
   203
slouken@8972
   204
    while (PeekMessage(&msg, data->messageWindow, 0, 0, PM_NOREMOVE)) {
slouken@8972
   205
        if (GetMessage(&msg, data->messageWindow, 0, 0) != 0)  {
slouken@8972
   206
            TranslateMessage(&msg);
slouken@8972
   207
            DispatchMessage(&msg);
slouken@8972
   208
        }
slouken@8972
   209
    }
slouken@8972
   210
}
slouken@8972
   211
slouken@8972
   212
#endif /* __WINRT__ */
slouken@8972
   213
slouken@8972
   214
/* Function/thread to scan the system for joysticks. */
slouken@8972
   215
static int
slouken@8972
   216
SDL_JoystickThread(void *_data)
slouken@8972
   217
{
slouken@8972
   218
    SDL_DeviceNotificationData notification_data;
slouken@8972
   219
slouken@8972
   220
#if SDL_JOYSTICK_XINPUT
slouken@8972
   221
    SDL_bool bOpenedXInputDevices[XUSER_MAX_COUNT];
slouken@8972
   222
    SDL_zero(bOpenedXInputDevices);
slouken@8972
   223
#endif
slouken@8972
   224
slouken@8972
   225
    if (SDL_CreateDeviceNotification(&notification_data) < 0) {
slouken@8972
   226
        return -1;
slouken@8972
   227
    }
slouken@8972
   228
slouken@8972
   229
    SDL_LockMutex(s_mutexJoyStickEnum);
slouken@8972
   230
    while (s_bJoystickThreadQuit == SDL_FALSE) {
slouken@8972
   231
        SDL_bool bXInputChanged = SDL_FALSE;
slouken@8972
   232
slouken@8972
   233
        SDL_CondWaitTimeout(s_condJoystickThread, s_mutexJoyStickEnum, 300);
slouken@8972
   234
slouken@8972
   235
        SDL_CheckDeviceNotification(&notification_data);
slouken@8972
   236
slouken@8972
   237
#if SDL_JOYSTICK_XINPUT
slouken@8972
   238
        if (SDL_XINPUT_Enabled() && XINPUTGETCAPABILITIES) {
slouken@8972
   239
            /* scan for any change in XInput devices */
slouken@8972
   240
            Uint8 userId;
slouken@8972
   241
            for (userId = 0; userId < XUSER_MAX_COUNT; userId++) {
slouken@8972
   242
                XINPUT_CAPABILITIES capabilities;
slouken@8972
   243
                const DWORD result = XINPUTGETCAPABILITIES(userId, XINPUT_FLAG_GAMEPAD, &capabilities);
slouken@8972
   244
                const SDL_bool available = (result == ERROR_SUCCESS);
slouken@8972
   245
                if (bOpenedXInputDevices[userId] != available) {
slouken@8972
   246
                    bXInputChanged = SDL_TRUE;
slouken@8972
   247
                    bOpenedXInputDevices[userId] = available;
slouken@8972
   248
                }
slouken@8972
   249
            }
slouken@8972
   250
        }
slouken@8972
   251
#endif /* SDL_JOYSTICK_XINPUT */
slouken@8972
   252
slouken@8972
   253
        if (s_bWindowsDeviceChanged || bXInputChanged) {
slouken@8972
   254
            SDL_UnlockMutex(s_mutexJoyStickEnum);  /* let main thread go while we SDL_Delay(). */
slouken@8972
   255
            SDL_Delay(300); /* wait for direct input to find out about this device */
slouken@8972
   256
            SDL_LockMutex(s_mutexJoyStickEnum);
slouken@8972
   257
slouken@8972
   258
            s_bDeviceRemoved = SDL_TRUE;
slouken@8972
   259
            s_bDeviceAdded = SDL_TRUE;
slouken@8972
   260
            s_bWindowsDeviceChanged = SDL_FALSE;
slouken@8972
   261
        }
slouken@8972
   262
    }
slouken@8972
   263
    SDL_UnlockMutex(s_mutexJoyStickEnum);
slouken@8972
   264
slouken@8972
   265
    SDL_CleanupDeviceNotification(&notification_data);
slouken@8972
   266
slouken@8972
   267
    return 1;
slouken@8972
   268
}
slouken@8972
   269
slouken@8972
   270
void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device)
slouken@8972
   271
{
slouken@8972
   272
    device->send_add_event = SDL_TRUE;
slouken@8972
   273
    device->nInstanceID = ++s_nInstanceID;
slouken@8972
   274
    device->pNext = SYS_Joystick;
slouken@8972
   275
    SYS_Joystick = device;
slouken@8972
   276
slouken@8972
   277
    s_bDeviceAdded = SDL_TRUE;
slouken@8972
   278
}
slouken@8972
   279
slouken@8972
   280
/* Function to scan the system for joysticks.
philipp@9311
   281
 * Joystick 0 should be the system default joystick.
slouken@8972
   282
 * It should return 0, or -1 on an unrecoverable fatal error.
slouken@8972
   283
 */
slouken@8972
   284
int
slouken@8972
   285
SDL_SYS_JoystickInit(void)
slouken@8972
   286
{
slouken@8972
   287
    if (SDL_DINPUT_JoystickInit() < 0) {
slouken@8972
   288
        SDL_SYS_JoystickQuit();
slouken@8972
   289
        return -1;
slouken@8972
   290
    }
slouken@8972
   291
slouken@8972
   292
    if (SDL_XINPUT_JoystickInit() < 0) {
slouken@8972
   293
        SDL_SYS_JoystickQuit();
slouken@8972
   294
        return -1;
slouken@8972
   295
    }
slouken@8972
   296
slouken@8972
   297
    s_mutexJoyStickEnum = SDL_CreateMutex();
slouken@8972
   298
    s_condJoystickThread = SDL_CreateCond();
slouken@8972
   299
    s_bDeviceAdded = SDL_TRUE; /* force a scan of the system for joysticks this first time */
slouken@8972
   300
slouken@8972
   301
    SDL_SYS_JoystickDetect();
slouken@8972
   302
slouken@8972
   303
    if (!s_threadJoystick) {
icculus@10146
   304
        /* spin up the thread to detect hotplug of devices */
slouken@8972
   305
        s_bJoystickThreadQuit = SDL_FALSE;
icculus@10146
   306
        s_threadJoystick = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
slouken@8972
   307
    }
slouken@8972
   308
    return SDL_SYS_NumJoysticks();
slouken@8972
   309
}
slouken@8972
   310
slouken@8972
   311
/* return the number of joysticks that are connected right now */
slouken@8972
   312
int
slouken@8972
   313
SDL_SYS_NumJoysticks()
slouken@8972
   314
{
slouken@8972
   315
    int nJoysticks = 0;
slouken@8972
   316
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   317
    while (device) {
slouken@8972
   318
        nJoysticks++;
slouken@8972
   319
        device = device->pNext;
slouken@8972
   320
    }
slouken@8972
   321
slouken@8972
   322
    return nJoysticks;
slouken@8972
   323
}
slouken@8972
   324
slouken@8972
   325
/* detect any new joysticks being inserted into the system */
slouken@8972
   326
void
slouken@8972
   327
SDL_SYS_JoystickDetect()
slouken@8972
   328
{
slouken@8972
   329
    JoyStick_DeviceData *pCurList = NULL;
slouken@8972
   330
#if !SDL_EVENTS_DISABLED
slouken@8972
   331
    SDL_Event event;
slouken@8972
   332
#endif
slouken@8972
   333
slouken@8972
   334
    /* only enum the devices if the joystick thread told us something changed */
slouken@8972
   335
    if (!s_bDeviceAdded && !s_bDeviceRemoved) {
slouken@8972
   336
        return;  /* thread hasn't signaled, nothing to do right now. */
slouken@8972
   337
    }
slouken@8972
   338
slouken@8972
   339
    SDL_LockMutex(s_mutexJoyStickEnum);
slouken@8972
   340
slouken@8972
   341
    s_bDeviceAdded = SDL_FALSE;
slouken@8972
   342
    s_bDeviceRemoved = SDL_FALSE;
slouken@8972
   343
slouken@8972
   344
    pCurList = SYS_Joystick;
slouken@8972
   345
    SYS_Joystick = NULL;
slouken@8972
   346
slouken@8972
   347
    /* Look for DirectInput joysticks, wheels, head trackers, gamepads, etc.. */
slouken@8972
   348
    SDL_DINPUT_JoystickDetect(&pCurList);
slouken@8972
   349
slouken@8972
   350
    /* Look for XInput devices. Do this last, so they're first in the final list. */
slouken@8972
   351
    SDL_XINPUT_JoystickDetect(&pCurList);
slouken@8972
   352
slouken@8972
   353
    SDL_UnlockMutex(s_mutexJoyStickEnum);
slouken@8972
   354
slouken@8972
   355
    while (pCurList) {
slouken@8972
   356
        JoyStick_DeviceData *pListNext = NULL;
slouken@8972
   357
slouken@8972
   358
        if (pCurList->bXInputDevice) {
slouken@8972
   359
            SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId);
slouken@8972
   360
        } else {
slouken@8972
   361
            SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
slouken@8972
   362
        }
slouken@8972
   363
slouken@8972
   364
#if !SDL_EVENTS_DISABLED
slouken@8972
   365
        SDL_zero(event);
slouken@8972
   366
        event.type = SDL_JOYDEVICEREMOVED;
slouken@8972
   367
slouken@8972
   368
        if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@8972
   369
            event.jdevice.which = pCurList->nInstanceID;
slouken@8972
   370
            if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@8972
   371
                SDL_PushEvent(&event);
slouken@8972
   372
            }
slouken@8972
   373
        }
slouken@8972
   374
#endif /* !SDL_EVENTS_DISABLED */
slouken@8972
   375
slouken@8972
   376
        pListNext = pCurList->pNext;
slouken@8972
   377
        SDL_free(pCurList->joystickname);
slouken@8972
   378
        SDL_free(pCurList);
slouken@8972
   379
        pCurList = pListNext;
slouken@8972
   380
    }
slouken@8972
   381
slouken@8972
   382
    if (s_bDeviceAdded) {
slouken@8972
   383
        JoyStick_DeviceData *pNewJoystick;
slouken@8972
   384
        int device_index = 0;
slouken@8972
   385
        s_bDeviceAdded = SDL_FALSE;
slouken@8972
   386
        pNewJoystick = SYS_Joystick;
slouken@8972
   387
        while (pNewJoystick) {
slouken@8972
   388
            if (pNewJoystick->send_add_event) {
slouken@8972
   389
                if (pNewJoystick->bXInputDevice) {
slouken@8972
   390
                    SDL_XINPUT_MaybeAddDevice(pNewJoystick->XInputUserId);
slouken@8972
   391
                } else {
slouken@8972
   392
                    SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
slouken@8972
   393
                }
slouken@8972
   394
slouken@8972
   395
#if !SDL_EVENTS_DISABLED
slouken@8972
   396
                SDL_zero(event);
slouken@8972
   397
                event.type = SDL_JOYDEVICEADDED;
slouken@8972
   398
slouken@8972
   399
                if (SDL_GetEventState(event.type) == SDL_ENABLE) {
slouken@8972
   400
                    event.jdevice.which = device_index;
slouken@8972
   401
                    if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
slouken@8972
   402
                        SDL_PushEvent(&event);
slouken@8972
   403
                    }
slouken@8972
   404
                }
slouken@8972
   405
#endif /* !SDL_EVENTS_DISABLED */
slouken@8972
   406
                pNewJoystick->send_add_event = SDL_FALSE;
slouken@8972
   407
            }
slouken@8972
   408
            device_index++;
slouken@8972
   409
            pNewJoystick = pNewJoystick->pNext;
slouken@8972
   410
        }
slouken@8972
   411
    }
slouken@8972
   412
}
slouken@8972
   413
slouken@8972
   414
/* Function to get the device-dependent name of a joystick */
slouken@8972
   415
const char *
slouken@8972
   416
SDL_SYS_JoystickNameForDeviceIndex(int device_index)
slouken@8972
   417
{
slouken@8972
   418
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   419
slouken@8972
   420
    for (; device_index > 0; device_index--)
slouken@8972
   421
        device = device->pNext;
slouken@8972
   422
slouken@8972
   423
    return device->joystickname;
slouken@8972
   424
}
slouken@8972
   425
slouken@8972
   426
/* Function to perform the mapping between current device instance and this joysticks instance id */
slouken@8972
   427
SDL_JoystickID
slouken@8972
   428
SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index)
slouken@8972
   429
{
slouken@8972
   430
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   431
    int index;
slouken@8972
   432
slouken@8972
   433
    for (index = device_index; index > 0; index--)
slouken@8972
   434
        device = device->pNext;
slouken@8972
   435
slouken@8972
   436
    return device->nInstanceID;
slouken@8972
   437
}
slouken@8972
   438
slouken@8972
   439
/* Function to open a joystick for use.
philipp@9380
   440
   The joystick to open is specified by the device index.
slouken@8972
   441
   This should fill the nbuttons and naxes fields of the joystick structure.
slouken@8972
   442
   It returns 0, or -1 if there is an error.
slouken@8972
   443
 */
slouken@8972
   444
int
slouken@8972
   445
SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
slouken@8972
   446
{
slouken@8972
   447
    JoyStick_DeviceData *joystickdevice = SYS_Joystick;
slouken@8972
   448
slouken@8972
   449
    for (; device_index > 0; device_index--)
slouken@8972
   450
        joystickdevice = joystickdevice->pNext;
slouken@8972
   451
slouken@8972
   452
    /* allocate memory for system specific hardware data */
slouken@8972
   453
    joystick->instance_id = joystickdevice->nInstanceID;
slouken@8972
   454
    joystick->hwdata =
slouken@8972
   455
        (struct joystick_hwdata *) SDL_malloc(sizeof(struct joystick_hwdata));
slouken@8972
   456
    if (joystick->hwdata == NULL) {
slouken@8972
   457
        return SDL_OutOfMemory();
slouken@8972
   458
    }
slouken@8972
   459
    SDL_zerop(joystick->hwdata);
slouken@8972
   460
    joystick->hwdata->guid = joystickdevice->guid;
slouken@8972
   461
slouken@8972
   462
    if (joystickdevice->bXInputDevice) {
slouken@8972
   463
        return SDL_XINPUT_JoystickOpen(joystick, joystickdevice);
slouken@8972
   464
    } else {
slouken@8972
   465
        return SDL_DINPUT_JoystickOpen(joystick, joystickdevice);
slouken@8972
   466
    }
slouken@8972
   467
}
slouken@8972
   468
slouken@8972
   469
/* return true if this joystick is plugged in right now */
slouken@8972
   470
SDL_bool 
slouken@8972
   471
SDL_SYS_JoystickAttached(SDL_Joystick * joystick)
slouken@8972
   472
{
icculus@9433
   473
    return joystick->hwdata && !joystick->hwdata->removed;
slouken@8972
   474
}
slouken@8972
   475
slouken@8972
   476
void
slouken@8972
   477
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
slouken@8972
   478
{
icculus@9433
   479
    if (!joystick->hwdata || joystick->hwdata->removed) {
slouken@8972
   480
        return;
slouken@8972
   481
    }
slouken@8972
   482
slouken@8972
   483
    if (joystick->hwdata->bXInputDevice) {
slouken@8972
   484
        SDL_XINPUT_JoystickUpdate(joystick);
slouken@8972
   485
    } else {
slouken@8972
   486
        SDL_DINPUT_JoystickUpdate(joystick);
slouken@8972
   487
    }
slouken@8972
   488
slouken@8972
   489
    if (joystick->hwdata->removed) {
icculus@9433
   490
        joystick->force_recentering = SDL_TRUE;
slouken@8972
   491
    }
slouken@8972
   492
}
slouken@8972
   493
slouken@8972
   494
/* Function to close a joystick after use */
slouken@8972
   495
void
slouken@8972
   496
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
slouken@8972
   497
{
slouken@8972
   498
    if (joystick->hwdata->bXInputDevice) {
slouken@8972
   499
        SDL_XINPUT_JoystickClose(joystick);
slouken@8972
   500
    } else {
slouken@8972
   501
        SDL_DINPUT_JoystickClose(joystick);
slouken@8972
   502
    }
slouken@8972
   503
slouken@8972
   504
    SDL_free(joystick->hwdata);
slouken@8972
   505
}
slouken@8972
   506
slouken@8972
   507
/* Function to perform any system-specific joystick related cleanup */
slouken@8972
   508
void
slouken@8972
   509
SDL_SYS_JoystickQuit(void)
slouken@8972
   510
{
slouken@8972
   511
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   512
slouken@8972
   513
    while (device) {
slouken@8972
   514
        JoyStick_DeviceData *device_next = device->pNext;
slouken@8972
   515
        SDL_free(device->joystickname);
slouken@8972
   516
        SDL_free(device);
slouken@8972
   517
        device = device_next;
slouken@8972
   518
    }
slouken@8972
   519
    SYS_Joystick = NULL;
slouken@8972
   520
slouken@8972
   521
    if (s_threadJoystick) {
slouken@8972
   522
        SDL_LockMutex(s_mutexJoyStickEnum);
slouken@8972
   523
        s_bJoystickThreadQuit = SDL_TRUE;
slouken@8972
   524
        SDL_CondBroadcast(s_condJoystickThread); /* signal the joystick thread to quit */
slouken@8972
   525
        SDL_UnlockMutex(s_mutexJoyStickEnum);
slouken@8972
   526
        SDL_WaitThread(s_threadJoystick, NULL); /* wait for it to bugger off */
slouken@8972
   527
slouken@8972
   528
        SDL_DestroyMutex(s_mutexJoyStickEnum);
slouken@8972
   529
        SDL_DestroyCond(s_condJoystickThread);
slouken@8972
   530
        s_condJoystickThread= NULL;
slouken@8972
   531
        s_mutexJoyStickEnum = NULL;
slouken@8972
   532
        s_threadJoystick = NULL;
slouken@8972
   533
    }
slouken@8972
   534
slouken@8972
   535
    SDL_DINPUT_JoystickQuit();
slouken@8972
   536
    SDL_XINPUT_JoystickQuit();
slouken@8972
   537
}
slouken@8972
   538
slouken@8972
   539
/* return the stable device guid for this device index */
slouken@8972
   540
SDL_JoystickGUID
slouken@8972
   541
SDL_SYS_JoystickGetDeviceGUID(int device_index)
slouken@8972
   542
{
slouken@8972
   543
    JoyStick_DeviceData *device = SYS_Joystick;
slouken@8972
   544
    int index;
slouken@8972
   545
slouken@8972
   546
    for (index = device_index; index > 0; index--)
slouken@8972
   547
        device = device->pNext;
slouken@8972
   548
slouken@8972
   549
    return device->guid;
slouken@8972
   550
}
slouken@8972
   551
slouken@8972
   552
SDL_JoystickGUID
slouken@8972
   553
SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick)
slouken@8972
   554
{
slouken@8972
   555
    return joystick->hwdata->guid;
slouken@8972
   556
}
slouken@8972
   557
slouken@8972
   558
#endif /* SDL_JOYSTICK_DINPUT || SDL_JOYSTICK_XINPUT */
slouken@8972
   559
slouken@8972
   560
/* vi: set ts=4 sw=4 expandtab: */