src/joystick/win32/SDL_dxjoystick.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 29 May 2006 04:04:35 +0000
branchSDL-1.3
changeset 1668 4da1ee79c9af
parent 1662 782fd950bd46
permissions -rw-r--r--
more tweaking indent options
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@1668
    51
extern int DX5_Load();
slouken@1668
    52
extern void DX5_Unload();
slouken@1668
    53
extern HRESULT(WINAPI * DInputCreate) (HINSTANCE hinst, DWORD dwVersion,
slouken@1668
    54
                                       LPDIRECTINPUT * ppDI,
slouken@1668
    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@1668
    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@1668
   127
        sprintf(errbuf, "%s: Unknown DirectInput error: 0x%x",
slouken@1668
   128
                function, code);
slouken@1662
   129
        break;
slouken@1662
   130
    }
slouken@1662
   131
    if (!errbuf[0]) {
slouken@1668
   132
        sprintf(errbuf, "%s: %s", function, error);
slouken@1662
   133
    }
slouken@1668
   134
    SDL_SetError("%s", errbuf);
slouken@1662
   135
    return;
slouken@1661
   136
}
slouken@1661
   137
slouken@1661
   138
slouken@1662
   139
BOOL CALLBACK
slouken@1668
   140
EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
slouken@1661
   141
{
slouken@1668
   142
    memcpy(&SYS_Joystick[SYS_NumJoysticks], pdidInstance,
slouken@1668
   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@1668
   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@1668
   179
        diprg.diph.dwSize = sizeof(diprg);
slouken@1668
   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@1668
   187
            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
slouken@1668
   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@1668
   193
        dilong.diph.dwSize = sizeof(dilong);
slouken@1668
   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@1668
   199
            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
slouken@1668
   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@1668
   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@1668
   228
    if (DX5_Load() < 0) {
slouken@1668
   229
        SDL_SetError("Couldn't load DirectInput");
slouken@1662
   230
        return (-1);
slouken@1662
   231
    }
slouken@1668
   232
    result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, &dinput, NULL);
slouken@1662
   233
    if (result != DI_OK) {
slouken@1668
   234
        DX5_Unload();
slouken@1668
   235
        SetDIerror("DirectInputCreate", result);
slouken@1662
   236
        return (-1);
slouken@1662
   237
    }
slouken@1661
   238
slouken@1668
   239
    result = IDirectInput_EnumDevices(dinput,
slouken@1668
   240
                                      DIDEVTYPE_JOYSTICK,
slouken@1668
   241
                                      EnumJoysticksCallback,
slouken@1668
   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@1668
   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@1668
   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@1668
   268
        (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata));
slouken@1662
   269
    if (joystick->hwdata == NULL) {
slouken@1668
   270
        SDL_OutOfMemory();
slouken@1662
   271
        return (-1);
slouken@1662
   272
    }
slouken@1668
   273
    memset(joystick->hwdata, 0, sizeof(*joystick->hwdata));
slouken@1662
   274
    joystick->hwdata->buffered = 1;
slouken@1661
   275
slouken@1662
   276
    result =
slouken@1668
   277
        IDirectInput_CreateDevice(dinput,
slouken@1668
   278
                                  &SYS_Joystick[joystick->index].
slouken@1668
   279
                                  guidInstance, &device, NULL);
slouken@1662
   280
    if (result != DI_OK) {
slouken@1668
   281
        SetDIerror("DirectInput::CreateDevice", result);
slouken@1662
   282
        return (-1);
slouken@1662
   283
    }
slouken@1661
   284
slouken@1668
   285
    result = IDirectInputDevice_QueryInterface(device,
slouken@1668
   286
                                               &IID_IDirectInputDevice2,
slouken@1668
   287
                                               (LPVOID *) & joystick->
slouken@1668
   288
                                               hwdata->InputDevice);
slouken@1668
   289
    IDirectInputDevice_Release(device);
slouken@1662
   290
    if (result != DI_OK) {
slouken@1668
   291
        SetDIerror("DirectInputDevice::QueryInterface", result);
slouken@1662
   292
        return (-1);
slouken@1662
   293
    }
slouken@1661
   294
slouken@1662
   295
    result =
slouken@1668
   296
        IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->
slouken@1668
   297
                                                InputDevice, SDL_Window,
slouken@1668
   298
                                                DISCL_NONEXCLUSIVE |
slouken@1668
   299
                                                DISCL_BACKGROUND);
slouken@1662
   300
    if (result != DI_OK) {
slouken@1668
   301
        SetDIerror("DirectInputDevice::SetCooperativeLevel", result);
slouken@1662
   302
        return (-1);
slouken@1662
   303
    }
slouken@1661
   304
slouken@1662
   305
    result =
slouken@1668
   306
        IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice,
slouken@1668
   307
                                          &c_dfDIJoystick);
slouken@1662
   308
    if (result != DI_OK) {
slouken@1668
   309
        SetDIerror("DirectInputDevice::SetDataFormat", result);
slouken@1662
   310
        return (-1);
slouken@1662
   311
    }
slouken@1661
   312
slouken@1668
   313
    IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice,
slouken@1668
   314
                                    DIJoystick_EnumDevObjectsProc,
slouken@1668
   315
                                    joystick,
slouken@1668
   316
                                    DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV);
slouken@1661
   317
slouken@1662
   318
    {
slouken@1662
   319
        DIPROPDWORD dipdw;
slouken@1668
   320
        memset(&dipdw, 0, sizeof(dipdw));
slouken@1668
   321
        dipdw.diph.dwSize = sizeof(dipdw);
slouken@1668
   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@1668
   327
            IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice,
slouken@1668
   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@1668
   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@1668
   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@1668
   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@1668
   374
SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
slouken@1661
   375
{
slouken@1662
   376
    if (joystick->axes[axis] != value)
slouken@1668
   377
        return SDL_PrivateJoystickAxis(joystick, axis, value);
slouken@1662
   378
    return 0;
slouken@1661
   379
}
slouken@1661
   380
slouken@1662
   381
static int
slouken@1668
   382
SDL_PrivateJoystickHat_Int(SDL_Joystick * joystick, Uint8 hat, Uint8 value)
slouken@1661
   383
{
slouken@1662
   384
    if (joystick->hats[hat] != value)
slouken@1668
   385
        return SDL_PrivateJoystickHat(joystick, hat, value);
slouken@1662
   386
    return 0;
slouken@1661
   387
}
slouken@1661
   388
slouken@1662
   389
static int
slouken@1668
   390
SDL_PrivateJoystickButton_Int(SDL_Joystick * joystick, Uint8 button,
slouken@1668
   391
                              Uint8 state)
slouken@1661
   392
{
slouken@1662
   393
    if (joystick->buttons[button] != state)
slouken@1668
   394
        return SDL_PrivateJoystickButton(joystick, button, state);
slouken@1662
   395
    return 0;
slouken@1661
   396
}
slouken@1661
   397
slouken@1661
   398
/* Function to update the state of a joystick - called as a device poll.
slouken@1661
   399
 * This function shouldn't update the joystick structure directly,
slouken@1661
   400
 * but instead should call SDL_PrivateJoystick*() to deliver events
slouken@1661
   401
 * and update joystick device state.
slouken@1661
   402
 */
slouken@1662
   403
void
slouken@1668
   404
SDL_SYS_JoystickUpdate_Polled(SDL_Joystick * joystick)
slouken@1661
   405
{
slouken@1662
   406
    DIJOYSTATE state;
slouken@1662
   407
    HRESULT result;
slouken@1662
   408
    int i;
slouken@1661
   409
slouken@1662
   410
    result =
slouken@1668
   411
        IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice,
slouken@1668
   412
                                           sizeof(state), &state);
slouken@1662
   413
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1668
   414
        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
slouken@1662
   415
        result =
slouken@1668
   416
            IDirectInputDevice2_GetDeviceState(joystick->hwdata->
slouken@1668
   417
                                               InputDevice, sizeof(state),
slouken@1668
   418
                                               &state);
slouken@1662
   419
    }
slouken@1661
   420
slouken@1662
   421
    /* Set each known axis, button and POV. */
slouken@1662
   422
    for (i = 0; i < joystick->hwdata->NumInputs; ++i) {
slouken@1662
   423
        const input_t *in = &joystick->hwdata->Inputs[i];
slouken@1661
   424
slouken@1662
   425
        switch (in->type) {
slouken@1662
   426
        case AXIS:
slouken@1662
   427
            switch (in->ofs) {
slouken@1662
   428
            case DIJOFS_X:
slouken@1668
   429
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   430
                                            (Sint16) state.lX);
slouken@1662
   431
                break;
slouken@1662
   432
            case DIJOFS_Y:
slouken@1668
   433
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   434
                                            (Sint16) state.lY);
slouken@1662
   435
                break;
slouken@1662
   436
            case DIJOFS_Z:
slouken@1668
   437
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   438
                                            (Sint16) state.lZ);
slouken@1662
   439
                break;
slouken@1662
   440
            case DIJOFS_RX:
slouken@1668
   441
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   442
                                            (Sint16) state.lRx);
slouken@1662
   443
                break;
slouken@1662
   444
            case DIJOFS_RY:
slouken@1668
   445
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   446
                                            (Sint16) state.lRy);
slouken@1662
   447
                break;
slouken@1662
   448
            case DIJOFS_RZ:
slouken@1668
   449
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   450
                                            (Sint16) state.lRz);
slouken@1662
   451
                break;
slouken@1668
   452
            case DIJOFS_SLIDER(0):
slouken@1668
   453
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   454
                                            (Sint16) state.rglSlider[0]);
slouken@1662
   455
                break;
slouken@1668
   456
            case DIJOFS_SLIDER(1):
slouken@1668
   457
                SDL_PrivateJoystickAxis_Int(joystick, in->num,
slouken@1668
   458
                                            (Sint16) state.rglSlider[0]);
slouken@1662
   459
                break;
slouken@1662
   460
            }
slouken@1661
   461
slouken@1662
   462
            break;
slouken@1661
   463
slouken@1662
   464
        case BUTTON:
slouken@1668
   465
            SDL_PrivateJoystickButton_Int(joystick, in->num,
slouken@1668
   466
                                          (Uint8) (state.
slouken@1668
   467
                                                   rgbButtons[in->ofs -
slouken@1668
   468
                                                              DIJOFS_BUTTON0]
slouken@1668
   469
                                                   ? SDL_PRESSED :
slouken@1668
   470
                                                   SDL_RELEASED));
slouken@1662
   471
            break;
slouken@1662
   472
        case HAT:
slouken@1662
   473
            {
slouken@1662
   474
                Uint8 pos =
slouken@1668
   475
                    TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]);
slouken@1668
   476
                SDL_PrivateJoystickHat_Int(joystick, in->num, pos);
slouken@1662
   477
                break;
slouken@1662
   478
            }
slouken@1662
   479
        }
slouken@1662
   480
    }
slouken@1661
   481
}
slouken@1661
   482
slouken@1662
   483
void
slouken@1668
   484
SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick * joystick)
slouken@1661
   485
{
slouken@1662
   486
    int i;
slouken@1662
   487
    HRESULT result;
slouken@1662
   488
    DWORD numevents;
slouken@1662
   489
    DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE];
slouken@1661
   490
slouken@1662
   491
    numevents = INPUT_QSIZE;
slouken@1662
   492
    result =
slouken@1668
   493
        IDirectInputDevice2_GetDeviceData(joystick->hwdata->InputDevice,
slouken@1668
   494
                                          sizeof(DIDEVICEOBJECTDATA),
slouken@1668
   495
                                          evtbuf, &numevents, 0);
slouken@1662
   496
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1668
   497
        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
slouken@1662
   498
        result =
slouken@1668
   499
            IDirectInputDevice2_GetDeviceData(joystick->hwdata->
slouken@1668
   500
                                              InputDevice,
slouken@1668
   501
                                              sizeof(DIDEVICEOBJECTDATA),
slouken@1668
   502
                                              evtbuf, &numevents, 0);
slouken@1662
   503
    }
slouken@1661
   504
slouken@1662
   505
    /* Handle the events */
slouken@1662
   506
    if (result != DI_OK)
slouken@1662
   507
        return;
slouken@1661
   508
slouken@1662
   509
    for (i = 0; i < (int) numevents; ++i) {
slouken@1662
   510
        int j;
slouken@1661
   511
slouken@1662
   512
        for (j = 0; j < joystick->hwdata->NumInputs; ++j) {
slouken@1662
   513
            const input_t *in = &joystick->hwdata->Inputs[j];
slouken@1661
   514
slouken@1662
   515
            if (evtbuf[i].dwOfs != in->ofs)
slouken@1662
   516
                continue;
slouken@1662
   517
slouken@1662
   518
            switch (in->type) {
slouken@1662
   519
            case AXIS:
slouken@1668
   520
                SDL_PrivateJoystickAxis(joystick, in->num,
slouken@1668
   521
                                        (Sint16) evtbuf[i].dwData);
slouken@1662
   522
                break;
slouken@1662
   523
            case BUTTON:
slouken@1668
   524
                SDL_PrivateJoystickButton(joystick, in->num,
slouken@1668
   525
                                          (Uint8) (evtbuf[i].
slouken@1668
   526
                                                   dwData ? SDL_PRESSED
slouken@1668
   527
                                                   : SDL_RELEASED));
slouken@1662
   528
                break;
slouken@1662
   529
            case HAT:
slouken@1662
   530
                {
slouken@1668
   531
                    Uint8 pos = TranslatePOV(evtbuf[i].dwData);
slouken@1668
   532
                    SDL_PrivateJoystickHat(joystick, in->num, pos);
slouken@1662
   533
                }
slouken@1662
   534
            }
slouken@1662
   535
        }
slouken@1662
   536
    }
slouken@1661
   537
}
slouken@1661
   538
slouken@1662
   539
void
slouken@1668
   540
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
slouken@1661
   541
{
slouken@1662
   542
    HRESULT result;
slouken@1661
   543
slouken@1668
   544
    result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
slouken@1662
   545
    if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) {
slouken@1668
   546
        IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice);
slouken@1668
   547
        IDirectInputDevice2_Poll(joystick->hwdata->InputDevice);
slouken@1662
   548
    }
slouken@1661
   549
slouken@1662
   550
    if (joystick->hwdata->buffered)
slouken@1668
   551
        SDL_SYS_JoystickUpdate_Buffered(joystick);
slouken@1662
   552
    else
slouken@1668
   553
        SDL_SYS_JoystickUpdate_Polled(joystick);
slouken@1661
   554
}
slouken@1661
   555
slouken@1661
   556
/* Function to close a joystick after use */
slouken@1662
   557
void
slouken@1668
   558
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
slouken@1661
   559
{
slouken@1668
   560
    IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice);
slouken@1668
   561
    IDirectInputDevice2_Release(joystick->hwdata->InputDevice);
slouken@1661
   562
slouken@1662
   563
    if (joystick->hwdata != NULL) {
slouken@1662
   564
        /* free system specific hardware data */
slouken@1668
   565
        free(joystick->hwdata);
slouken@1662
   566
    }
slouken@1661
   567
}
slouken@1661
   568
slouken@1661
   569
/* Function to perform any system-specific joystick related cleanup */
slouken@1662
   570
void
slouken@1668
   571
SDL_SYS_JoystickQuit(void)
slouken@1661
   572
{
slouken@1668
   573
    IDirectInput_Release(dinput);
slouken@1662
   574
    dinput = NULL;
slouken@1668
   575
    DX5_Unload();
slouken@1661
   576
}
slouken@1661
   577
slouken@1661
   578
#endif /* SDL_JOYSTICK_DINPUT */
slouken@1662
   579
/* vi: set ts=4 sw=4 expandtab: */