src/joystick/win32/SDL_dxjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1661 281d3f4870e5
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

The headers are being converted to automatically generate doxygen documentation.
slouken@1661
     1
/*
slouken@1661
     2
    SDL - Simple DirectMedia Layer
slouken@1661
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@1661
     4
slouken@1661
     5
    This library is free software; you can redistribute it and/or
slouken@1661
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1661
     7
    License as published by the Free Software Foundation; either
slouken@1661
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@1661
     9
slouken@1661
    10
    This library is distributed in the hope that it will be useful,
slouken@1661
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1661
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1661
    13
    Lesser General Public License for more details.
slouken@1661
    14
slouken@1661
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1661
    16
    License along with this library; if not, write to the Free Software
slouken@1661
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@1661
    18
slouken@1661
    19
    Sam Lantinga
slouken@1661
    20
    slouken@libsdl.org
slouken@1661
    21
*/
slouken@1661
    22
#include "SDL_config.h"
slouken@1661
    23
slouken@1661
    24
#ifdef SDL_JOYSTICK_DINPUT
slouken@1661
    25
slouken@1661
    26
/* DirectInput joystick driver; written by Glenn Maynard, based on Andrei de
slouken@1661
    27
 * A. Formiga's WINMM driver. 
slouken@1661
    28
 *
slouken@1661
    29
 * Hats and sliders are completely untested; the app I'm writing this for mostly
slouken@1661
    30
 * doesn't use them and I don't own any joysticks with them. 
slouken@1661
    31
 *
slouken@1661
    32
 * We don't bother to use event notification here.  It doesn't seem to work
slouken@1661
    33
 * with polled devices, and it's fine to call IDirectInputDevice2_GetDeviceData and
slouken@1661
    34
 * let it return 0 events. */
slouken@1661
    35
slouken@1661
    36
#include "SDL_error.h"
slouken@1661
    37
#include "SDL_events.h"
slouken@1661
    38
#include "SDL_joystick.h"
slouken@1661
    39
#include "../SDL_sysjoystick.h"
slouken@1661
    40
#include "../SDL_joystick_c.h"
slouken@1661
    41
slouken@1661
    42
#define WIN32_LEAN_AND_MEAN
slouken@1661
    43
#include <windows.h>
slouken@1661
    44
slouken@1661
    45
#define DIRECTINPUT_VERSION 0x0500
slouken@1661
    46
#include <dinput.h>
slouken@1661
    47
slouken@1662
    48
#define INPUT_QSIZE	32      /* Buffer up to 32 input messages */
slouken@1661
    49
slouken@1661
    50
extern HINSTANCE SDL_Instance;
slouken@1662
    51
extern int DX5_Load ();
slouken@1662
    52
extern void DX5_Unload ();
slouken@1662
    53
extern HRESULT (WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
slouken@1662
    54
                                        LPDIRECTINPUT * ppDI,
slouken@1662
    55
                                        LPUNKNOWN punkOuter);
slouken@1661
    56
slouken@1661
    57
static LPDIRECTINPUT dinput = NULL;
slouken@1661
    58
slouken@1661
    59
#define MAX_JOYSTICKS	8
slouken@1662
    60
#define MAX_INPUTS	256     /* each joystick can have up to 256 inputs */
slouken@1661
    61
#define AXIS_MIN	-32768  /* minimum value for axis coordinate */
slouken@1661
    62
#define AXIS_MAX	32767   /* maximum value for axis coordinate */
slouken@1662
    63
#define JOY_AXIS_THRESHOLD	(((AXIS_MAX)-(AXIS_MIN))/100)   /* 1% motion */
slouken@1661
    64
slouken@1662
    65
typedef enum Type
slouken@1662
    66
{ BUTTON, AXIS, HAT } Type;
slouken@1661
    67
slouken@1661
    68
/* array to hold joystick ID values */
slouken@1661
    69
static DIDEVICEINSTANCE SYS_Joystick[MAX_JOYSTICKS];
slouken@1662
    70
static int SYS_NumJoysticks;
slouken@1661
    71
slouken@1661
    72
extern HWND SDL_Window;
slouken@1661
    73
slouken@1661
    74
typedef struct input_t
slouken@1661
    75
{
slouken@1662
    76
    /* DirectInput offset for this input type: */
slouken@1662
    77
    DWORD ofs;
slouken@1661
    78
slouken@1662
    79
    /* Button, axis or hat: */
slouken@1662
    80
    Type type;
slouken@1661
    81
slouken@1662
    82
    /* SDL input offset: */
slouken@1662
    83
    Uint8 num;
slouken@1661
    84
} input_t;
slouken@1661
    85
slouken@1661
    86
/* The private structure used to keep track of a joystick */
slouken@1661
    87
struct joystick_hwdata
slouken@1661
    88
{
slouken@1662
    89
    LPDIRECTINPUTDEVICE2 InputDevice;
slouken@1662
    90
    int buffered;
slouken@1661
    91
slouken@1662
    92
    input_t Inputs[MAX_INPUTS];
slouken@1662
    93
    int NumInputs;
slouken@1661
    94
};
slouken@1661
    95
slouken@1661
    96
/* Convert a DirectInput return code to a text message */
slouken@1662
    97
static void
slouken@1662
    98
SetDIerror (char *function, int code)
slouken@1661
    99
{
slouken@1662
   100
    static char *error;
slouken@1662
   101
    static char errbuf[1024];
slouken@1661
   102
slouken@1662
   103
    errbuf[0] = 0;
slouken@1662
   104
    switch (code) {
slouken@1662
   105
    case DIERR_GENERIC:
slouken@1662
   106
        error = "Undefined error!";
slouken@1662
   107
        break;
slouken@1662
   108
    case DIERR_OLDDIRECTINPUTVERSION:
slouken@1662
   109
        error = "Your version of DirectInput needs upgrading";
slouken@1662
   110
        break;
slouken@1662
   111
    case DIERR_INVALIDPARAM:
slouken@1662
   112
        error = "Invalid parameters";
slouken@1662
   113
        break;
slouken@1662
   114
    case DIERR_OUTOFMEMORY:
slouken@1662
   115
        error = "Out of memory";
slouken@1662
   116
        break;
slouken@1662
   117
    case DIERR_DEVICENOTREG:
slouken@1662
   118
        error = "Device not registered";
slouken@1662
   119
        break;
slouken@1662
   120
    case DIERR_NOINTERFACE:
slouken@1662
   121
        error = "Interface not supported";
slouken@1662
   122
        break;
slouken@1662
   123
    case DIERR_NOTINITIALIZED:
slouken@1662
   124
        error = "Device not initialized";
slouken@1662
   125
        break;
slouken@1662
   126
    default:
slouken@1662
   127
        sprintf (errbuf, "%s: Unknown DirectInput error: 0x%x",
slouken@1662
   128
                 function, code);
slouken@1662
   129
        break;
slouken@1662
   130
    }
slouken@1662
   131
    if (!errbuf[0]) {
slouken@1662
   132
        sprintf (errbuf, "%s: %s", function, error);
slouken@1662
   133
    }
slouken@1662
   134
    SDL_SetError ("%s", errbuf);
slouken@1662
   135
    return;
slouken@1661
   136
}
slouken@1661
   137
slouken@1661
   138
slouken@1662
   139
BOOL CALLBACK
slouken@1662
   140
EnumJoysticksCallback (const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
slouken@1661
   141
{
slouken@1662
   142
    memcpy (&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
slouken@1662
   143
            sizeof (DIDEVICEINSTANCE));
slouken@1662
   144
    SYS_NumJoysticks++;
slouken@1661
   145
slouken@1662
   146
    if (SYS_NumJoysticks >= MAX_JOYSTICKS)
slouken@1662
   147
        return DIENUM_STOP;
slouken@1661
   148
slouken@1662
   149
    return DIENUM_CONTINUE;
slouken@1661
   150
}
slouken@1661
   151
slouken@1662
   152
static BOOL CALLBACK
slouken@1662
   153
DIJoystick_EnumDevObjectsProc (LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
slouken@1661
   154
{
slouken@1662
   155
    SDL_Joystick *joystick = (SDL_Joystick *) pvRef;
slouken@1662
   156
    HRESULT result;
slouken@1662
   157
    input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs];
slouken@1662
   158
    const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS;
slouken@1662
   159
    if (!(dev->dwType & SupportedMask))
slouken@1662
   160
        return DIENUM_CONTINUE; /* unsupported */
slouken@1661
   161
slouken@1662
   162
    in->ofs = dev->dwOfs;
slouken@1661
   163
slouken@1662
   164
    if (dev->dwType & DIDFT_BUTTON) {
slouken@1662
   165
        in->type = BUTTON;
slouken@1662
   166
        in->num = joystick->nbuttons;
slouken@1662
   167
        joystick->nbuttons++;
slouken@1662
   168
    } else if (dev->dwType & DIDFT_POV) {
slouken@1662
   169
        in->type = HAT;
slouken@1662
   170
        in->num = joystick->nhats;
slouken@1662
   171
        joystick->nhats++;
slouken@1662
   172
    } else {                    /* dev->dwType & DIDFT_AXIS */
slouken@1662
   173
        DIPROPRANGE diprg;
slouken@1662
   174
        DIPROPDWORD dilong;
slouken@1661
   175
slouken@1662
   176
        in->type = AXIS;
slouken@1662
   177
        in->num = joystick->naxes;
slouken@1661
   178
slouken@1662
   179
        diprg.diph.dwSize = sizeof (diprg);
slouken@1662
   180
        diprg.diph.dwHeaderSize = sizeof (diprg.diph);
slouken@1662
   181
        diprg.diph.dwObj = dev->dwOfs;
slouken@1662
   182
        diprg.diph.dwHow = DIPH_BYOFFSET;
slouken@1662
   183
        diprg.lMin = AXIS_MIN;
slouken@1662
   184
        diprg.lMax = AXIS_MAX;
slouken@1661
   185
slouken@1662
   186
        result =
slouken@1662
   187
            IDirectInputDevice2_SetProperty (joystick->hwdata->InputDevice,
slouken@1662
   188
                                             DIPROP_RANGE, &diprg.diph);
slouken@1662
   189
        if (result != DI_OK)
slouken@1662
   190
            return DIENUM_CONTINUE;     /* don't use this axis */
slouken@1661
   191
slouken@1662
   192
        /* Set dead zone to 0. */
slouken@1662
   193
        dilong.diph.dwSize = sizeof (dilong);
slouken@1662
   194
        dilong.diph.dwHeaderSize = sizeof (dilong.diph);
slouken@1662
   195
        dilong.diph.dwObj = dev->dwOfs;
slouken@1662
   196
        dilong.diph.dwHow = DIPH_BYOFFSET;
slouken@1662
   197
        dilong.dwData = 0;
slouken@1662
   198
        result =
slouken@1662
   199
            IDirectInputDevice2_SetProperty (joystick->hwdata->InputDevice,
slouken@1662
   200
                                             DIPROP_DEADZONE, &dilong.diph);
slouken@1662
   201
        if (result != DI_OK)
slouken@1662
   202
            return DIENUM_CONTINUE;     /* don't use this axis */
slouken@1661
   203
slouken@1662
   204
        joystick->naxes++;
slouken@1662
   205
    }
slouken@1662
   206
slouken@1662
   207
    joystick->hwdata->NumInputs++;
slouken@1662
   208
slouken@1662
   209
    if (joystick->hwdata->NumInputs == MAX_INPUTS)
slouken@1662
   210
        return DIENUM_STOP;     /* too many */
slouken@1662
   211
slouken@1662
   212
    return DIENUM_CONTINUE;
slouken@1661
   213
}
slouken@1661
   214
slouken@1661
   215
/* Function to scan the system for joysticks.
slouken@1661
   216
 * This function should set SDL_numjoysticks to the number of available
slouken@1661
   217
 * joysticks.  Joystick 0 should be the system default joystick.
slouken@1661
   218
 * It should return 0, or -1 on an unrecoverable fatal error.
slouken@1661
   219
 */
slouken@1662
   220
int
slouken@1662
   221
SDL_SYS_JoystickInit (void)
slouken@1661
   222
{
slouken@1662
   223
    HRESULT result;
slouken@1661
   224
slouken@1662
   225
    SYS_NumJoysticks = 0;
slouken@1661
   226
slouken@1662
   227
    /* Create the DirectInput object */
slouken@1662
   228
    if (DX5_Load () < 0) {
slouken@1662
   229
        SDL_SetError ("Couldn't load DirectInput");
slouken@1662
   230
        return (-1);
slouken@1662
   231
    }
slouken@1662
   232
    result = DInputCreate (SDL_Instance, DIRECTINPUT_VERSION, &dinput, NULL);
slouken@1662
   233
    if (result != DI_OK) {
slouken@1662
   234
        DX5_Unload ();
slouken@1662
   235
        SetDIerror ("DirectInputCreate", result);
slouken@1662
   236
        return (-1);
slouken@1662
   237
    }
slouken@1661
   238
slouken@1662
   239
    result = IDirectInput_EnumDevices (dinput,
slouken@1662
   240
                                       DIDEVTYPE_JOYSTICK,
slouken@1662
   241
                                       EnumJoysticksCallback,
slouken@1662
   242
                                       NULL, DIEDFL_ATTACHEDONLY);
slouken@1661
   243
slouken@1662
   244
    return SYS_NumJoysticks;
slouken@1661
   245
}
slouken@1661
   246
slouken@1661
   247
/* Function to get the device-dependent name of a joystick */
slouken@1662
   248
const char *
slouken@1662
   249
SDL_SYS_JoystickName (int index)
slouken@1661
   250
{
slouken@1662
   251
        /***-> test for invalid index ? */
slouken@1662
   252
    return (SYS_Joystick[index].tszProductName);
slouken@1661
   253
}
slouken@1661
   254
slouken@1661
   255
/* Function to open a joystick for use.
slouken@1661
   256
   The joystick to open is specified by the index field of the joystick.
slouken@1661
   257
   This should fill the nbuttons and naxes fields of the joystick structure.
slouken@1661
   258
   It returns 0, or -1 if there is an error.
slouken@1661
   259
 */
slouken@1662
   260
int
slouken@1662
   261
SDL_SYS_JoystickOpen (SDL_Joystick * joystick)
slouken@1661
   262
{
slouken@1662
   263
    HRESULT result;
slouken@1662
   264
    LPDIRECTINPUTDEVICE device;
slouken@1661
   265
slouken@1662
   266
    /* allocate memory for system specific hardware data */
slouken@1662
   267
    joystick->hwdata =
slouken@1662
   268
        (struct joystick_hwdata *) malloc (sizeof (*joystick->hwdata));
slouken@1662
   269
    if (joystick->hwdata == NULL) {
slouken@1662
   270
        SDL_OutOfMemory ();
slouken@1662
   271
        return (-1);
slouken@1662
   272
    }
slouken@1662
   273
    memset (joystick->hwdata, 0, sizeof (*joystick->hwdata));
slouken@1662
   274
    joystick->hwdata->buffered = 1;
slouken@1661
   275
slouken@1662
   276
    result =
slouken@1662
   277
        IDirectInput_CreateDevice (dinput,
slouken@1662
   278
                                   &SYS_Joystick[joystick->index].
slouken@1662
   279
                                   guidInstance, &device, NULL);
slouken@1662
   280
    if (result != DI_OK) {
slouken@1662
   281
        SetDIerror ("DirectInput::CreateDevice", result);
slouken@1662
   282
        return (-1);
slouken@1662
   283
    }
slouken@1661
   284
slouken@1662
   285
    result = IDirectInputDevice_QueryInterface (device,
slouken@1662
   286
                                                &IID_IDirectInputDevice2,
slouken@1662
   287
                                                (LPVOID *) & joystick->
slouken@1662
   288
                                                hwdata->InputDevice);
slouken@1662
   289
    IDirectInputDevice_Release (device);
slouken@1662
   290
    if (result != DI_OK) {
slouken@1662
   291
        SetDIerror ("DirectInputDevice::QueryInterface", result);
slouken@1662
   292
        return (-1);
slouken@1662
   293
    }
slouken@1661
   294
slouken@1662
   295
    result =
slouken@1662
   296
        IDirectInputDevice2_SetCooperativeLevel (joystick->hwdata->
slouken@1662
   297
                                                 InputDevice, SDL_Window,
slouken@1662
   298
                                                 DISCL_NONEXCLUSIVE |
slouken@1662
   299
                                                 DISCL_BACKGROUND);
slouken@1662
   300
    if (result != DI_OK) {
slouken@1662
   301
        SetDIerror ("DirectInputDevice::SetCooperativeLevel", result);
slouken@1662
   302
        return (-1);
slouken@1662
   303
    }
slouken@1661
   304
slouken@1662
   305
    result =
slouken@1662
   306
        IDirectInputDevice2_SetDataFormat (joystick->hwdata->InputDevice,
slouken@1662
   307
                                           &c_dfDIJoystick);
slouken@1662
   308
    if (result != DI_OK) {
slouken@1662
   309
        SetDIerror ("DirectInputDevice::SetDataFormat", result);
slouken@1662
   310
        return (-1);
slouken@1662
   311
    }
slouken@1661
   312
slouken@1662
   313
    IDirectInputDevice2_EnumObjects (joystick->hwdata->InputDevice,
slouken@1662
   314
                                     DIJoystick_EnumDevObjectsProc,
slouken@1662
   315
                                     joystick,
slouken@1662
   316
                                     DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
slouken@1661
   317
slouken@1662
   318
    {
slouken@1662
   319
        DIPROPDWORD dipdw;
slouken@1662
   320
        memset (&dipdw, 0, sizeof (dipdw));
slouken@1662
   321
        dipdw.diph.dwSize = sizeof (dipdw);
slouken@1662
   322
        dipdw.diph.dwHeaderSize = sizeof (dipdw.diph);
slouken@1662
   323
        dipdw.diph.dwObj = 0;
slouken@1662
   324
        dipdw.diph.dwHow = DIPH_DEVICE;
slouken@1662
   325
        dipdw.dwData = INPUT_QSIZE;
slouken@1662
   326
        result =
slouken@1662
   327
            IDirectInputDevice2_SetProperty (joystick->hwdata->InputDevice,
slouken@1662
   328
                                             DIPROP_BUFFERSIZE, &dipdw.diph);
slouken@1661
   329
slouken@1662
   330
        if (result == DI_POLLEDDEVICE) {
slouken@1662
   331
            /* This device doesn't support buffering, so we're forced
slouken@1662
   332
             * to use less reliable polling. */
slouken@1662
   333
            joystick->hwdata->buffered = 0;
slouken@1662
   334
        } else if (result != DI_OK) {
slouken@1662
   335
            SetDIerror ("DirectInputDevice::SetProperty", result);
slouken@1662
   336
            return (-1);
slouken@1662
   337
        }
slouken@1662
   338
    }
slouken@1662
   339
slouken@1662
   340
    return (0);
slouken@1661
   341
}
slouken@1661
   342
slouken@1662
   343
static Uint8
slouken@1662
   344
TranslatePOV (DWORD value)
slouken@1661
   345
{
slouken@1662
   346
    const int HAT_VALS[] = {
slouken@1662
   347
        SDL_HAT_UP,
slouken@1662
   348
        SDL_HAT_UP | SDL_HAT_RIGHT,
slouken@1662
   349
        SDL_HAT_RIGHT,
slouken@1662
   350
        SDL_HAT_DOWN | SDL_HAT_RIGHT,
slouken@1662
   351
        SDL_HAT_DOWN,
slouken@1662
   352
        SDL_HAT_DOWN | SDL_HAT_LEFT,
slouken@1662
   353
        SDL_HAT_LEFT,
slouken@1662
   354
        SDL_HAT_UP | SDL_HAT_LEFT
slouken@1662
   355
    };
slouken@1661
   356
slouken@1662
   357
    if (LOWORD (value) == 0xFFFF)
slouken@1662
   358
        return SDL_HAT_CENTERED;
slouken@1661
   359
slouken@1662
   360
    /* Round the value up: */
slouken@1662
   361
    value += 4500 / 2;
slouken@1662
   362
    value %= 36000;
slouken@1662
   363
    value /= 4500;
slouken@1661
   364
slouken@1662
   365
    if (value >= 8)
slouken@1662
   366
        return SDL_HAT_CENTERED;        /* shouldn't happen */
slouken@1662
   367
slouken@1662
   368
    return HAT_VALS[value];
slouken@1661
   369
}
slouken@1661
   370
slouken@1661
   371
/* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to
slouken@1661
   372
 * do it. */
slouken@1662
   373
static int
slouken@1662
   374
SDL_PrivateJoystickAxis_Int (SDL_Joystick * joystick, Uint8 axis,
slouken@1662
   375
                             Sint16 value)
slouken@1661
   376
{
slouken@1662
   377
    if (joystick->axes[axis] != value)
slouken@1662
   378
        return SDL_PrivateJoystickAxis (joystick, axis, value);
slouken@1662
   379
    return 0;
slouken@1661
   380
}
slouken@1661
   381
slouken@1662
   382
static int
slouken@1662
   383
SDL_PrivateJoystickHat_Int (SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@1661
   384
{
slouken@1662
   385
    if (joystick->hats[hat] != value)
slouken@1662
   386
        return SDL_PrivateJoystickHat (joystick, hat, value);
slouken@1662
   387
    return 0;
slouken@1661
   388
}
slouken@1661
   389
slouken@1662
   390
static int
slouken@1662
   391
SDL_PrivateJoystickButton_Int (SDL_Joystick * joystick, Uint8 button,
slouken@1662
   392
                               Uint8 state)
slouken@1661
   393
{
slouken@1662
   394
    if (joystick->buttons[button] != state)
slouken@1662
   395
        return SDL_PrivateJoystickButton (joystick, button, state);
slouken@1662
   396
    return 0;
slouken@1661
   397
}
slouken@1661
   398
slouken@1661
   399
/* Function to update the state of a joystick - called as a device poll.
slouken@1661
   400
 * This function shouldn't update the joystick structure directly,
slouken@1661
   401
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@1661
   402
 * and update joystick device state.
slouken@1661
   403
 */
slouken@1662
   404
void
slouken@1662
   405
SDL_SYS_JoystickUpdate_Polled (SDL_Joystick * joystick)
slouken@1661
   406
{
slouken@1662
   407
    DIJOYSTATE state;
slouken@1662
   408
    HRESULT result;
slouken@1662
   409
    int i;
slouken@1661
   410
slouken@1662
   411
    result =
slouken@1662
   412
        IDirectInputDevice2_GetDeviceState (joystick->hwdata->InputDevice,
slouken@1662
   413
                                            sizeof (state), &state);
slouken@1662
   414
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1662
   415
        IDirectInputDevice2_Acquire (joystick->hwdata->InputDevice);
slouken@1662
   416
        result =
slouken@1662
   417
            IDirectInputDevice2_GetDeviceState (joystick->hwdata->
slouken@1662
   418
                                                InputDevice, sizeof (state),
slouken@1662
   419
                                                &state);
slouken@1662
   420
    }
slouken@1661
   421
slouken@1662
   422
    /* Set each known axis, button and POV. */
slouken@1662
   423
    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
slouken@1662
   424
        const input_t *in = &joystick->hwdata->Inputs[i];
slouken@1661
   425
slouken@1662
   426
        switch (in->type) {
slouken@1662
   427
        case AXIS:
slouken@1662
   428
            switch (in->ofs) {
slouken@1662
   429
            case DIJOFS_X:
slouken@1662
   430
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   431
                                             (Sint16) state.lX);
slouken@1662
   432
                break;
slouken@1662
   433
            case DIJOFS_Y:
slouken@1662
   434
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   435
                                             (Sint16) state.lY);
slouken@1662
   436
                break;
slouken@1662
   437
            case DIJOFS_Z:
slouken@1662
   438
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   439
                                             (Sint16) state.lZ);
slouken@1662
   440
                break;
slouken@1662
   441
            case DIJOFS_RX:
slouken@1662
   442
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   443
                                             (Sint16) state.lRx);
slouken@1662
   444
                break;
slouken@1662
   445
            case DIJOFS_RY:
slouken@1662
   446
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   447
                                             (Sint16) state.lRy);
slouken@1662
   448
                break;
slouken@1662
   449
            case DIJOFS_RZ:
slouken@1662
   450
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   451
                                             (Sint16) state.lRz);
slouken@1662
   452
                break;
slouken@1662
   453
            case DIJOFS_SLIDER (0):
slouken@1662
   454
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   455
                                             (Sint16) state.rglSlider[0]);
slouken@1662
   456
                break;
slouken@1662
   457
            case DIJOFS_SLIDER (1):
slouken@1662
   458
                SDL_PrivateJoystickAxis_Int (joystick, in->num,
slouken@1662
   459
                                             (Sint16) state.rglSlider[0]);
slouken@1662
   460
                break;
slouken@1662
   461
            }
slouken@1661
   462
slouken@1662
   463
            break;
slouken@1661
   464
slouken@1662
   465
        case BUTTON:
slouken@1662
   466
            SDL_PrivateJoystickButton_Int (joystick, in->num,
slouken@1662
   467
                                           (Uint8) (state.
slouken@1662
   468
                                                    rgbButtons[in->ofs -
slouken@1662
   469
                                                               DIJOFS_BUTTON0]
slouken@1662
   470
                                                    ? SDL_PRESSED :
slouken@1662
   471
                                                    SDL_RELEASED));
slouken@1662
   472
            break;
slouken@1662
   473
        case HAT:
slouken@1662
   474
            {
slouken@1662
   475
                Uint8 pos =
slouken@1662
   476
                    TranslatePOV (state.rgdwPOV[in->ofs - DIJOFS_POV (0)]);
slouken@1662
   477
                SDL_PrivateJoystickHat_Int (joystick, in->num, pos);
slouken@1662
   478
                break;
slouken@1662
   479
            }
slouken@1662
   480
        }
slouken@1662
   481
    }
slouken@1661
   482
}
slouken@1661
   483
slouken@1662
   484
void
slouken@1662
   485
SDL_SYS_JoystickUpdate_Buffered (SDL_Joystick * joystick)
slouken@1661
   486
{
slouken@1662
   487
    int i;
slouken@1662
   488
    HRESULT result;
slouken@1662
   489
    DWORD numevents;
slouken@1662
   490
    DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
slouken@1661
   491
slouken@1662
   492
    numevents = INPUT_QSIZE;
slouken@1662
   493
    result =
slouken@1662
   494
        IDirectInputDevice2_GetDeviceData (joystick->hwdata->InputDevice,
slouken@1662
   495
                                           sizeof (DIDEVICEOBJECTDATA),
slouken@1662
   496
                                           evtbuf, &numevents, 0);
slouken@1662
   497
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1662
   498
        IDirectInputDevice2_Acquire (joystick->hwdata->InputDevice);
slouken@1662
   499
        result =
slouken@1662
   500
            IDirectInputDevice2_GetDeviceData (joystick->hwdata->
slouken@1662
   501
                                               InputDevice,
slouken@1662
   502
                                               sizeof (DIDEVICEOBJECTDATA),
slouken@1662
   503
                                               evtbuf, &numevents, 0);
slouken@1662
   504
    }
slouken@1661
   505
slouken@1662
   506
    /* Handle the events */
slouken@1662
   507
    if (result != DI_OK)
slouken@1662
   508
        return;
slouken@1661
   509
slouken@1662
   510
    for (i = 0; i < (int) numevents; ++i) {
slouken@1662
   511
        int j;
slouken@1661
   512
slouken@1662
   513
        for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
slouken@1662
   514
            const input_t *in = &joystick->hwdata->Inputs[j];
slouken@1661
   515
slouken@1662
   516
            if (evtbuf[i].dwOfs != in->ofs)
slouken@1662
   517
                continue;
slouken@1662
   518
slouken@1662
   519
            switch (in->type) {
slouken@1662
   520
            case AXIS:
slouken@1662
   521
                SDL_PrivateJoystickAxis (joystick, in->num,
slouken@1662
   522
                                         (Sint16) evtbuf[i].dwData);
slouken@1662
   523
                break;
slouken@1662
   524
            case BUTTON:
slouken@1662
   525
                SDL_PrivateJoystickButton (joystick, in->num,
slouken@1662
   526
                                           (Uint8) (evtbuf[i].
slouken@1662
   527
                                                    dwData ? SDL_PRESSED
slouken@1662
   528
                                                    : SDL_RELEASED));
slouken@1662
   529
                break;
slouken@1662
   530
            case HAT:
slouken@1662
   531
                {
slouken@1662
   532
                    Uint8 pos = TranslatePOV (evtbuf[i].dwData);
slouken@1662
   533
                    SDL_PrivateJoystickHat (joystick, in->num, pos);
slouken@1662
   534
                }
slouken@1662
   535
            }
slouken@1662
   536
        }
slouken@1662
   537
    }
slouken@1661
   538
}
slouken@1661
   539
slouken@1662
   540
void
slouken@1662
   541
SDL_SYS_JoystickUpdate (SDL_Joystick * joystick)
slouken@1661
   542
{
slouken@1662
   543
    HRESULT result;
slouken@1661
   544
slouken@1662
   545
    result = IDirectInputDevice2_Poll (joystick->hwdata->InputDevice);
slouken@1662
   546
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1662
   547
        IDirectInputDevice2_Acquire (joystick->hwdata->InputDevice);
slouken@1662
   548
        IDirectInputDevice2_Poll (joystick->hwdata->InputDevice);
slouken@1662
   549
    }
slouken@1661
   550
slouken@1662
   551
    if (joystick->hwdata->buffered)
slouken@1662
   552
        SDL_SYS_JoystickUpdate_Buffered (joystick);
slouken@1662
   553
    else
slouken@1662
   554
        SDL_SYS_JoystickUpdate_Polled (joystick);
slouken@1661
   555
}
slouken@1661
   556
slouken@1661
   557
/* Function to close a joystick after use */
slouken@1662
   558
void
slouken@1662
   559
SDL_SYS_JoystickClose (SDL_Joystick * joystick)
slouken@1661
   560
{
slouken@1662
   561
    IDirectInputDevice2_Unacquire (joystick->hwdata->InputDevice);
slouken@1662
   562
    IDirectInputDevice2_Release (joystick->hwdata->InputDevice);
slouken@1661
   563
slouken@1662
   564
    if (joystick->hwdata != NULL) {
slouken@1662
   565
        /* free system specific hardware data */
slouken@1662
   566
        free (joystick->hwdata);
slouken@1662
   567
    }
slouken@1661
   568
}
slouken@1661
   569
slouken@1661
   570
/* Function to perform any system-specific joystick related cleanup */
slouken@1662
   571
void
slouken@1662
   572
SDL_SYS_JoystickQuit (void)
slouken@1661
   573
{
slouken@1662
   574
    IDirectInput_Release (dinput);
slouken@1662
   575
    dinput = NULL;
slouken@1662
   576
    DX5_Unload ();
slouken@1661
   577
}
slouken@1661
   578
slouken@1661
   579
#endif /* SDL_JOYSTICK_DINPUT */
slouken@1662
   580
/* vi: set ts=4 sw=4 expandtab: */