src/haptic/windows/SDL_dinputhaptic.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 20 May 2020 16:58:33 -0400
changeset 13838 02e41b30186f
parent 13789 a359f4f93439
child 13914 348d0896fc9e
permissions -rw-r--r--
windows: Fix calls to CoCreateInstance() so last parameter is a LPVOID *.
slouken@8972
     1
/*
slouken@8972
     2
  Simple DirectMedia Layer
slouken@13422
     3
  Copyright (C) 1997-2020 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@9661
    23
#include "SDL_error.h"
icculus@9661
    24
#include "SDL_haptic.h"
icculus@9662
    25
#include "../SDL_syshaptic.h"
icculus@9661
    26
icculus@9658
    27
#if SDL_HAPTIC_DINPUT
icculus@9658
    28
icculus@9147
    29
#include "SDL_stdinc.h"
slouken@8972
    30
#include "SDL_timer.h"
slouken@8972
    31
#include "SDL_windowshaptic_c.h"
slouken@8972
    32
#include "SDL_dinputhaptic_c.h"
slouken@8972
    33
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
slouken@8972
    34
slouken@8972
    35
/*
slouken@8972
    36
 * External stuff.
slouken@8972
    37
 */
slouken@8972
    38
extern HWND SDL_HelperWindow;
slouken@8972
    39
slouken@8972
    40
slouken@8972
    41
/*
slouken@8972
    42
 * Internal stuff.
slouken@8972
    43
 */
slouken@8972
    44
static SDL_bool coinitialized = SDL_FALSE;
slouken@8972
    45
static LPDIRECTINPUT8 dinput = NULL;
slouken@8972
    46
slouken@8972
    47
slouken@8972
    48
/*
slouken@8972
    49
 * Like SDL_SetError but for DX error codes.
slouken@8972
    50
 */
slouken@8972
    51
static int
slouken@8972
    52
DI_SetError(const char *str, HRESULT err)
slouken@8972
    53
{
slouken@8972
    54
    /*
slouken@8972
    55
       SDL_SetError("Haptic: %s - %s: %s", str,
slouken@8972
    56
       DXGetErrorString8A(err), DXGetErrorDescription8A(err));
slouken@8972
    57
     */
slouken@8972
    58
    return SDL_SetError("Haptic error %s", str);
slouken@8972
    59
}
slouken@8972
    60
slouken@8972
    61
/*
slouken@8972
    62
 * Callback to find the haptic devices.
slouken@8972
    63
 */
slouken@8972
    64
static BOOL CALLBACK
slouken@8972
    65
EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
slouken@8972
    66
{
slouken@8972
    67
    (void) pContext;
slouken@8972
    68
    SDL_DINPUT_MaybeAddDevice(pdidInstance);
slouken@8972
    69
    return DIENUM_CONTINUE;  /* continue enumerating */
slouken@8972
    70
}
slouken@8972
    71
slouken@8972
    72
int
slouken@8972
    73
SDL_DINPUT_HapticInit(void)
slouken@8972
    74
{
slouken@8972
    75
    HRESULT ret;
slouken@8972
    76
    HINSTANCE instance;
slouken@8972
    77
slouken@8972
    78
    if (dinput != NULL) {       /* Already open. */
slouken@8972
    79
        return SDL_SetError("Haptic: SubSystem already open.");
slouken@8972
    80
    }
slouken@8972
    81
slouken@8972
    82
    ret = WIN_CoInitialize();
slouken@8972
    83
    if (FAILED(ret)) {
slouken@8972
    84
        return DI_SetError("Coinitialize", ret);
slouken@8972
    85
    }
slouken@8972
    86
slouken@8972
    87
    coinitialized = SDL_TRUE;
slouken@8972
    88
slouken@8972
    89
    ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
icculus@13838
    90
        &IID_IDirectInput8, (LPVOID *) &dinput);
slouken@8972
    91
    if (FAILED(ret)) {
slouken@8972
    92
        SDL_SYS_HapticQuit();
slouken@8972
    93
        return DI_SetError("CoCreateInstance", ret);
slouken@8972
    94
    }
slouken@8972
    95
slouken@8972
    96
    /* Because we used CoCreateInstance, we need to Initialize it, first. */
slouken@8972
    97
    instance = GetModuleHandle(NULL);
slouken@8972
    98
    if (instance == NULL) {
slouken@8972
    99
        SDL_SYS_HapticQuit();
slouken@8976
   100
        return SDL_SetError("GetModuleHandle() failed with error code %lu.",
slouken@8972
   101
            GetLastError());
slouken@8972
   102
    }
slouken@8972
   103
    ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
slouken@8972
   104
    if (FAILED(ret)) {
slouken@8972
   105
        SDL_SYS_HapticQuit();
slouken@8972
   106
        return DI_SetError("Initializing DirectInput device", ret);
slouken@8972
   107
    }
slouken@8972
   108
slouken@8972
   109
    /* Look for haptic devices. */
slouken@8972
   110
    ret = IDirectInput8_EnumDevices(dinput,
slouken@8972
   111
        0,
slouken@8972
   112
        EnumHapticsCallback,
slouken@8972
   113
        NULL,
slouken@8972
   114
        DIEDFL_FORCEFEEDBACK |
slouken@8972
   115
        DIEDFL_ATTACHEDONLY);
slouken@8972
   116
    if (FAILED(ret)) {
slouken@8972
   117
        SDL_SYS_HapticQuit();
slouken@8972
   118
        return DI_SetError("Enumerating DirectInput devices", ret);
slouken@8972
   119
    }
slouken@8972
   120
    return 0;
slouken@8972
   121
}
slouken@8972
   122
slouken@8972
   123
int
slouken@8972
   124
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
   125
{
slouken@8972
   126
    HRESULT ret;
slouken@8972
   127
    LPDIRECTINPUTDEVICE8 device;
slouken@8972
   128
    const DWORD needflags = DIDC_ATTACHED | DIDC_FORCEFEEDBACK;
slouken@8972
   129
    DIDEVCAPS capabilities;
slouken@8972
   130
    SDL_hapticlist_item *item = NULL;
slouken@8972
   131
slouken@8972
   132
    if (dinput == NULL) {
slouken@8972
   133
        return -1;  /* not initialized. We'll pick these up on enumeration if we init later. */
slouken@8972
   134
    }
slouken@8972
   135
slouken@8972
   136
    /* Make sure we don't already have it */
slouken@8972
   137
    for (item = SDL_hapticlist; item; item = item->next) {
slouken@8972
   138
        if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
slouken@8972
   139
            return -1;  /* Already added */
slouken@8972
   140
        }
slouken@8972
   141
    }
slouken@8972
   142
slouken@8972
   143
    /* Open the device */
slouken@8972
   144
    ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance, &device, NULL);
slouken@8972
   145
    if (FAILED(ret)) {
slouken@8972
   146
        /* DI_SetError("Creating DirectInput device",ret); */
slouken@8972
   147
        return -1;
slouken@8972
   148
    }
slouken@8972
   149
slouken@8972
   150
    /* Get capabilities. */
slouken@8972
   151
    SDL_zero(capabilities);
slouken@8972
   152
    capabilities.dwSize = sizeof(DIDEVCAPS);
slouken@8972
   153
    ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
slouken@8972
   154
    IDirectInputDevice8_Release(device);
slouken@8972
   155
    if (FAILED(ret)) {
slouken@8972
   156
        /* DI_SetError("Getting device capabilities",ret); */
slouken@8972
   157
        return -1;
slouken@8972
   158
    }
slouken@8972
   159
slouken@8972
   160
    if ((capabilities.dwFlags & needflags) != needflags) {
slouken@8972
   161
        return -1;  /* not a device we can use. */
slouken@8972
   162
    }
slouken@8972
   163
slouken@8972
   164
    item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
slouken@8972
   165
    if (item == NULL) {
slouken@8972
   166
        return SDL_OutOfMemory();
slouken@8972
   167
    }
slouken@8972
   168
slouken@8972
   169
    item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
slouken@8972
   170
    if (!item->name) {
slouken@8972
   171
        SDL_free(item);
slouken@8972
   172
        return -1;
slouken@8972
   173
    }
slouken@8972
   174
slouken@8972
   175
    /* Copy the instance over, useful for creating devices. */
slouken@8972
   176
    SDL_memcpy(&item->instance, pdidInstance, sizeof(DIDEVICEINSTANCE));
slouken@8972
   177
    SDL_memcpy(&item->capabilities, &capabilities, sizeof(capabilities));
slouken@8972
   178
slouken@8972
   179
    return SDL_SYS_AddHapticDevice(item);
slouken@8972
   180
}
slouken@8972
   181
slouken@8972
   182
int
slouken@8972
   183
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
   184
{
slouken@8972
   185
    SDL_hapticlist_item *item;
slouken@8972
   186
    SDL_hapticlist_item *prev = NULL;
slouken@8972
   187
slouken@8972
   188
    if (dinput == NULL) {
slouken@8972
   189
        return -1;  /* not initialized, ignore this. */
slouken@8972
   190
    }
slouken@8972
   191
slouken@8972
   192
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
slouken@8972
   193
        if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
slouken@8972
   194
            /* found it, remove it. */
slouken@8972
   195
            return SDL_SYS_RemoveHapticDevice(prev, item);
slouken@8972
   196
        }
slouken@8972
   197
        prev = item;
slouken@8972
   198
    }
slouken@8972
   199
    return -1;
slouken@8972
   200
}
slouken@8972
   201
slouken@8972
   202
/*
slouken@8972
   203
 * Callback to get supported axes.
slouken@8972
   204
 */
slouken@8972
   205
static BOOL CALLBACK
slouken@8972
   206
DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
slouken@8972
   207
{
slouken@8972
   208
    SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
slouken@8972
   209
slouken@8972
   210
    if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
slouken@8972
   211
        const GUID *guid = &dev->guidType;
slouken@8972
   212
        DWORD offset = 0;
icculus@10885
   213
        if (WIN_IsEqualGUID(guid, &GUID_XAxis)) {
slouken@8972
   214
            offset = DIJOFS_X;
icculus@10885
   215
        } else if (WIN_IsEqualGUID(guid, &GUID_YAxis)) {
slouken@8972
   216
            offset = DIJOFS_Y;
icculus@10885
   217
        } else if (WIN_IsEqualGUID(guid, &GUID_ZAxis)) {
slouken@8972
   218
            offset = DIJOFS_Z;
icculus@10885
   219
        } else if (WIN_IsEqualGUID(guid, &GUID_RxAxis)) {
slouken@8972
   220
            offset = DIJOFS_RX;
icculus@10885
   221
        } else if (WIN_IsEqualGUID(guid, &GUID_RyAxis)) {
slouken@8972
   222
            offset = DIJOFS_RY;
icculus@10885
   223
        } else if (WIN_IsEqualGUID(guid, &GUID_RzAxis)) {
slouken@8972
   224
            offset = DIJOFS_RZ;
slouken@8972
   225
        } else {
slouken@8972
   226
            return DIENUM_CONTINUE;   /* can't use this, go on. */
slouken@8972
   227
        }
slouken@8972
   228
slouken@8972
   229
        haptic->hwdata->axes[haptic->naxes] = offset;
slouken@8972
   230
        haptic->naxes++;
slouken@8972
   231
slouken@8972
   232
        /* Currently using the artificial limit of 3 axes. */
slouken@8972
   233
        if (haptic->naxes >= 3) {
slouken@8972
   234
            return DIENUM_STOP;
slouken@8972
   235
        }
slouken@8972
   236
    }
slouken@8972
   237
slouken@8972
   238
    return DIENUM_CONTINUE;
slouken@8972
   239
}
slouken@8972
   240
slouken@8972
   241
/*
slouken@8972
   242
 * Callback to get all supported effects.
slouken@8972
   243
 */
slouken@8972
   244
#define EFFECT_TEST(e,s)               \
icculus@10885
   245
if (WIN_IsEqualGUID(&pei->guid, &(e)))   \
slouken@8972
   246
   haptic->supported |= (s)
slouken@8972
   247
static BOOL CALLBACK
slouken@8972
   248
DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
slouken@8972
   249
{
slouken@8972
   250
    /* Prepare the haptic device. */
slouken@8972
   251
    SDL_Haptic *haptic = (SDL_Haptic *) pv;
slouken@8972
   252
slouken@8972
   253
    /* Get supported. */
slouken@8972
   254
    EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
slouken@8972
   255
    EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
slouken@8972
   256
    EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
slouken@8972
   257
    EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
slouken@8972
   258
    EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
slouken@8972
   259
    EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
slouken@8972
   260
    EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
slouken@8972
   261
    /* !!! FIXME: put this back when we have more bits in 2.1 */
slouken@8972
   262
    /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
slouken@8972
   263
    EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
slouken@8972
   264
    EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
slouken@8972
   265
    EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
slouken@8972
   266
    EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
slouken@8972
   267
slouken@8972
   268
    /* Check for more. */
slouken@8972
   269
    return DIENUM_CONTINUE;
slouken@8972
   270
}
slouken@8972
   271
slouken@8972
   272
/*
slouken@8972
   273
 * Opens the haptic device.
slouken@8972
   274
 *
slouken@8972
   275
 *    Steps:
slouken@8972
   276
 *       - Set cooperative level.
slouken@8972
   277
 *       - Set data format.
slouken@8972
   278
 *       - Acquire exclusiveness.
slouken@8972
   279
 *       - Reset actuators.
slouken@8972
   280
 *       - Get supported features.
slouken@8972
   281
 */
slouken@8972
   282
static int
slouken@8972
   283
SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
slouken@8972
   284
{
slouken@8972
   285
    HRESULT ret;
slouken@8972
   286
    DIPROPDWORD dipdw;
slouken@8972
   287
slouken@8972
   288
    /* Allocate the hwdata */
slouken@8972
   289
    haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
slouken@8972
   290
    if (haptic->hwdata == NULL) {
slouken@8972
   291
        return SDL_OutOfMemory();
slouken@8972
   292
    }
slouken@8972
   293
    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
slouken@8972
   294
slouken@8972
   295
    /* We'll use the device8 from now on. */
slouken@8972
   296
    haptic->hwdata->device = device8;
slouken@8972
   297
    haptic->hwdata->is_joystick = is_joystick;
slouken@8972
   298
slouken@8972
   299
    /* !!! FIXME: opening a haptic device here first will make an attempt to
slouken@8972
   300
       !!! FIXME:  SDL_JoystickOpen() that same device fail later, since we
slouken@8972
   301
       !!! FIXME:  have it open in exclusive mode. But this will allow
slouken@8972
   302
       !!! FIXME:  SDL_JoystickOpen() followed by SDL_HapticOpenFromJoystick()
slouken@8972
   303
       !!! FIXME:  to work, and that's probably the common case. Still,
slouken@8972
   304
       !!! FIXME:  ideally, We need to unify the opening code. */
slouken@8972
   305
slouken@8972
   306
    if (!is_joystick) {  /* if is_joystick, we already set this up elsewhere. */
slouken@8972
   307
        /* Grab it exclusively to use force feedback stuff. */
slouken@8972
   308
        ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
slouken@8972
   309
                                                      SDL_HelperWindow,
slouken@8972
   310
                                                      DISCL_EXCLUSIVE |
slouken@8972
   311
                                                      DISCL_BACKGROUND);
slouken@8972
   312
        if (FAILED(ret)) {
slouken@8972
   313
            DI_SetError("Setting cooperative level to exclusive", ret);
slouken@8972
   314
            goto acquire_err;
slouken@8972
   315
        }
slouken@8972
   316
slouken@8972
   317
        /* Set data format. */
slouken@8972
   318
        ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
slouken@10442
   319
                                                &SDL_c_dfDIJoystick2);
slouken@8972
   320
        if (FAILED(ret)) {
slouken@8972
   321
            DI_SetError("Setting data format", ret);
slouken@8972
   322
            goto acquire_err;
slouken@8972
   323
        }
slouken@8972
   324
slouken@8972
   325
slouken@8972
   326
        /* Acquire the device. */
slouken@8972
   327
        ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
slouken@8972
   328
        if (FAILED(ret)) {
slouken@8972
   329
            DI_SetError("Acquiring DirectInput device", ret);
slouken@8972
   330
            goto acquire_err;
slouken@8972
   331
        }
slouken@8972
   332
    }
slouken@8972
   333
slouken@10463
   334
    /* Get number of axes. */
slouken@10463
   335
    ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
slouken@10463
   336
                                          DI_DeviceObjectCallback,
slouken@10463
   337
                                          haptic, DIDFT_AXIS);
slouken@10463
   338
    if (FAILED(ret)) {
slouken@10463
   339
        DI_SetError("Getting device axes", ret);
slouken@10463
   340
        goto acquire_err;
slouken@10463
   341
    }
slouken@10463
   342
slouken@8972
   343
    /* Reset all actuators - just in case. */
slouken@8972
   344
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
   345
                                                       DISFFC_RESET);
slouken@8972
   346
    if (FAILED(ret)) {
slouken@8972
   347
        DI_SetError("Resetting device", ret);
slouken@8972
   348
        goto acquire_err;
slouken@8972
   349
    }
slouken@8972
   350
slouken@8972
   351
    /* Enabling actuators. */
slouken@8972
   352
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
   353
                                                       DISFFC_SETACTUATORSON);
slouken@8972
   354
    if (FAILED(ret)) {
slouken@8972
   355
        DI_SetError("Enabling actuators", ret);
slouken@8972
   356
        goto acquire_err;
slouken@8972
   357
    }
slouken@8972
   358
slouken@8972
   359
    /* Get supported effects. */
slouken@8972
   360
    ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
slouken@8972
   361
                                          DI_EffectCallback, haptic,
slouken@8972
   362
                                          DIEFT_ALL);
slouken@8972
   363
    if (FAILED(ret)) {
slouken@8972
   364
        DI_SetError("Enumerating supported effects", ret);
slouken@8972
   365
        goto acquire_err;
slouken@8972
   366
    }
slouken@8972
   367
    if (haptic->supported == 0) {       /* Error since device supports nothing. */
slouken@8972
   368
        SDL_SetError("Haptic: Internal error on finding supported effects.");
slouken@8972
   369
        goto acquire_err;
slouken@8972
   370
    }
slouken@8972
   371
slouken@8972
   372
    /* Check autogain and autocenter. */
slouken@8972
   373
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
   374
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
   375
    dipdw.diph.dwObj = 0;
slouken@8972
   376
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   377
    dipdw.dwData = 10000;
slouken@8972
   378
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
   379
                                          DIPROP_FFGAIN, &dipdw.diph);
slouken@8972
   380
    if (!FAILED(ret)) {         /* Gain is supported. */
slouken@8972
   381
        haptic->supported |= SDL_HAPTIC_GAIN;
slouken@8972
   382
    }
slouken@8972
   383
    dipdw.diph.dwObj = 0;
slouken@8972
   384
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   385
    dipdw.dwData = DIPROPAUTOCENTER_OFF;
slouken@8972
   386
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
   387
                                          DIPROP_AUTOCENTER, &dipdw.diph);
slouken@8972
   388
    if (!FAILED(ret)) {         /* Autocenter is supported. */
slouken@8972
   389
        haptic->supported |= SDL_HAPTIC_AUTOCENTER;
slouken@8972
   390
    }
slouken@8972
   391
slouken@8972
   392
    /* Status is always supported. */
slouken@8972
   393
    haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
slouken@8972
   394
slouken@8972
   395
    /* Check maximum effects. */
slouken@8972
   396
    haptic->neffects = 128;     /* This is not actually supported as thus under windows,
slouken@8972
   397
                                   there is no way to tell the number of EFFECTS that a
slouken@8972
   398
                                   device can hold, so we'll just use a "random" number
slouken@8972
   399
                                   instead and put warnings in SDL_haptic.h */
slouken@8972
   400
    haptic->nplaying = 128;     /* Even more impossible to get this then neffects. */
slouken@8972
   401
slouken@8972
   402
    /* Prepare effects memory. */
slouken@8972
   403
    haptic->effects = (struct haptic_effect *)
slouken@8972
   404
        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
slouken@8972
   405
    if (haptic->effects == NULL) {
slouken@8972
   406
        SDL_OutOfMemory();
slouken@8972
   407
        goto acquire_err;
slouken@8972
   408
    }
slouken@8972
   409
    /* Clear the memory */
slouken@8972
   410
    SDL_memset(haptic->effects, 0,
slouken@8972
   411
               sizeof(struct haptic_effect) * haptic->neffects);
slouken@8972
   412
slouken@8972
   413
    return 0;
slouken@8972
   414
slouken@8972
   415
    /* Error handling */
slouken@8972
   416
  acquire_err:
slouken@8972
   417
    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
slouken@8972
   418
    return -1;
slouken@8972
   419
}
slouken@8972
   420
slouken@8972
   421
int
slouken@8972
   422
SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
slouken@8972
   423
{
slouken@8972
   424
    HRESULT ret;
slouken@8972
   425
    LPDIRECTINPUTDEVICE8 device;
slouken@8972
   426
    LPDIRECTINPUTDEVICE8 device8;
slouken@8972
   427
slouken@8972
   428
    /* Open the device */
slouken@8972
   429
    ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
slouken@8972
   430
        &device, NULL);
slouken@8972
   431
    if (FAILED(ret)) {
slouken@8972
   432
        DI_SetError("Creating DirectInput device", ret);
slouken@8972
   433
        return -1;
slouken@8972
   434
    }
slouken@8972
   435
slouken@8972
   436
    /* Now get the IDirectInputDevice8 interface, instead. */
slouken@8972
   437
    ret = IDirectInputDevice8_QueryInterface(device,
slouken@8972
   438
        &IID_IDirectInputDevice8,
slouken@8972
   439
        (LPVOID *)&device8);
slouken@8972
   440
    /* Done with the temporary one now. */
slouken@8972
   441
    IDirectInputDevice8_Release(device);
slouken@8972
   442
    if (FAILED(ret)) {
slouken@8972
   443
        DI_SetError("Querying DirectInput interface", ret);
slouken@8972
   444
        return -1;
slouken@8972
   445
    }
slouken@8972
   446
slouken@8972
   447
    if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
slouken@8972
   448
        IDirectInputDevice8_Release(device8);
slouken@8972
   449
        return -1;
slouken@8972
   450
    }
slouken@8972
   451
    return 0;
slouken@8972
   452
}
slouken@8972
   453
slouken@8972
   454
int
slouken@8972
   455
SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
   456
{
slouken@8972
   457
    HRESULT ret;
slouken@8972
   458
    DIDEVICEINSTANCE hap_instance, joy_instance;
slouken@8972
   459
slouken@8972
   460
    hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   461
    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   462
slouken@8972
   463
    /* Get the device instances. */
slouken@8972
   464
    ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
slouken@8972
   465
        &hap_instance);
slouken@8972
   466
    if (FAILED(ret)) {
slouken@8972
   467
        return 0;
slouken@8972
   468
    }
slouken@8972
   469
    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
slouken@8972
   470
        &joy_instance);
slouken@8972
   471
    if (FAILED(ret)) {
slouken@8972
   472
        return 0;
slouken@8972
   473
    }
slouken@8972
   474
icculus@10885
   475
    return WIN_IsEqualGUID(&hap_instance.guidInstance, &joy_instance.guidInstance);
slouken@8972
   476
}
slouken@8972
   477
slouken@8972
   478
int
slouken@8972
   479
SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
   480
{
slouken@8972
   481
    SDL_hapticlist_item *item;
slouken@8972
   482
    int index = 0;
slouken@8972
   483
    HRESULT ret;
slouken@8972
   484
    DIDEVICEINSTANCE joy_instance;
slouken@8972
   485
slouken@8972
   486
    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   487
    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
slouken@8972
   488
    if (FAILED(ret)) {
slouken@8972
   489
        return -1;
slouken@8972
   490
    }
slouken@8972
   491
slouken@8972
   492
    /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
slouken@8972
   493
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
icculus@10885
   494
        if (!item->bXInputHaptic && WIN_IsEqualGUID(&item->instance.guidInstance, &joy_instance.guidInstance)) {
slouken@8972
   495
            haptic->index = index;
slouken@8972
   496
            return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
slouken@8972
   497
        }
slouken@8972
   498
        ++index;
slouken@8972
   499
    }
slouken@8972
   500
slouken@8972
   501
    SDL_SetError("Couldn't find joystick in haptic device list");
slouken@8972
   502
    return -1;
slouken@8972
   503
}
slouken@8972
   504
slouken@8972
   505
void
slouken@8972
   506
SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
slouken@8972
   507
{
slouken@8972
   508
    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
slouken@8972
   509
slouken@8972
   510
    /* Only release if isn't grabbed by a joystick. */
slouken@8972
   511
    if (haptic->hwdata->is_joystick == 0) {
slouken@8972
   512
        IDirectInputDevice8_Release(haptic->hwdata->device);
slouken@8972
   513
    }
slouken@8972
   514
}
slouken@8972
   515
slouken@8972
   516
void
slouken@8972
   517
SDL_DINPUT_HapticQuit(void)
slouken@8972
   518
{
slouken@8972
   519
    if (dinput != NULL) {
slouken@8972
   520
        IDirectInput8_Release(dinput);
slouken@8972
   521
        dinput = NULL;
slouken@8972
   522
    }
slouken@8972
   523
slouken@8972
   524
    if (coinitialized) {
slouken@8972
   525
        WIN_CoUninitialize();
slouken@8972
   526
        coinitialized = SDL_FALSE;
slouken@8972
   527
    }
slouken@8972
   528
}
slouken@8972
   529
slouken@8972
   530
/*
slouken@8972
   531
 * Converts an SDL trigger button to an DIEFFECT trigger button.
slouken@8972
   532
 */
slouken@8972
   533
static DWORD
slouken@8972
   534
DIGetTriggerButton(Uint16 button)
slouken@8972
   535
{
slouken@8972
   536
    DWORD dwTriggerButton;
slouken@8972
   537
slouken@8972
   538
    dwTriggerButton = DIEB_NOTRIGGER;
slouken@8972
   539
slouken@8972
   540
    if (button != 0) {
slouken@8972
   541
        dwTriggerButton = DIJOFS_BUTTON(button - 1);
slouken@8972
   542
    }
slouken@8972
   543
slouken@8972
   544
    return dwTriggerButton;
slouken@8972
   545
}
slouken@8972
   546
slouken@8972
   547
slouken@8972
   548
/*
slouken@8972
   549
 * Sets the direction.
slouken@8972
   550
 */
slouken@8972
   551
static int
slouken@8972
   552
SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
slouken@8972
   553
{
slouken@8972
   554
    LONG *rglDir;
slouken@8972
   555
slouken@8972
   556
    /* Handle no axes a part. */
slouken@8972
   557
    if (naxes == 0) {
slouken@8972
   558
        effect->dwFlags |= DIEFF_SPHERICAL;     /* Set as default. */
slouken@8972
   559
        effect->rglDirection = NULL;
slouken@8972
   560
        return 0;
slouken@8972
   561
    }
slouken@8972
   562
slouken@8972
   563
    /* Has axes. */
slouken@8972
   564
    rglDir = SDL_malloc(sizeof(LONG) * naxes);
slouken@8972
   565
    if (rglDir == NULL) {
slouken@8972
   566
        return SDL_OutOfMemory();
slouken@8972
   567
    }
slouken@8972
   568
    SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
slouken@8972
   569
    effect->rglDirection = rglDir;
slouken@8972
   570
slouken@8972
   571
    switch (dir->type) {
slouken@8972
   572
    case SDL_HAPTIC_POLAR:
slouken@8972
   573
        effect->dwFlags |= DIEFF_POLAR;
slouken@8972
   574
        rglDir[0] = dir->dir[0];
slouken@8972
   575
        return 0;
slouken@8972
   576
    case SDL_HAPTIC_CARTESIAN:
slouken@8972
   577
        effect->dwFlags |= DIEFF_CARTESIAN;
slouken@8972
   578
        rglDir[0] = dir->dir[0];
slouken@8972
   579
        if (naxes > 1)
slouken@8972
   580
            rglDir[1] = dir->dir[1];
slouken@8972
   581
        if (naxes > 2)
slouken@8972
   582
            rglDir[2] = dir->dir[2];
slouken@8972
   583
        return 0;
slouken@8972
   584
    case SDL_HAPTIC_SPHERICAL:
slouken@8972
   585
        effect->dwFlags |= DIEFF_SPHERICAL;
slouken@8972
   586
        rglDir[0] = dir->dir[0];
slouken@8972
   587
        if (naxes > 1)
slouken@8972
   588
            rglDir[1] = dir->dir[1];
slouken@8972
   589
        if (naxes > 2)
slouken@8972
   590
            rglDir[2] = dir->dir[2];
slouken@8972
   591
        return 0;
slouken@13789
   592
    case SDL_HAPTIC_STEERING_AXIS:
slouken@13635
   593
        effect->dwFlags |= DIEFF_CARTESIAN;
slouken@13635
   594
        rglDir[0] = 0;
slouken@13635
   595
        return 0;
slouken@8972
   596
slouken@8972
   597
    default:
slouken@8972
   598
        return SDL_SetError("Haptic: Unknown direction type.");
slouken@8972
   599
    }
slouken@8972
   600
}
slouken@8972
   601
icculus@9071
   602
/* Clamps and converts. */
icculus@9071
   603
#define CCONVERT(x)   (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
icculus@9071
   604
/* Just converts. */
icculus@9071
   605
#define CONVERT(x)    (((x)*10000) / 0x7FFF)
slouken@8972
   606
/*
slouken@8972
   607
 * Creates the DIEFFECT from a SDL_HapticEffect.
slouken@8972
   608
 */
slouken@8972
   609
static int
slouken@8972
   610
SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
slouken@8972
   611
                   SDL_HapticEffect * src)
slouken@8972
   612
{
slouken@8972
   613
    int i;
slouken@8972
   614
    DICONSTANTFORCE *constant;
slouken@8972
   615
    DIPERIODIC *periodic;
slouken@8972
   616
    DICONDITION *condition;     /* Actually an array of conditions - one per axis. */
slouken@8972
   617
    DIRAMPFORCE *ramp;
slouken@8972
   618
    DICUSTOMFORCE *custom;
slouken@8972
   619
    DIENVELOPE *envelope;
slouken@8972
   620
    SDL_HapticConstant *hap_constant;
slouken@8972
   621
    SDL_HapticPeriodic *hap_periodic;
slouken@8972
   622
    SDL_HapticCondition *hap_condition;
slouken@8972
   623
    SDL_HapticRamp *hap_ramp;
slouken@8972
   624
    SDL_HapticCustom *hap_custom;
slouken@8972
   625
    DWORD *axes;
slouken@8972
   626
slouken@8972
   627
    /* Set global stuff. */
slouken@8972
   628
    SDL_memset(dest, 0, sizeof(DIEFFECT));
slouken@8972
   629
    dest->dwSize = sizeof(DIEFFECT);    /* Set the structure size. */
slouken@8972
   630
    dest->dwSamplePeriod = 0;   /* Not used by us. */
slouken@8972
   631
    dest->dwGain = 10000;       /* Gain is set globally, not locally. */
slouken@8972
   632
    dest->dwFlags = DIEFF_OBJECTOFFSETS;        /* Seems obligatory. */
slouken@8972
   633
slouken@8972
   634
    /* Envelope. */
slouken@8972
   635
    envelope = SDL_malloc(sizeof(DIENVELOPE));
slouken@8972
   636
    if (envelope == NULL) {
slouken@8972
   637
        return SDL_OutOfMemory();
slouken@8972
   638
    }
slouken@8972
   639
    SDL_memset(envelope, 0, sizeof(DIENVELOPE));
slouken@8972
   640
    dest->lpEnvelope = envelope;
slouken@8972
   641
    envelope->dwSize = sizeof(DIENVELOPE);      /* Always should be this. */
slouken@8972
   642
slouken@8972
   643
    /* Axes. */
slouken@13789
   644
    if (src->constant.direction.type == SDL_HAPTIC_STEERING_AXIS) {
slouken@13635
   645
        dest->cAxes = 1;
slouken@13635
   646
    } else {
slouken@13635
   647
        dest->cAxes = haptic->naxes;
slouken@13635
   648
    }
slouken@8972
   649
    if (dest->cAxes > 0) {
slouken@8972
   650
        axes = SDL_malloc(sizeof(DWORD) * dest->cAxes);
slouken@8972
   651
        if (axes == NULL) {
slouken@8972
   652
            return SDL_OutOfMemory();
slouken@8972
   653
        }
slouken@8972
   654
        axes[0] = haptic->hwdata->axes[0];      /* Always at least one axis. */
slouken@8972
   655
        if (dest->cAxes > 1) {
slouken@8972
   656
            axes[1] = haptic->hwdata->axes[1];
slouken@8972
   657
        }
slouken@8972
   658
        if (dest->cAxes > 2) {
slouken@8972
   659
            axes[2] = haptic->hwdata->axes[2];
slouken@8972
   660
        }
slouken@8972
   661
        dest->rgdwAxes = axes;
slouken@8972
   662
    }
slouken@8972
   663
slouken@8972
   664
    /* The big type handling switch, even bigger than Linux's version. */
slouken@8972
   665
    switch (src->type) {
slouken@8972
   666
    case SDL_HAPTIC_CONSTANT:
slouken@8972
   667
        hap_constant = &src->constant;
slouken@8972
   668
        constant = SDL_malloc(sizeof(DICONSTANTFORCE));
slouken@8972
   669
        if (constant == NULL) {
slouken@8972
   670
            return SDL_OutOfMemory();
slouken@8972
   671
        }
slouken@8972
   672
        SDL_memset(constant, 0, sizeof(DICONSTANTFORCE));
slouken@8972
   673
slouken@8972
   674
        /* Specifics */
slouken@8972
   675
        constant->lMagnitude = CONVERT(hap_constant->level);
slouken@8972
   676
        dest->cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
slouken@8972
   677
        dest->lpvTypeSpecificParams = constant;
slouken@8972
   678
slouken@8972
   679
        /* Generics */
slouken@8972
   680
        dest->dwDuration = hap_constant->length * 1000; /* In microseconds. */
slouken@8972
   681
        dest->dwTriggerButton = DIGetTriggerButton(hap_constant->button);
slouken@8972
   682
        dest->dwTriggerRepeatInterval = hap_constant->interval;
slouken@8972
   683
        dest->dwStartDelay = hap_constant->delay * 1000;        /* In microseconds. */
slouken@8972
   684
slouken@8972
   685
        /* Direction. */
slouken@8972
   686
        if (SDL_SYS_SetDirection(dest, &hap_constant->direction, dest->cAxes) < 0) {
slouken@8972
   687
            return -1;
slouken@8972
   688
        }
slouken@8972
   689
slouken@8972
   690
        /* Envelope */
slouken@8972
   691
        if ((hap_constant->attack_length == 0)
slouken@8972
   692
            && (hap_constant->fade_length == 0)) {
slouken@8972
   693
            SDL_free(dest->lpEnvelope);
slouken@8972
   694
            dest->lpEnvelope = NULL;
slouken@8972
   695
        } else {
icculus@9071
   696
            envelope->dwAttackLevel = CCONVERT(hap_constant->attack_level);
slouken@8972
   697
            envelope->dwAttackTime = hap_constant->attack_length * 1000;
icculus@9071
   698
            envelope->dwFadeLevel = CCONVERT(hap_constant->fade_level);
slouken@8972
   699
            envelope->dwFadeTime = hap_constant->fade_length * 1000;
slouken@8972
   700
        }
slouken@8972
   701
slouken@8972
   702
        break;
slouken@8972
   703
slouken@8972
   704
    case SDL_HAPTIC_SINE:
slouken@8972
   705
    /* !!! FIXME: put this back when we have more bits in 2.1 */
slouken@8972
   706
    /* case SDL_HAPTIC_SQUARE: */
slouken@8972
   707
    case SDL_HAPTIC_TRIANGLE:
slouken@8972
   708
    case SDL_HAPTIC_SAWTOOTHUP:
slouken@8972
   709
    case SDL_HAPTIC_SAWTOOTHDOWN:
slouken@8972
   710
        hap_periodic = &src->periodic;
slouken@8972
   711
        periodic = SDL_malloc(sizeof(DIPERIODIC));
slouken@8972
   712
        if (periodic == NULL) {
slouken@8972
   713
            return SDL_OutOfMemory();
slouken@8972
   714
        }
slouken@8972
   715
        SDL_memset(periodic, 0, sizeof(DIPERIODIC));
slouken@8972
   716
slouken@8972
   717
        /* Specifics */
icculus@9147
   718
        periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude));
slouken@8972
   719
        periodic->lOffset = CONVERT(hap_periodic->offset);
icculus@9147
   720
        periodic->dwPhase = 
icculus@9147
   721
                (hap_periodic->phase + (hap_periodic->magnitude < 0 ? 18000 : 0)) % 36000;
slouken@8972
   722
        periodic->dwPeriod = hap_periodic->period * 1000;
slouken@8972
   723
        dest->cbTypeSpecificParams = sizeof(DIPERIODIC);
slouken@8972
   724
        dest->lpvTypeSpecificParams = periodic;
slouken@8972
   725
slouken@8972
   726
        /* Generics */
slouken@8972
   727
        dest->dwDuration = hap_periodic->length * 1000; /* In microseconds. */
slouken@8972
   728
        dest->dwTriggerButton = DIGetTriggerButton(hap_periodic->button);
slouken@8972
   729
        dest->dwTriggerRepeatInterval = hap_periodic->interval;
slouken@8972
   730
        dest->dwStartDelay = hap_periodic->delay * 1000;        /* In microseconds. */
slouken@8972
   731
slouken@8972
   732
        /* Direction. */
slouken@8972
   733
        if (SDL_SYS_SetDirection(dest, &hap_periodic->direction, dest->cAxes)
slouken@8972
   734
            < 0) {
slouken@8972
   735
            return -1;
slouken@8972
   736
        }
slouken@8972
   737
slouken@8972
   738
        /* Envelope */
slouken@8972
   739
        if ((hap_periodic->attack_length == 0)
slouken@8972
   740
            && (hap_periodic->fade_length == 0)) {
slouken@8972
   741
            SDL_free(dest->lpEnvelope);
slouken@8972
   742
            dest->lpEnvelope = NULL;
slouken@8972
   743
        } else {
icculus@9071
   744
            envelope->dwAttackLevel = CCONVERT(hap_periodic->attack_level);
slouken@8972
   745
            envelope->dwAttackTime = hap_periodic->attack_length * 1000;
icculus@9071
   746
            envelope->dwFadeLevel = CCONVERT(hap_periodic->fade_level);
slouken@8972
   747
            envelope->dwFadeTime = hap_periodic->fade_length * 1000;
slouken@8972
   748
        }
slouken@8972
   749
slouken@8972
   750
        break;
slouken@8972
   751
slouken@8972
   752
    case SDL_HAPTIC_SPRING:
slouken@8972
   753
    case SDL_HAPTIC_DAMPER:
slouken@8972
   754
    case SDL_HAPTIC_INERTIA:
slouken@8972
   755
    case SDL_HAPTIC_FRICTION:
slouken@8972
   756
        hap_condition = &src->condition;
slouken@8972
   757
        condition = SDL_malloc(sizeof(DICONDITION) * dest->cAxes);
slouken@8972
   758
        if (condition == NULL) {
slouken@8972
   759
            return SDL_OutOfMemory();
slouken@8972
   760
        }
slouken@8972
   761
        SDL_memset(condition, 0, sizeof(DICONDITION));
slouken@8972
   762
slouken@8972
   763
        /* Specifics */
slouken@8972
   764
        for (i = 0; i < (int) dest->cAxes; i++) {
slouken@8972
   765
            condition[i].lOffset = CONVERT(hap_condition->center[i]);
slouken@8972
   766
            condition[i].lPositiveCoefficient =
slouken@8972
   767
                CONVERT(hap_condition->right_coeff[i]);
slouken@8972
   768
            condition[i].lNegativeCoefficient =
slouken@8972
   769
                CONVERT(hap_condition->left_coeff[i]);
slouken@8972
   770
            condition[i].dwPositiveSaturation =
icculus@9071
   771
                CCONVERT(hap_condition->right_sat[i] / 2);
slouken@8972
   772
            condition[i].dwNegativeSaturation =
icculus@9071
   773
                CCONVERT(hap_condition->left_sat[i] / 2);
icculus@9071
   774
            condition[i].lDeadBand = CCONVERT(hap_condition->deadband[i] / 2);
slouken@8972
   775
        }
slouken@8972
   776
        dest->cbTypeSpecificParams = sizeof(DICONDITION) * dest->cAxes;
slouken@8972
   777
        dest->lpvTypeSpecificParams = condition;
slouken@8972
   778
slouken@8972
   779
        /* Generics */
slouken@8972
   780
        dest->dwDuration = hap_condition->length * 1000;        /* In microseconds. */
slouken@8972
   781
        dest->dwTriggerButton = DIGetTriggerButton(hap_condition->button);
slouken@8972
   782
        dest->dwTriggerRepeatInterval = hap_condition->interval;
slouken@8972
   783
        dest->dwStartDelay = hap_condition->delay * 1000;       /* In microseconds. */
slouken@8972
   784
slouken@8972
   785
        /* Direction. */
slouken@8972
   786
        if (SDL_SYS_SetDirection(dest, &hap_condition->direction, dest->cAxes)
slouken@8972
   787
            < 0) {
slouken@8972
   788
            return -1;
slouken@8972
   789
        }
slouken@8972
   790
slouken@8972
   791
        /* Envelope - Not actually supported by most CONDITION implementations. */
slouken@8972
   792
        SDL_free(dest->lpEnvelope);
slouken@8972
   793
        dest->lpEnvelope = NULL;
slouken@8972
   794
slouken@8972
   795
        break;
slouken@8972
   796
slouken@8972
   797
    case SDL_HAPTIC_RAMP:
slouken@8972
   798
        hap_ramp = &src->ramp;
slouken@8972
   799
        ramp = SDL_malloc(sizeof(DIRAMPFORCE));
slouken@8972
   800
        if (ramp == NULL) {
slouken@8972
   801
            return SDL_OutOfMemory();
slouken@8972
   802
        }
slouken@8972
   803
        SDL_memset(ramp, 0, sizeof(DIRAMPFORCE));
slouken@8972
   804
slouken@8972
   805
        /* Specifics */
slouken@8972
   806
        ramp->lStart = CONVERT(hap_ramp->start);
slouken@8972
   807
        ramp->lEnd = CONVERT(hap_ramp->end);
slouken@8972
   808
        dest->cbTypeSpecificParams = sizeof(DIRAMPFORCE);
slouken@8972
   809
        dest->lpvTypeSpecificParams = ramp;
slouken@8972
   810
slouken@8972
   811
        /* Generics */
slouken@8972
   812
        dest->dwDuration = hap_ramp->length * 1000;     /* In microseconds. */
slouken@8972
   813
        dest->dwTriggerButton = DIGetTriggerButton(hap_ramp->button);
slouken@8972
   814
        dest->dwTriggerRepeatInterval = hap_ramp->interval;
slouken@8972
   815
        dest->dwStartDelay = hap_ramp->delay * 1000;    /* In microseconds. */
slouken@8972
   816
slouken@8972
   817
        /* Direction. */
slouken@8972
   818
        if (SDL_SYS_SetDirection(dest, &hap_ramp->direction, dest->cAxes) < 0) {
slouken@8972
   819
            return -1;
slouken@8972
   820
        }
slouken@8972
   821
slouken@8972
   822
        /* Envelope */
slouken@8972
   823
        if ((hap_ramp->attack_length == 0) && (hap_ramp->fade_length == 0)) {
slouken@8972
   824
            SDL_free(dest->lpEnvelope);
slouken@8972
   825
            dest->lpEnvelope = NULL;
slouken@8972
   826
        } else {
icculus@9071
   827
            envelope->dwAttackLevel = CCONVERT(hap_ramp->attack_level);
slouken@8972
   828
            envelope->dwAttackTime = hap_ramp->attack_length * 1000;
icculus@9071
   829
            envelope->dwFadeLevel = CCONVERT(hap_ramp->fade_level);
slouken@8972
   830
            envelope->dwFadeTime = hap_ramp->fade_length * 1000;
slouken@8972
   831
        }
slouken@8972
   832
slouken@8972
   833
        break;
slouken@8972
   834
slouken@8972
   835
    case SDL_HAPTIC_CUSTOM:
slouken@8972
   836
        hap_custom = &src->custom;
slouken@8972
   837
        custom = SDL_malloc(sizeof(DICUSTOMFORCE));
slouken@8972
   838
        if (custom == NULL) {
slouken@8972
   839
            return SDL_OutOfMemory();
slouken@8972
   840
        }
slouken@8972
   841
        SDL_memset(custom, 0, sizeof(DICUSTOMFORCE));
slouken@8972
   842
slouken@8972
   843
        /* Specifics */
slouken@8972
   844
        custom->cChannels = hap_custom->channels;
slouken@8972
   845
        custom->dwSamplePeriod = hap_custom->period * 1000;
slouken@8972
   846
        custom->cSamples = hap_custom->samples;
slouken@8972
   847
        custom->rglForceData =
slouken@8972
   848
            SDL_malloc(sizeof(LONG) * custom->cSamples * custom->cChannels);
slouken@8972
   849
        for (i = 0; i < hap_custom->samples * hap_custom->channels; i++) {      /* Copy data. */
icculus@9071
   850
            custom->rglForceData[i] = CCONVERT(hap_custom->data[i]);
slouken@8972
   851
        }
slouken@8972
   852
        dest->cbTypeSpecificParams = sizeof(DICUSTOMFORCE);
slouken@8972
   853
        dest->lpvTypeSpecificParams = custom;
slouken@8972
   854
slouken@8972
   855
        /* Generics */
slouken@8972
   856
        dest->dwDuration = hap_custom->length * 1000;   /* In microseconds. */
slouken@8972
   857
        dest->dwTriggerButton = DIGetTriggerButton(hap_custom->button);
slouken@8972
   858
        dest->dwTriggerRepeatInterval = hap_custom->interval;
slouken@8972
   859
        dest->dwStartDelay = hap_custom->delay * 1000;  /* In microseconds. */
slouken@8972
   860
slouken@8972
   861
        /* Direction. */
slouken@8972
   862
        if (SDL_SYS_SetDirection(dest, &hap_custom->direction, dest->cAxes) < 0) {
slouken@8972
   863
            return -1;
slouken@8972
   864
        }
slouken@8972
   865
slouken@8972
   866
        /* Envelope */
slouken@8972
   867
        if ((hap_custom->attack_length == 0)
slouken@8972
   868
            && (hap_custom->fade_length == 0)) {
slouken@8972
   869
            SDL_free(dest->lpEnvelope);
slouken@8972
   870
            dest->lpEnvelope = NULL;
slouken@8972
   871
        } else {
icculus@9071
   872
            envelope->dwAttackLevel = CCONVERT(hap_custom->attack_level);
slouken@8972
   873
            envelope->dwAttackTime = hap_custom->attack_length * 1000;
icculus@9071
   874
            envelope->dwFadeLevel = CCONVERT(hap_custom->fade_level);
slouken@8972
   875
            envelope->dwFadeTime = hap_custom->fade_length * 1000;
slouken@8972
   876
        }
slouken@8972
   877
slouken@8972
   878
        break;
slouken@8972
   879
slouken@8972
   880
    default:
slouken@8972
   881
        return SDL_SetError("Haptic: Unknown effect type.");
slouken@8972
   882
    }
slouken@8972
   883
slouken@8972
   884
    return 0;
slouken@8972
   885
}
slouken@8972
   886
slouken@8972
   887
slouken@8972
   888
/*
slouken@8972
   889
 * Frees an DIEFFECT allocated by SDL_SYS_ToDIEFFECT.
slouken@8972
   890
 */
slouken@8972
   891
static void
slouken@8972
   892
SDL_SYS_HapticFreeDIEFFECT(DIEFFECT * effect, int type)
slouken@8972
   893
{
slouken@8972
   894
    DICUSTOMFORCE *custom;
slouken@8972
   895
slouken@8972
   896
    SDL_free(effect->lpEnvelope);
slouken@8972
   897
    effect->lpEnvelope = NULL;
slouken@8972
   898
    SDL_free(effect->rgdwAxes);
slouken@8972
   899
    effect->rgdwAxes = NULL;
slouken@8972
   900
    if (effect->lpvTypeSpecificParams != NULL) {
slouken@8972
   901
        if (type == SDL_HAPTIC_CUSTOM) {        /* Must free the custom data. */
slouken@8972
   902
            custom = (DICUSTOMFORCE *) effect->lpvTypeSpecificParams;
slouken@8972
   903
            SDL_free(custom->rglForceData);
slouken@8972
   904
            custom->rglForceData = NULL;
slouken@8972
   905
        }
slouken@8972
   906
        SDL_free(effect->lpvTypeSpecificParams);
slouken@8972
   907
        effect->lpvTypeSpecificParams = NULL;
slouken@8972
   908
    }
slouken@8972
   909
    SDL_free(effect->rglDirection);
slouken@8972
   910
    effect->rglDirection = NULL;
slouken@8972
   911
}
slouken@8972
   912
slouken@8972
   913
/*
slouken@8972
   914
 * Gets the effect type from the generic SDL haptic effect wrapper.
slouken@8972
   915
 */
slouken@8972
   916
static REFGUID
slouken@8972
   917
SDL_SYS_HapticEffectType(SDL_HapticEffect * effect)
slouken@8972
   918
{
slouken@8972
   919
    switch (effect->type) {
slouken@8972
   920
    case SDL_HAPTIC_CONSTANT:
slouken@8972
   921
        return &GUID_ConstantForce;
slouken@8972
   922
slouken@8972
   923
    case SDL_HAPTIC_RAMP:
slouken@8972
   924
        return &GUID_RampForce;
slouken@8972
   925
slouken@8972
   926
    /* !!! FIXME: put this back when we have more bits in 2.1 */
slouken@8972
   927
    /* case SDL_HAPTIC_SQUARE:
slouken@8972
   928
        return &GUID_Square; */
slouken@8972
   929
slouken@8972
   930
    case SDL_HAPTIC_SINE:
slouken@8972
   931
        return &GUID_Sine;
slouken@8972
   932
slouken@8972
   933
    case SDL_HAPTIC_TRIANGLE:
slouken@8972
   934
        return &GUID_Triangle;
slouken@8972
   935
slouken@8972
   936
    case SDL_HAPTIC_SAWTOOTHUP:
slouken@8972
   937
        return &GUID_SawtoothUp;
slouken@8972
   938
slouken@8972
   939
    case SDL_HAPTIC_SAWTOOTHDOWN:
slouken@8972
   940
        return &GUID_SawtoothDown;
slouken@8972
   941
slouken@8972
   942
    case SDL_HAPTIC_SPRING:
slouken@8972
   943
        return &GUID_Spring;
slouken@8972
   944
slouken@8972
   945
    case SDL_HAPTIC_DAMPER:
slouken@8972
   946
        return &GUID_Damper;
slouken@8972
   947
slouken@8972
   948
    case SDL_HAPTIC_INERTIA:
slouken@8972
   949
        return &GUID_Inertia;
slouken@8972
   950
slouken@8972
   951
    case SDL_HAPTIC_FRICTION:
slouken@8972
   952
        return &GUID_Friction;
slouken@8972
   953
slouken@8972
   954
    case SDL_HAPTIC_CUSTOM:
slouken@8972
   955
        return &GUID_CustomForce;
slouken@8972
   956
slouken@8972
   957
    default:
slouken@8972
   958
        return NULL;
slouken@8972
   959
    }
slouken@8972
   960
}
slouken@8972
   961
int
slouken@8972
   962
SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
slouken@8972
   963
{
slouken@8972
   964
    HRESULT ret;
slouken@8972
   965
    REFGUID type = SDL_SYS_HapticEffectType(base);
slouken@8972
   966
slouken@8972
   967
    if (type == NULL) {
slouken@8972
   968
        SDL_SetError("Haptic: Unknown effect type.");
slouken@8972
   969
        return -1;
slouken@8972
   970
    }
slouken@8972
   971
slouken@8972
   972
    /* Get the effect. */
slouken@8972
   973
    if (SDL_SYS_ToDIEFFECT(haptic, &effect->hweffect->effect, base) < 0) {
slouken@8972
   974
        goto err_effectdone;
slouken@8972
   975
    }
slouken@8972
   976
slouken@8972
   977
    /* Create the actual effect. */
slouken@8972
   978
    ret = IDirectInputDevice8_CreateEffect(haptic->hwdata->device, type,
slouken@8972
   979
        &effect->hweffect->effect,
slouken@8972
   980
        &effect->hweffect->ref, NULL);
slouken@8972
   981
    if (FAILED(ret)) {
slouken@8972
   982
        DI_SetError("Unable to create effect", ret);
slouken@8972
   983
        goto err_effectdone;
slouken@8972
   984
    }
slouken@8972
   985
slouken@8972
   986
    return 0;
slouken@8972
   987
slouken@8972
   988
err_effectdone:
slouken@8972
   989
    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, base->type);
slouken@8972
   990
    return -1;
slouken@8972
   991
}
slouken@8972
   992
slouken@8972
   993
int
slouken@8972
   994
SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
slouken@8972
   995
{
slouken@8972
   996
    HRESULT ret;
slouken@8972
   997
    DWORD flags;
slouken@8972
   998
    DIEFFECT temp;
slouken@8972
   999
slouken@8972
  1000
    /* Get the effect. */
slouken@8972
  1001
    SDL_memset(&temp, 0, sizeof(DIEFFECT));
slouken@8972
  1002
    if (SDL_SYS_ToDIEFFECT(haptic, &temp, data) < 0) {
slouken@8972
  1003
        goto err_update;
slouken@8972
  1004
    }
slouken@8972
  1005
slouken@8972
  1006
    /* Set the flags.  Might be worthwhile to diff temp with loaded effect and
slouken@8972
  1007
    *  only change those parameters. */
slouken@8972
  1008
    flags = DIEP_DIRECTION |
slouken@8972
  1009
        DIEP_DURATION |
slouken@8972
  1010
        DIEP_ENVELOPE |
slouken@8972
  1011
        DIEP_STARTDELAY |
slouken@8972
  1012
        DIEP_TRIGGERBUTTON |
slouken@8972
  1013
        DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS;
slouken@8972
  1014
slouken@8972
  1015
    /* Create the actual effect. */
slouken@8972
  1016
    ret =
slouken@8972
  1017
        IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
slouken@10819
  1018
    if (ret == DIERR_NOTEXCLUSIVEACQUIRED) {
slouken@10819
  1019
        IDirectInputDevice8_Unacquire(haptic->hwdata->device);
slouken@10819
  1020
        ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device, SDL_HelperWindow, DISCL_EXCLUSIVE | DISCL_BACKGROUND);
slouken@10819
  1021
        if (SUCCEEDED(ret)) {
slouken@10819
  1022
            ret = DIERR_NOTACQUIRED;
slouken@10819
  1023
        }
slouken@10819
  1024
    }
slouken@10819
  1025
    if (ret == DIERR_INPUTLOST || ret == DIERR_NOTACQUIRED) {
slouken@10819
  1026
        ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
slouken@10819
  1027
        if (SUCCEEDED(ret)) {
slouken@10819
  1028
            ret = IDirectInputEffect_SetParameters(effect->hweffect->ref, &temp, flags);
slouken@10819
  1029
        }
slouken@10819
  1030
    }
slouken@8972
  1031
    if (FAILED(ret)) {
slouken@8972
  1032
        DI_SetError("Unable to update effect", ret);
slouken@8972
  1033
        goto err_update;
slouken@8972
  1034
    }
slouken@8972
  1035
slouken@8972
  1036
    /* Copy it over. */
slouken@8972
  1037
    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
slouken@8972
  1038
    SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
slouken@8972
  1039
slouken@8972
  1040
    return 0;
slouken@8972
  1041
slouken@8972
  1042
err_update:
slouken@8972
  1043
    SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
slouken@8972
  1044
    return -1;
slouken@8972
  1045
}
slouken@8972
  1046
slouken@8972
  1047
int
slouken@8972
  1048
SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
slouken@8972
  1049
{
slouken@8972
  1050
    HRESULT ret;
slouken@8972
  1051
    DWORD iter;
slouken@8972
  1052
slouken@8972
  1053
    /* Check if it's infinite. */
slouken@8972
  1054
    if (iterations == SDL_HAPTIC_INFINITY) {
slouken@8972
  1055
        iter = INFINITE;
slouken@8972
  1056
    } else {
slouken@8972
  1057
        iter = iterations;
slouken@8972
  1058
    }
slouken@8972
  1059
slouken@8972
  1060
    /* Run the effect. */
slouken@8972
  1061
    ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
slouken@8972
  1062
    if (FAILED(ret)) {
slouken@8972
  1063
        return DI_SetError("Running the effect", ret);
slouken@8972
  1064
    }
slouken@8972
  1065
    return 0;
slouken@8972
  1066
}
slouken@8972
  1067
slouken@8972
  1068
int
slouken@8972
  1069
SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1070
{
slouken@8972
  1071
    HRESULT ret;
slouken@8972
  1072
slouken@8972
  1073
    ret = IDirectInputEffect_Stop(effect->hweffect->ref);
slouken@8972
  1074
    if (FAILED(ret)) {
slouken@8972
  1075
        return DI_SetError("Unable to stop effect", ret);
slouken@8972
  1076
    }
slouken@8972
  1077
    return 0;
slouken@8972
  1078
}
slouken@8972
  1079
slouken@8972
  1080
void
slouken@8972
  1081
SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1082
{
slouken@8972
  1083
    HRESULT ret;
slouken@8972
  1084
slouken@8972
  1085
    ret = IDirectInputEffect_Unload(effect->hweffect->ref);
slouken@8972
  1086
    if (FAILED(ret)) {
slouken@8972
  1087
        DI_SetError("Removing effect from the device", ret);
slouken@8972
  1088
    }
slouken@8972
  1089
    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);
slouken@8972
  1090
}
slouken@8972
  1091
slouken@8972
  1092
int
slouken@8972
  1093
SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1094
{
slouken@8972
  1095
    HRESULT ret;
slouken@8972
  1096
    DWORD status;
slouken@8972
  1097
slouken@8972
  1098
    ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
slouken@8972
  1099
    if (FAILED(ret)) {
slouken@8972
  1100
        return DI_SetError("Getting effect status", ret);
slouken@8972
  1101
    }
slouken@8972
  1102
slouken@8972
  1103
    if (status == 0)
slouken@8972
  1104
        return SDL_FALSE;
slouken@8972
  1105
    return SDL_TRUE;
slouken@8972
  1106
}
slouken@8972
  1107
slouken@8972
  1108
int
slouken@8972
  1109
SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@8972
  1110
{
slouken@8972
  1111
    HRESULT ret;
slouken@8972
  1112
    DIPROPDWORD dipdw;
slouken@8972
  1113
slouken@8972
  1114
    /* Create the weird structure thingy. */
slouken@8972
  1115
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
  1116
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
  1117
    dipdw.diph.dwObj = 0;
slouken@8972
  1118
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
  1119
    dipdw.dwData = gain * 100;  /* 0 to 10,000 */
slouken@8972
  1120
slouken@8972
  1121
    /* Try to set the autocenter. */
slouken@8972
  1122
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
  1123
        DIPROP_FFGAIN, &dipdw.diph);
slouken@8972
  1124
    if (FAILED(ret)) {
slouken@8972
  1125
        return DI_SetError("Setting gain", ret);
slouken@8972
  1126
    }
slouken@8972
  1127
    return 0;
slouken@8972
  1128
}
slouken@8972
  1129
slouken@8972
  1130
int
slouken@8972
  1131
SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@8972
  1132
{
slouken@8972
  1133
    HRESULT ret;
slouken@8972
  1134
    DIPROPDWORD dipdw;
slouken@8972
  1135
slouken@8972
  1136
    /* Create the weird structure thingy. */
slouken@8972
  1137
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
  1138
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
  1139
    dipdw.diph.dwObj = 0;
slouken@8972
  1140
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
  1141
    dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
slouken@8972
  1142
        DIPROPAUTOCENTER_ON;
slouken@8972
  1143
slouken@8972
  1144
    /* Try to set the autocenter. */
slouken@8972
  1145
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
  1146
        DIPROP_AUTOCENTER, &dipdw.diph);
slouken@8972
  1147
    if (FAILED(ret)) {
slouken@8972
  1148
        return DI_SetError("Setting autocenter", ret);
slouken@8972
  1149
    }
slouken@8972
  1150
    return 0;
slouken@8972
  1151
}
slouken@8972
  1152
slouken@8972
  1153
int
slouken@8972
  1154
SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
slouken@8972
  1155
{
slouken@8972
  1156
    HRESULT ret;
slouken@8972
  1157
slouken@8972
  1158
    /* Pause the device. */
slouken@8972
  1159
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1160
        DISFFC_PAUSE);
slouken@8972
  1161
    if (FAILED(ret)) {
slouken@8972
  1162
        return DI_SetError("Pausing the device", ret);
slouken@8972
  1163
    }
slouken@8972
  1164
    return 0;
slouken@8972
  1165
}
slouken@8972
  1166
slouken@8972
  1167
int
slouken@8972
  1168
SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
slouken@8972
  1169
{
slouken@8972
  1170
    HRESULT ret;
slouken@8972
  1171
slouken@8972
  1172
    /* Unpause the device. */
slouken@8972
  1173
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1174
        DISFFC_CONTINUE);
slouken@8972
  1175
    if (FAILED(ret)) {
slouken@8972
  1176
        return DI_SetError("Pausing the device", ret);
slouken@8972
  1177
    }
slouken@8972
  1178
    return 0;
slouken@8972
  1179
}
slouken@8972
  1180
slouken@8972
  1181
int
slouken@8972
  1182
SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
slouken@8972
  1183
{
slouken@8972
  1184
    HRESULT ret;
slouken@8972
  1185
slouken@8972
  1186
    /* Try to stop the effects. */
slouken@8972
  1187
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1188
        DISFFC_STOPALL);
slouken@8972
  1189
    if (FAILED(ret)) {
slouken@8972
  1190
        return DI_SetError("Stopping the device", ret);
slouken@8972
  1191
    }
slouken@8972
  1192
    return 0;
slouken@8972
  1193
}
slouken@8972
  1194
slouken@8972
  1195
#else /* !SDL_HAPTIC_DINPUT */
slouken@8972
  1196
icculus@9661
  1197
typedef struct DIDEVICEINSTANCE DIDEVICEINSTANCE;
icculus@9663
  1198
typedef struct SDL_hapticlist_item SDL_hapticlist_item;
icculus@9661
  1199
slouken@8972
  1200
int
slouken@8972
  1201
SDL_DINPUT_HapticInit(void)
slouken@8972
  1202
{
slouken@8972
  1203
    return 0;
slouken@8972
  1204
}
slouken@8972
  1205
slouken@8972
  1206
int
slouken@8972
  1207
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
  1208
{
slouken@8972
  1209
    return SDL_Unsupported();
slouken@8972
  1210
}
slouken@8972
  1211
slouken@8972
  1212
int
slouken@8972
  1213
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
  1214
{
slouken@8972
  1215
    return SDL_Unsupported();
slouken@8972
  1216
}
slouken@8972
  1217
slouken@8972
  1218
int
slouken@8972
  1219
SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
slouken@8972
  1220
{
slouken@8972
  1221
    return SDL_Unsupported();
slouken@8972
  1222
}
slouken@8972
  1223
slouken@8972
  1224
int
slouken@8972
  1225
SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
  1226
{
slouken@8972
  1227
    return SDL_Unsupported();
slouken@8972
  1228
}
slouken@8972
  1229
slouken@8972
  1230
int
slouken@8972
  1231
SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
  1232
{
slouken@8972
  1233
    return SDL_Unsupported();
slouken@8972
  1234
}
slouken@8972
  1235
slouken@8972
  1236
void
slouken@8972
  1237
SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
slouken@8972
  1238
{
slouken@8972
  1239
}
slouken@8972
  1240
slouken@8972
  1241
void
slouken@8972
  1242
SDL_DINPUT_HapticQuit(void)
slouken@8972
  1243
{
slouken@8972
  1244
}
slouken@8972
  1245
slouken@8972
  1246
int
slouken@8972
  1247
SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
slouken@8972
  1248
{
slouken@8972
  1249
    return SDL_Unsupported();
slouken@8972
  1250
}
slouken@8972
  1251
slouken@8972
  1252
int
slouken@8972
  1253
SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
slouken@8972
  1254
{
slouken@8972
  1255
    return SDL_Unsupported();
slouken@8972
  1256
}
slouken@8972
  1257
slouken@8972
  1258
int
slouken@8972
  1259
SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
slouken@8972
  1260
{
slouken@8972
  1261
    return SDL_Unsupported();
slouken@8972
  1262
}
slouken@8972
  1263
slouken@8972
  1264
int
slouken@8972
  1265
SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1266
{
slouken@8972
  1267
    return SDL_Unsupported();
slouken@8972
  1268
}
slouken@8972
  1269
slouken@8972
  1270
void
slouken@8972
  1271
SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1272
{
slouken@8972
  1273
}
slouken@8972
  1274
slouken@8972
  1275
int
slouken@8972
  1276
SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1277
{
slouken@8972
  1278
    return SDL_Unsupported();
slouken@8972
  1279
}
slouken@8972
  1280
slouken@8972
  1281
int
slouken@8972
  1282
SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@8972
  1283
{
slouken@8972
  1284
    return SDL_Unsupported();
slouken@8972
  1285
}
slouken@8972
  1286
slouken@8972
  1287
int
slouken@8972
  1288
SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@8972
  1289
{
slouken@8972
  1290
    return SDL_Unsupported();
slouken@8972
  1291
}
slouken@8972
  1292
slouken@8972
  1293
int
slouken@8972
  1294
SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
slouken@8972
  1295
{
slouken@8972
  1296
    return SDL_Unsupported();
slouken@8972
  1297
}
slouken@8972
  1298
slouken@8972
  1299
int
slouken@8972
  1300
SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
slouken@8972
  1301
{
slouken@8972
  1302
    return SDL_Unsupported();
slouken@8972
  1303
}
slouken@8972
  1304
slouken@8972
  1305
int
slouken@8972
  1306
SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
slouken@8972
  1307
{
slouken@8972
  1308
    return SDL_Unsupported();
slouken@8972
  1309
}
slouken@8972
  1310
slouken@8972
  1311
#endif /* SDL_HAPTIC_DINPUT */
slouken@8972
  1312
slouken@8972
  1313
/* vi: set ts=4 sw=4 expandtab: */