src/haptic/windows/SDL_dinputhaptic.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 17 Sep 2014 14:49:36 -0400
changeset 9147 6bf589c8d549
parent 9071 8e04e17c7af3
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Haptic: Deal with negative periodic magnitudes (thanks, Elias!).

A negative periodic magnitude doesn't exist in Windows' and MacOS' FF APIs

The periodic magnitude parameter of the SDL Haptic API is based on the Linux
FF API, so it means they are not directly compatible:
'dwMagnitude' is a 'DWORD', which is unsigned.

Fixes Bugzilla #2701.
slouken@8972
     1
/*
slouken@8972
     2
  Simple DirectMedia Layer
slouken@8972
     3
  Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
slouken@8972
     4
slouken@8972
     5
  This software is provided 'as-is', without any express or implied
slouken@8972
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@8972
     7
  arising from the use of this software.
slouken@8972
     8
slouken@8972
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@8972
    10
  including commercial applications, and to alter it and redistribute it
slouken@8972
    11
  freely, subject to the following restrictions:
slouken@8972
    12
slouken@8972
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@8972
    14
     claim that you wrote the original software. If you use this software
slouken@8972
    15
     in a product, an acknowledgment in the product documentation would be
slouken@8972
    16
     appreciated but is not required.
slouken@8972
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@8972
    18
     misrepresented as being the original software.
slouken@8972
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@8972
    20
*/
slouken@8972
    21
#include "../../SDL_internal.h"
slouken@8972
    22
slouken@8972
    23
#include "SDL_error.h"
icculus@9147
    24
#include "SDL_stdinc.h"
slouken@8972
    25
#include "SDL_haptic.h"
slouken@8972
    26
#include "SDL_timer.h"
slouken@8972
    27
#include "SDL_windowshaptic_c.h"
slouken@8972
    28
#include "SDL_dinputhaptic_c.h"
slouken@8972
    29
#include "../SDL_syshaptic.h"
slouken@8972
    30
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
slouken@8972
    31
slouken@8972
    32
slouken@8972
    33
#if SDL_HAPTIC_DINPUT
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
 * Checks to see if two GUID are the same.
slouken@8972
    63
 */
slouken@8972
    64
static int
slouken@8972
    65
DI_GUIDIsSame(const GUID * a, const GUID * b)
slouken@8972
    66
{
slouken@8972
    67
    return (SDL_memcmp(a, b, sizeof (GUID)) == 0);
slouken@8972
    68
}
slouken@8972
    69
slouken@8972
    70
/*
slouken@8972
    71
 * Callback to find the haptic devices.
slouken@8972
    72
 */
slouken@8972
    73
static BOOL CALLBACK
slouken@8972
    74
EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext)
slouken@8972
    75
{
slouken@8972
    76
    (void) pContext;
slouken@8972
    77
    SDL_DINPUT_MaybeAddDevice(pdidInstance);
slouken@8972
    78
    return DIENUM_CONTINUE;  /* continue enumerating */
slouken@8972
    79
}
slouken@8972
    80
slouken@8972
    81
int
slouken@8972
    82
SDL_DINPUT_HapticInit(void)
slouken@8972
    83
{
slouken@8972
    84
    HRESULT ret;
slouken@8972
    85
    HINSTANCE instance;
slouken@8972
    86
slouken@8972
    87
    if (dinput != NULL) {       /* Already open. */
slouken@8972
    88
        return SDL_SetError("Haptic: SubSystem already open.");
slouken@8972
    89
    }
slouken@8972
    90
slouken@8972
    91
    ret = WIN_CoInitialize();
slouken@8972
    92
    if (FAILED(ret)) {
slouken@8972
    93
        return DI_SetError("Coinitialize", ret);
slouken@8972
    94
    }
slouken@8972
    95
slouken@8972
    96
    coinitialized = SDL_TRUE;
slouken@8972
    97
slouken@8972
    98
    ret = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER,
slouken@8972
    99
        &IID_IDirectInput8, (LPVOID)& dinput);
slouken@8972
   100
    if (FAILED(ret)) {
slouken@8972
   101
        SDL_SYS_HapticQuit();
slouken@8972
   102
        return DI_SetError("CoCreateInstance", ret);
slouken@8972
   103
    }
slouken@8972
   104
slouken@8972
   105
    /* Because we used CoCreateInstance, we need to Initialize it, first. */
slouken@8972
   106
    instance = GetModuleHandle(NULL);
slouken@8972
   107
    if (instance == NULL) {
slouken@8972
   108
        SDL_SYS_HapticQuit();
slouken@8976
   109
        return SDL_SetError("GetModuleHandle() failed with error code %lu.",
slouken@8972
   110
            GetLastError());
slouken@8972
   111
    }
slouken@8972
   112
    ret = IDirectInput8_Initialize(dinput, instance, DIRECTINPUT_VERSION);
slouken@8972
   113
    if (FAILED(ret)) {
slouken@8972
   114
        SDL_SYS_HapticQuit();
slouken@8972
   115
        return DI_SetError("Initializing DirectInput device", ret);
slouken@8972
   116
    }
slouken@8972
   117
slouken@8972
   118
    /* Look for haptic devices. */
slouken@8972
   119
    ret = IDirectInput8_EnumDevices(dinput,
slouken@8972
   120
        0,
slouken@8972
   121
        EnumHapticsCallback,
slouken@8972
   122
        NULL,
slouken@8972
   123
        DIEDFL_FORCEFEEDBACK |
slouken@8972
   124
        DIEDFL_ATTACHEDONLY);
slouken@8972
   125
    if (FAILED(ret)) {
slouken@8972
   126
        SDL_SYS_HapticQuit();
slouken@8972
   127
        return DI_SetError("Enumerating DirectInput devices", ret);
slouken@8972
   128
    }
slouken@8972
   129
    return 0;
slouken@8972
   130
}
slouken@8972
   131
slouken@8972
   132
int
slouken@8972
   133
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
   134
{
slouken@8972
   135
    HRESULT ret;
slouken@8972
   136
    LPDIRECTINPUTDEVICE8 device;
slouken@8972
   137
    const DWORD needflags = DIDC_ATTACHED | DIDC_FORCEFEEDBACK;
slouken@8972
   138
    DIDEVCAPS capabilities;
slouken@8972
   139
    SDL_hapticlist_item *item = NULL;
slouken@8972
   140
slouken@8972
   141
    if (dinput == NULL) {
slouken@8972
   142
        return -1;  /* not initialized. We'll pick these up on enumeration if we init later. */
slouken@8972
   143
    }
slouken@8972
   144
slouken@8972
   145
    /* Make sure we don't already have it */
slouken@8972
   146
    for (item = SDL_hapticlist; item; item = item->next) {
slouken@8972
   147
        if ((!item->bXInputHaptic) && (SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0)) {
slouken@8972
   148
            return -1;  /* Already added */
slouken@8972
   149
        }
slouken@8972
   150
    }
slouken@8972
   151
slouken@8972
   152
    /* Open the device */
slouken@8972
   153
    ret = IDirectInput8_CreateDevice(dinput, &pdidInstance->guidInstance, &device, NULL);
slouken@8972
   154
    if (FAILED(ret)) {
slouken@8972
   155
        /* DI_SetError("Creating DirectInput device",ret); */
slouken@8972
   156
        return -1;
slouken@8972
   157
    }
slouken@8972
   158
slouken@8972
   159
    /* Get capabilities. */
slouken@8972
   160
    SDL_zero(capabilities);
slouken@8972
   161
    capabilities.dwSize = sizeof(DIDEVCAPS);
slouken@8972
   162
    ret = IDirectInputDevice8_GetCapabilities(device, &capabilities);
slouken@8972
   163
    IDirectInputDevice8_Release(device);
slouken@8972
   164
    if (FAILED(ret)) {
slouken@8972
   165
        /* DI_SetError("Getting device capabilities",ret); */
slouken@8972
   166
        return -1;
slouken@8972
   167
    }
slouken@8972
   168
slouken@8972
   169
    if ((capabilities.dwFlags & needflags) != needflags) {
slouken@8972
   170
        return -1;  /* not a device we can use. */
slouken@8972
   171
    }
slouken@8972
   172
slouken@8972
   173
    item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item));
slouken@8972
   174
    if (item == NULL) {
slouken@8972
   175
        return SDL_OutOfMemory();
slouken@8972
   176
    }
slouken@8972
   177
slouken@8972
   178
    item->name = WIN_StringToUTF8(pdidInstance->tszProductName);
slouken@8972
   179
    if (!item->name) {
slouken@8972
   180
        SDL_free(item);
slouken@8972
   181
        return -1;
slouken@8972
   182
    }
slouken@8972
   183
slouken@8972
   184
    /* Copy the instance over, useful for creating devices. */
slouken@8972
   185
    SDL_memcpy(&item->instance, pdidInstance, sizeof(DIDEVICEINSTANCE));
slouken@8972
   186
    SDL_memcpy(&item->capabilities, &capabilities, sizeof(capabilities));
slouken@8972
   187
slouken@8972
   188
    return SDL_SYS_AddHapticDevice(item);
slouken@8972
   189
}
slouken@8972
   190
slouken@8972
   191
int
slouken@8972
   192
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
   193
{
slouken@8972
   194
    SDL_hapticlist_item *item;
slouken@8972
   195
    SDL_hapticlist_item *prev = NULL;
slouken@8972
   196
slouken@8972
   197
    if (dinput == NULL) {
slouken@8972
   198
        return -1;  /* not initialized, ignore this. */
slouken@8972
   199
    }
slouken@8972
   200
slouken@8972
   201
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
slouken@8972
   202
        if (!item->bXInputHaptic && SDL_memcmp(&item->instance, pdidInstance, sizeof(*pdidInstance)) == 0) {
slouken@8972
   203
            /* found it, remove it. */
slouken@8972
   204
            return SDL_SYS_RemoveHapticDevice(prev, item);
slouken@8972
   205
        }
slouken@8972
   206
        prev = item;
slouken@8972
   207
    }
slouken@8972
   208
    return -1;
slouken@8972
   209
}
slouken@8972
   210
slouken@8972
   211
/*
slouken@8972
   212
 * Callback to get supported axes.
slouken@8972
   213
 */
slouken@8972
   214
static BOOL CALLBACK
slouken@8972
   215
DI_DeviceObjectCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef)
slouken@8972
   216
{
slouken@8972
   217
    SDL_Haptic *haptic = (SDL_Haptic *) pvRef;
slouken@8972
   218
slouken@8972
   219
    if ((dev->dwType & DIDFT_AXIS) && (dev->dwFlags & DIDOI_FFACTUATOR)) {
slouken@8972
   220
        const GUID *guid = &dev->guidType;
slouken@8972
   221
        DWORD offset = 0;
slouken@8972
   222
        if (DI_GUIDIsSame(guid, &GUID_XAxis)) {
slouken@8972
   223
            offset = DIJOFS_X;
slouken@8972
   224
        } else if (DI_GUIDIsSame(guid, &GUID_YAxis)) {
slouken@8972
   225
            offset = DIJOFS_Y;
slouken@8972
   226
        } else if (DI_GUIDIsSame(guid, &GUID_ZAxis)) {
slouken@8972
   227
            offset = DIJOFS_Z;
slouken@8972
   228
        } else if (DI_GUIDIsSame(guid, &GUID_RxAxis)) {
slouken@8972
   229
            offset = DIJOFS_RX;
slouken@8972
   230
        } else if (DI_GUIDIsSame(guid, &GUID_RyAxis)) {
slouken@8972
   231
            offset = DIJOFS_RY;
slouken@8972
   232
        } else if (DI_GUIDIsSame(guid, &GUID_RzAxis)) {
slouken@8972
   233
            offset = DIJOFS_RZ;
slouken@8972
   234
        } else {
slouken@8972
   235
            return DIENUM_CONTINUE;   /* can't use this, go on. */
slouken@8972
   236
        }
slouken@8972
   237
slouken@8972
   238
        haptic->hwdata->axes[haptic->naxes] = offset;
slouken@8972
   239
        haptic->naxes++;
slouken@8972
   240
slouken@8972
   241
        /* Currently using the artificial limit of 3 axes. */
slouken@8972
   242
        if (haptic->naxes >= 3) {
slouken@8972
   243
            return DIENUM_STOP;
slouken@8972
   244
        }
slouken@8972
   245
    }
slouken@8972
   246
slouken@8972
   247
    return DIENUM_CONTINUE;
slouken@8972
   248
}
slouken@8972
   249
slouken@8972
   250
/*
slouken@8972
   251
 * Callback to get all supported effects.
slouken@8972
   252
 */
slouken@8972
   253
#define EFFECT_TEST(e,s)               \
slouken@8972
   254
if (DI_GUIDIsSame(&pei->guid, &(e)))   \
slouken@8972
   255
   haptic->supported |= (s)
slouken@8972
   256
static BOOL CALLBACK
slouken@8972
   257
DI_EffectCallback(LPCDIEFFECTINFO pei, LPVOID pv)
slouken@8972
   258
{
slouken@8972
   259
    /* Prepare the haptic device. */
slouken@8972
   260
    SDL_Haptic *haptic = (SDL_Haptic *) pv;
slouken@8972
   261
slouken@8972
   262
    /* Get supported. */
slouken@8972
   263
    EFFECT_TEST(GUID_Spring, SDL_HAPTIC_SPRING);
slouken@8972
   264
    EFFECT_TEST(GUID_Damper, SDL_HAPTIC_DAMPER);
slouken@8972
   265
    EFFECT_TEST(GUID_Inertia, SDL_HAPTIC_INERTIA);
slouken@8972
   266
    EFFECT_TEST(GUID_Friction, SDL_HAPTIC_FRICTION);
slouken@8972
   267
    EFFECT_TEST(GUID_ConstantForce, SDL_HAPTIC_CONSTANT);
slouken@8972
   268
    EFFECT_TEST(GUID_CustomForce, SDL_HAPTIC_CUSTOM);
slouken@8972
   269
    EFFECT_TEST(GUID_Sine, SDL_HAPTIC_SINE);
slouken@8972
   270
    /* !!! FIXME: put this back when we have more bits in 2.1 */
slouken@8972
   271
    /* EFFECT_TEST(GUID_Square, SDL_HAPTIC_SQUARE); */
slouken@8972
   272
    EFFECT_TEST(GUID_Triangle, SDL_HAPTIC_TRIANGLE);
slouken@8972
   273
    EFFECT_TEST(GUID_SawtoothUp, SDL_HAPTIC_SAWTOOTHUP);
slouken@8972
   274
    EFFECT_TEST(GUID_SawtoothDown, SDL_HAPTIC_SAWTOOTHDOWN);
slouken@8972
   275
    EFFECT_TEST(GUID_RampForce, SDL_HAPTIC_RAMP);
slouken@8972
   276
slouken@8972
   277
    /* Check for more. */
slouken@8972
   278
    return DIENUM_CONTINUE;
slouken@8972
   279
}
slouken@8972
   280
slouken@8972
   281
/*
slouken@8972
   282
 * Opens the haptic device.
slouken@8972
   283
 *
slouken@8972
   284
 *    Steps:
slouken@8972
   285
 *       - Set cooperative level.
slouken@8972
   286
 *       - Set data format.
slouken@8972
   287
 *       - Acquire exclusiveness.
slouken@8972
   288
 *       - Reset actuators.
slouken@8972
   289
 *       - Get supported features.
slouken@8972
   290
 */
slouken@8972
   291
static int
slouken@8972
   292
SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device8, SDL_bool is_joystick)
slouken@8972
   293
{
slouken@8972
   294
    HRESULT ret;
slouken@8972
   295
    DIPROPDWORD dipdw;
slouken@8972
   296
slouken@8972
   297
    /* Allocate the hwdata */
slouken@8972
   298
    haptic->hwdata = (struct haptic_hwdata *)SDL_malloc(sizeof(*haptic->hwdata));
slouken@8972
   299
    if (haptic->hwdata == NULL) {
slouken@8972
   300
        return SDL_OutOfMemory();
slouken@8972
   301
    }
slouken@8972
   302
    SDL_memset(haptic->hwdata, 0, sizeof(*haptic->hwdata));
slouken@8972
   303
slouken@8972
   304
    /* We'll use the device8 from now on. */
slouken@8972
   305
    haptic->hwdata->device = device8;
slouken@8972
   306
    haptic->hwdata->is_joystick = is_joystick;
slouken@8972
   307
slouken@8972
   308
    /* !!! FIXME: opening a haptic device here first will make an attempt to
slouken@8972
   309
       !!! FIXME:  SDL_JoystickOpen() that same device fail later, since we
slouken@8972
   310
       !!! FIXME:  have it open in exclusive mode. But this will allow
slouken@8972
   311
       !!! FIXME:  SDL_JoystickOpen() followed by SDL_HapticOpenFromJoystick()
slouken@8972
   312
       !!! FIXME:  to work, and that's probably the common case. Still,
slouken@8972
   313
       !!! FIXME:  ideally, We need to unify the opening code. */
slouken@8972
   314
slouken@8972
   315
    if (!is_joystick) {  /* if is_joystick, we already set this up elsewhere. */
slouken@8972
   316
        /* Grab it exclusively to use force feedback stuff. */
slouken@8972
   317
        ret = IDirectInputDevice8_SetCooperativeLevel(haptic->hwdata->device,
slouken@8972
   318
                                                      SDL_HelperWindow,
slouken@8972
   319
                                                      DISCL_EXCLUSIVE |
slouken@8972
   320
                                                      DISCL_BACKGROUND);
slouken@8972
   321
        if (FAILED(ret)) {
slouken@8972
   322
            DI_SetError("Setting cooperative level to exclusive", ret);
slouken@8972
   323
            goto acquire_err;
slouken@8972
   324
        }
slouken@8972
   325
slouken@8972
   326
        /* Set data format. */
slouken@8972
   327
        ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
slouken@8972
   328
                                                &c_dfDIJoystick2);
slouken@8972
   329
        if (FAILED(ret)) {
slouken@8972
   330
            DI_SetError("Setting data format", ret);
slouken@8972
   331
            goto acquire_err;
slouken@8972
   332
        }
slouken@8972
   333
slouken@8972
   334
        /* Get number of axes. */
slouken@8972
   335
        ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
slouken@8972
   336
                                              DI_DeviceObjectCallback,
slouken@8972
   337
                                              haptic, DIDFT_AXIS);
slouken@8972
   338
        if (FAILED(ret)) {
slouken@8972
   339
            DI_SetError("Getting device axes", ret);
slouken@8972
   340
            goto acquire_err;
slouken@8972
   341
        }
slouken@8972
   342
slouken@8972
   343
        /* Acquire the device. */
slouken@8972
   344
        ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
slouken@8972
   345
        if (FAILED(ret)) {
slouken@8972
   346
            DI_SetError("Acquiring DirectInput device", ret);
slouken@8972
   347
            goto acquire_err;
slouken@8972
   348
        }
slouken@8972
   349
    }
slouken@8972
   350
slouken@8972
   351
    /* Reset all actuators - just in case. */
slouken@8972
   352
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
   353
                                                       DISFFC_RESET);
slouken@8972
   354
    if (FAILED(ret)) {
slouken@8972
   355
        DI_SetError("Resetting device", ret);
slouken@8972
   356
        goto acquire_err;
slouken@8972
   357
    }
slouken@8972
   358
slouken@8972
   359
    /* Enabling actuators. */
slouken@8972
   360
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
   361
                                                       DISFFC_SETACTUATORSON);
slouken@8972
   362
    if (FAILED(ret)) {
slouken@8972
   363
        DI_SetError("Enabling actuators", ret);
slouken@8972
   364
        goto acquire_err;
slouken@8972
   365
    }
slouken@8972
   366
slouken@8972
   367
    /* Get supported effects. */
slouken@8972
   368
    ret = IDirectInputDevice8_EnumEffects(haptic->hwdata->device,
slouken@8972
   369
                                          DI_EffectCallback, haptic,
slouken@8972
   370
                                          DIEFT_ALL);
slouken@8972
   371
    if (FAILED(ret)) {
slouken@8972
   372
        DI_SetError("Enumerating supported effects", ret);
slouken@8972
   373
        goto acquire_err;
slouken@8972
   374
    }
slouken@8972
   375
    if (haptic->supported == 0) {       /* Error since device supports nothing. */
slouken@8972
   376
        SDL_SetError("Haptic: Internal error on finding supported effects.");
slouken@8972
   377
        goto acquire_err;
slouken@8972
   378
    }
slouken@8972
   379
slouken@8972
   380
    /* Check autogain and autocenter. */
slouken@8972
   381
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
   382
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
   383
    dipdw.diph.dwObj = 0;
slouken@8972
   384
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   385
    dipdw.dwData = 10000;
slouken@8972
   386
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
   387
                                          DIPROP_FFGAIN, &dipdw.diph);
slouken@8972
   388
    if (!FAILED(ret)) {         /* Gain is supported. */
slouken@8972
   389
        haptic->supported |= SDL_HAPTIC_GAIN;
slouken@8972
   390
    }
slouken@8972
   391
    dipdw.diph.dwObj = 0;
slouken@8972
   392
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
   393
    dipdw.dwData = DIPROPAUTOCENTER_OFF;
slouken@8972
   394
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
   395
                                          DIPROP_AUTOCENTER, &dipdw.diph);
slouken@8972
   396
    if (!FAILED(ret)) {         /* Autocenter is supported. */
slouken@8972
   397
        haptic->supported |= SDL_HAPTIC_AUTOCENTER;
slouken@8972
   398
    }
slouken@8972
   399
slouken@8972
   400
    /* Status is always supported. */
slouken@8972
   401
    haptic->supported |= SDL_HAPTIC_STATUS | SDL_HAPTIC_PAUSE;
slouken@8972
   402
slouken@8972
   403
    /* Check maximum effects. */
slouken@8972
   404
    haptic->neffects = 128;     /* This is not actually supported as thus under windows,
slouken@8972
   405
                                   there is no way to tell the number of EFFECTS that a
slouken@8972
   406
                                   device can hold, so we'll just use a "random" number
slouken@8972
   407
                                   instead and put warnings in SDL_haptic.h */
slouken@8972
   408
    haptic->nplaying = 128;     /* Even more impossible to get this then neffects. */
slouken@8972
   409
slouken@8972
   410
    /* Prepare effects memory. */
slouken@8972
   411
    haptic->effects = (struct haptic_effect *)
slouken@8972
   412
        SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects);
slouken@8972
   413
    if (haptic->effects == NULL) {
slouken@8972
   414
        SDL_OutOfMemory();
slouken@8972
   415
        goto acquire_err;
slouken@8972
   416
    }
slouken@8972
   417
    /* Clear the memory */
slouken@8972
   418
    SDL_memset(haptic->effects, 0,
slouken@8972
   419
               sizeof(struct haptic_effect) * haptic->neffects);
slouken@8972
   420
slouken@8972
   421
    return 0;
slouken@8972
   422
slouken@8972
   423
    /* Error handling */
slouken@8972
   424
  acquire_err:
slouken@8972
   425
    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
slouken@8972
   426
    return -1;
slouken@8972
   427
}
slouken@8972
   428
slouken@8972
   429
int
slouken@8972
   430
SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
slouken@8972
   431
{
slouken@8972
   432
    HRESULT ret;
slouken@8972
   433
    LPDIRECTINPUTDEVICE8 device;
slouken@8972
   434
    LPDIRECTINPUTDEVICE8 device8;
slouken@8972
   435
slouken@8972
   436
    /* Open the device */
slouken@8972
   437
    ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance,
slouken@8972
   438
        &device, NULL);
slouken@8972
   439
    if (FAILED(ret)) {
slouken@8972
   440
        DI_SetError("Creating DirectInput device", ret);
slouken@8972
   441
        return -1;
slouken@8972
   442
    }
slouken@8972
   443
slouken@8972
   444
    /* Now get the IDirectInputDevice8 interface, instead. */
slouken@8972
   445
    ret = IDirectInputDevice8_QueryInterface(device,
slouken@8972
   446
        &IID_IDirectInputDevice8,
slouken@8972
   447
        (LPVOID *)&device8);
slouken@8972
   448
    /* Done with the temporary one now. */
slouken@8972
   449
    IDirectInputDevice8_Release(device);
slouken@8972
   450
    if (FAILED(ret)) {
slouken@8972
   451
        DI_SetError("Querying DirectInput interface", ret);
slouken@8972
   452
        return -1;
slouken@8972
   453
    }
slouken@8972
   454
slouken@8972
   455
    if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) {
slouken@8972
   456
        IDirectInputDevice8_Release(device8);
slouken@8972
   457
        return -1;
slouken@8972
   458
    }
slouken@8972
   459
    return 0;
slouken@8972
   460
}
slouken@8972
   461
slouken@8972
   462
int
slouken@8972
   463
SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
   464
{
slouken@8972
   465
    HRESULT ret;
slouken@8972
   466
    DIDEVICEINSTANCE hap_instance, joy_instance;
slouken@8972
   467
slouken@8972
   468
    hap_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   469
    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   470
slouken@8972
   471
    /* Get the device instances. */
slouken@8972
   472
    ret = IDirectInputDevice8_GetDeviceInfo(haptic->hwdata->device,
slouken@8972
   473
        &hap_instance);
slouken@8972
   474
    if (FAILED(ret)) {
slouken@8972
   475
        return 0;
slouken@8972
   476
    }
slouken@8972
   477
    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice,
slouken@8972
   478
        &joy_instance);
slouken@8972
   479
    if (FAILED(ret)) {
slouken@8972
   480
        return 0;
slouken@8972
   481
    }
slouken@8972
   482
slouken@8972
   483
    return DI_GUIDIsSame(&hap_instance.guidInstance, &joy_instance.guidInstance);
slouken@8972
   484
}
slouken@8972
   485
slouken@8972
   486
int
slouken@8972
   487
SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
   488
{
slouken@8972
   489
    SDL_hapticlist_item *item;
slouken@8972
   490
    int index = 0;
slouken@8972
   491
    HRESULT ret;
slouken@8972
   492
    DIDEVICEINSTANCE joy_instance;
slouken@8972
   493
slouken@8972
   494
    joy_instance.dwSize = sizeof(DIDEVICEINSTANCE);
slouken@8972
   495
    ret = IDirectInputDevice8_GetDeviceInfo(joystick->hwdata->InputDevice, &joy_instance);
slouken@8972
   496
    if (FAILED(ret)) {
slouken@8972
   497
        return -1;
slouken@8972
   498
    }
slouken@8972
   499
slouken@8972
   500
    /* Since it comes from a joystick we have to try to match it with a haptic device on our haptic list. */
slouken@8972
   501
    for (item = SDL_hapticlist; item != NULL; item = item->next) {
slouken@8972
   502
        if (!item->bXInputHaptic && DI_GUIDIsSame(&item->instance.guidInstance, &joy_instance.guidInstance)) {
slouken@8972
   503
            haptic->index = index;
slouken@8972
   504
            return SDL_DINPUT_HapticOpenFromDevice(haptic, joystick->hwdata->InputDevice, SDL_TRUE);
slouken@8972
   505
        }
slouken@8972
   506
        ++index;
slouken@8972
   507
    }
slouken@8972
   508
slouken@8972
   509
    SDL_SetError("Couldn't find joystick in haptic device list");
slouken@8972
   510
    return -1;
slouken@8972
   511
}
slouken@8972
   512
slouken@8972
   513
void
slouken@8972
   514
SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
slouken@8972
   515
{
slouken@8972
   516
    IDirectInputDevice8_Unacquire(haptic->hwdata->device);
slouken@8972
   517
slouken@8972
   518
    /* Only release if isn't grabbed by a joystick. */
slouken@8972
   519
    if (haptic->hwdata->is_joystick == 0) {
slouken@8972
   520
        IDirectInputDevice8_Release(haptic->hwdata->device);
slouken@8972
   521
    }
slouken@8972
   522
}
slouken@8972
   523
slouken@8972
   524
void
slouken@8972
   525
SDL_DINPUT_HapticQuit(void)
slouken@8972
   526
{
slouken@8972
   527
    if (dinput != NULL) {
slouken@8972
   528
        IDirectInput8_Release(dinput);
slouken@8972
   529
        dinput = NULL;
slouken@8972
   530
    }
slouken@8972
   531
slouken@8972
   532
    if (coinitialized) {
slouken@8972
   533
        WIN_CoUninitialize();
slouken@8972
   534
        coinitialized = SDL_FALSE;
slouken@8972
   535
    }
slouken@8972
   536
}
slouken@8972
   537
slouken@8972
   538
/*
slouken@8972
   539
 * Converts an SDL trigger button to an DIEFFECT trigger button.
slouken@8972
   540
 */
slouken@8972
   541
static DWORD
slouken@8972
   542
DIGetTriggerButton(Uint16 button)
slouken@8972
   543
{
slouken@8972
   544
    DWORD dwTriggerButton;
slouken@8972
   545
slouken@8972
   546
    dwTriggerButton = DIEB_NOTRIGGER;
slouken@8972
   547
slouken@8972
   548
    if (button != 0) {
slouken@8972
   549
        dwTriggerButton = DIJOFS_BUTTON(button - 1);
slouken@8972
   550
    }
slouken@8972
   551
slouken@8972
   552
    return dwTriggerButton;
slouken@8972
   553
}
slouken@8972
   554
slouken@8972
   555
slouken@8972
   556
/*
slouken@8972
   557
 * Sets the direction.
slouken@8972
   558
 */
slouken@8972
   559
static int
slouken@8972
   560
SDL_SYS_SetDirection(DIEFFECT * effect, SDL_HapticDirection * dir, int naxes)
slouken@8972
   561
{
slouken@8972
   562
    LONG *rglDir;
slouken@8972
   563
slouken@8972
   564
    /* Handle no axes a part. */
slouken@8972
   565
    if (naxes == 0) {
slouken@8972
   566
        effect->dwFlags |= DIEFF_SPHERICAL;     /* Set as default. */
slouken@8972
   567
        effect->rglDirection = NULL;
slouken@8972
   568
        return 0;
slouken@8972
   569
    }
slouken@8972
   570
slouken@8972
   571
    /* Has axes. */
slouken@8972
   572
    rglDir = SDL_malloc(sizeof(LONG) * naxes);
slouken@8972
   573
    if (rglDir == NULL) {
slouken@8972
   574
        return SDL_OutOfMemory();
slouken@8972
   575
    }
slouken@8972
   576
    SDL_memset(rglDir, 0, sizeof(LONG) * naxes);
slouken@8972
   577
    effect->rglDirection = rglDir;
slouken@8972
   578
slouken@8972
   579
    switch (dir->type) {
slouken@8972
   580
    case SDL_HAPTIC_POLAR:
slouken@8972
   581
        effect->dwFlags |= DIEFF_POLAR;
slouken@8972
   582
        rglDir[0] = dir->dir[0];
slouken@8972
   583
        return 0;
slouken@8972
   584
    case SDL_HAPTIC_CARTESIAN:
slouken@8972
   585
        effect->dwFlags |= DIEFF_CARTESIAN;
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@8972
   592
    case SDL_HAPTIC_SPHERICAL:
slouken@8972
   593
        effect->dwFlags |= DIEFF_SPHERICAL;
slouken@8972
   594
        rglDir[0] = dir->dir[0];
slouken@8972
   595
        if (naxes > 1)
slouken@8972
   596
            rglDir[1] = dir->dir[1];
slouken@8972
   597
        if (naxes > 2)
slouken@8972
   598
            rglDir[2] = dir->dir[2];
slouken@8972
   599
        return 0;
slouken@8972
   600
slouken@8972
   601
    default:
slouken@8972
   602
        return SDL_SetError("Haptic: Unknown direction type.");
slouken@8972
   603
    }
slouken@8972
   604
}
slouken@8972
   605
icculus@9071
   606
/* Clamps and converts. */
icculus@9071
   607
#define CCONVERT(x)   (((x) > 0x7FFF) ? 10000 : ((x)*10000) / 0x7FFF)
icculus@9071
   608
/* Just converts. */
icculus@9071
   609
#define CONVERT(x)    (((x)*10000) / 0x7FFF)
slouken@8972
   610
/*
slouken@8972
   611
 * Creates the DIEFFECT from a SDL_HapticEffect.
slouken@8972
   612
 */
slouken@8972
   613
static int
slouken@8972
   614
SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest,
slouken@8972
   615
                   SDL_HapticEffect * src)
slouken@8972
   616
{
slouken@8972
   617
    int i;
slouken@8972
   618
    DICONSTANTFORCE *constant;
slouken@8972
   619
    DIPERIODIC *periodic;
slouken@8972
   620
    DICONDITION *condition;     /* Actually an array of conditions - one per axis. */
slouken@8972
   621
    DIRAMPFORCE *ramp;
slouken@8972
   622
    DICUSTOMFORCE *custom;
slouken@8972
   623
    DIENVELOPE *envelope;
slouken@8972
   624
    SDL_HapticConstant *hap_constant;
slouken@8972
   625
    SDL_HapticPeriodic *hap_periodic;
slouken@8972
   626
    SDL_HapticCondition *hap_condition;
slouken@8972
   627
    SDL_HapticRamp *hap_ramp;
slouken@8972
   628
    SDL_HapticCustom *hap_custom;
slouken@8972
   629
    DWORD *axes;
slouken@8972
   630
slouken@8972
   631
    /* Set global stuff. */
slouken@8972
   632
    SDL_memset(dest, 0, sizeof(DIEFFECT));
slouken@8972
   633
    dest->dwSize = sizeof(DIEFFECT);    /* Set the structure size. */
slouken@8972
   634
    dest->dwSamplePeriod = 0;   /* Not used by us. */
slouken@8972
   635
    dest->dwGain = 10000;       /* Gain is set globally, not locally. */
slouken@8972
   636
    dest->dwFlags = DIEFF_OBJECTOFFSETS;        /* Seems obligatory. */
slouken@8972
   637
slouken@8972
   638
    /* Envelope. */
slouken@8972
   639
    envelope = SDL_malloc(sizeof(DIENVELOPE));
slouken@8972
   640
    if (envelope == NULL) {
slouken@8972
   641
        return SDL_OutOfMemory();
slouken@8972
   642
    }
slouken@8972
   643
    SDL_memset(envelope, 0, sizeof(DIENVELOPE));
slouken@8972
   644
    dest->lpEnvelope = envelope;
slouken@8972
   645
    envelope->dwSize = sizeof(DIENVELOPE);      /* Always should be this. */
slouken@8972
   646
slouken@8972
   647
    /* Axes. */
slouken@8972
   648
    dest->cAxes = haptic->naxes;
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@8972
  1018
    if (FAILED(ret)) {
slouken@8972
  1019
        DI_SetError("Unable to update effect", ret);
slouken@8972
  1020
        goto err_update;
slouken@8972
  1021
    }
slouken@8972
  1022
slouken@8972
  1023
    /* Copy it over. */
slouken@8972
  1024
    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, data->type);
slouken@8972
  1025
    SDL_memcpy(&effect->hweffect->effect, &temp, sizeof(DIEFFECT));
slouken@8972
  1026
slouken@8972
  1027
    return 0;
slouken@8972
  1028
slouken@8972
  1029
err_update:
slouken@8972
  1030
    SDL_SYS_HapticFreeDIEFFECT(&temp, data->type);
slouken@8972
  1031
    return -1;
slouken@8972
  1032
}
slouken@8972
  1033
slouken@8972
  1034
int
slouken@8972
  1035
SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
slouken@8972
  1036
{
slouken@8972
  1037
    HRESULT ret;
slouken@8972
  1038
    DWORD iter;
slouken@8972
  1039
slouken@8972
  1040
    /* Check if it's infinite. */
slouken@8972
  1041
    if (iterations == SDL_HAPTIC_INFINITY) {
slouken@8972
  1042
        iter = INFINITE;
slouken@8972
  1043
    } else {
slouken@8972
  1044
        iter = iterations;
slouken@8972
  1045
    }
slouken@8972
  1046
slouken@8972
  1047
    /* Run the effect. */
slouken@8972
  1048
    ret = IDirectInputEffect_Start(effect->hweffect->ref, iter, 0);
slouken@8972
  1049
    if (FAILED(ret)) {
slouken@8972
  1050
        return DI_SetError("Running the effect", ret);
slouken@8972
  1051
    }
slouken@8972
  1052
    return 0;
slouken@8972
  1053
}
slouken@8972
  1054
slouken@8972
  1055
int
slouken@8972
  1056
SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1057
{
slouken@8972
  1058
    HRESULT ret;
slouken@8972
  1059
slouken@8972
  1060
    ret = IDirectInputEffect_Stop(effect->hweffect->ref);
slouken@8972
  1061
    if (FAILED(ret)) {
slouken@8972
  1062
        return DI_SetError("Unable to stop effect", ret);
slouken@8972
  1063
    }
slouken@8972
  1064
    return 0;
slouken@8972
  1065
}
slouken@8972
  1066
slouken@8972
  1067
void
slouken@8972
  1068
SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1069
{
slouken@8972
  1070
    HRESULT ret;
slouken@8972
  1071
slouken@8972
  1072
    ret = IDirectInputEffect_Unload(effect->hweffect->ref);
slouken@8972
  1073
    if (FAILED(ret)) {
slouken@8972
  1074
        DI_SetError("Removing effect from the device", ret);
slouken@8972
  1075
    }
slouken@8972
  1076
    SDL_SYS_HapticFreeDIEFFECT(&effect->hweffect->effect, effect->effect.type);
slouken@8972
  1077
}
slouken@8972
  1078
slouken@8972
  1079
int
slouken@8972
  1080
SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1081
{
slouken@8972
  1082
    HRESULT ret;
slouken@8972
  1083
    DWORD status;
slouken@8972
  1084
slouken@8972
  1085
    ret = IDirectInputEffect_GetEffectStatus(effect->hweffect->ref, &status);
slouken@8972
  1086
    if (FAILED(ret)) {
slouken@8972
  1087
        return DI_SetError("Getting effect status", ret);
slouken@8972
  1088
    }
slouken@8972
  1089
slouken@8972
  1090
    if (status == 0)
slouken@8972
  1091
        return SDL_FALSE;
slouken@8972
  1092
    return SDL_TRUE;
slouken@8972
  1093
}
slouken@8972
  1094
slouken@8972
  1095
int
slouken@8972
  1096
SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@8972
  1097
{
slouken@8972
  1098
    HRESULT ret;
slouken@8972
  1099
    DIPROPDWORD dipdw;
slouken@8972
  1100
slouken@8972
  1101
    /* Create the weird structure thingy. */
slouken@8972
  1102
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
  1103
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
  1104
    dipdw.diph.dwObj = 0;
slouken@8972
  1105
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
  1106
    dipdw.dwData = gain * 100;  /* 0 to 10,000 */
slouken@8972
  1107
slouken@8972
  1108
    /* Try to set the autocenter. */
slouken@8972
  1109
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
  1110
        DIPROP_FFGAIN, &dipdw.diph);
slouken@8972
  1111
    if (FAILED(ret)) {
slouken@8972
  1112
        return DI_SetError("Setting gain", ret);
slouken@8972
  1113
    }
slouken@8972
  1114
    return 0;
slouken@8972
  1115
}
slouken@8972
  1116
slouken@8972
  1117
int
slouken@8972
  1118
SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@8972
  1119
{
slouken@8972
  1120
    HRESULT ret;
slouken@8972
  1121
    DIPROPDWORD dipdw;
slouken@8972
  1122
slouken@8972
  1123
    /* Create the weird structure thingy. */
slouken@8972
  1124
    dipdw.diph.dwSize = sizeof(DIPROPDWORD);
slouken@8972
  1125
    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
slouken@8972
  1126
    dipdw.diph.dwObj = 0;
slouken@8972
  1127
    dipdw.diph.dwHow = DIPH_DEVICE;
slouken@8972
  1128
    dipdw.dwData = (autocenter == 0) ? DIPROPAUTOCENTER_OFF :
slouken@8972
  1129
        DIPROPAUTOCENTER_ON;
slouken@8972
  1130
slouken@8972
  1131
    /* Try to set the autocenter. */
slouken@8972
  1132
    ret = IDirectInputDevice8_SetProperty(haptic->hwdata->device,
slouken@8972
  1133
        DIPROP_AUTOCENTER, &dipdw.diph);
slouken@8972
  1134
    if (FAILED(ret)) {
slouken@8972
  1135
        return DI_SetError("Setting autocenter", ret);
slouken@8972
  1136
    }
slouken@8972
  1137
    return 0;
slouken@8972
  1138
}
slouken@8972
  1139
slouken@8972
  1140
int
slouken@8972
  1141
SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
slouken@8972
  1142
{
slouken@8972
  1143
    HRESULT ret;
slouken@8972
  1144
slouken@8972
  1145
    /* Pause the device. */
slouken@8972
  1146
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1147
        DISFFC_PAUSE);
slouken@8972
  1148
    if (FAILED(ret)) {
slouken@8972
  1149
        return DI_SetError("Pausing the device", ret);
slouken@8972
  1150
    }
slouken@8972
  1151
    return 0;
slouken@8972
  1152
}
slouken@8972
  1153
slouken@8972
  1154
int
slouken@8972
  1155
SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
slouken@8972
  1156
{
slouken@8972
  1157
    HRESULT ret;
slouken@8972
  1158
slouken@8972
  1159
    /* Unpause the device. */
slouken@8972
  1160
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1161
        DISFFC_CONTINUE);
slouken@8972
  1162
    if (FAILED(ret)) {
slouken@8972
  1163
        return DI_SetError("Pausing the device", ret);
slouken@8972
  1164
    }
slouken@8972
  1165
    return 0;
slouken@8972
  1166
}
slouken@8972
  1167
slouken@8972
  1168
int
slouken@8972
  1169
SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
slouken@8972
  1170
{
slouken@8972
  1171
    HRESULT ret;
slouken@8972
  1172
slouken@8972
  1173
    /* Try to stop the effects. */
slouken@8972
  1174
    ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
slouken@8972
  1175
        DISFFC_STOPALL);
slouken@8972
  1176
    if (FAILED(ret)) {
slouken@8972
  1177
        return DI_SetError("Stopping the device", ret);
slouken@8972
  1178
    }
slouken@8972
  1179
    return 0;
slouken@8972
  1180
}
slouken@8972
  1181
slouken@8972
  1182
#else /* !SDL_HAPTIC_DINPUT */
slouken@8972
  1183
slouken@8972
  1184
slouken@8972
  1185
int
slouken@8972
  1186
SDL_DINPUT_HapticInit(void)
slouken@8972
  1187
{
slouken@8972
  1188
    return 0;
slouken@8972
  1189
}
slouken@8972
  1190
slouken@8972
  1191
int
slouken@8972
  1192
SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
  1193
{
slouken@8972
  1194
    return SDL_Unsupported();
slouken@8972
  1195
}
slouken@8972
  1196
slouken@8972
  1197
int
slouken@8972
  1198
SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance)
slouken@8972
  1199
{
slouken@8972
  1200
    return SDL_Unsupported();
slouken@8972
  1201
}
slouken@8972
  1202
slouken@8972
  1203
int
slouken@8972
  1204
SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item)
slouken@8972
  1205
{
slouken@8972
  1206
    return SDL_Unsupported();
slouken@8972
  1207
}
slouken@8972
  1208
slouken@8972
  1209
int
slouken@8972
  1210
SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
  1211
{
slouken@8972
  1212
    return SDL_Unsupported();
slouken@8972
  1213
}
slouken@8972
  1214
slouken@8972
  1215
int
slouken@8972
  1216
SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
slouken@8972
  1217
{
slouken@8972
  1218
    return SDL_Unsupported();
slouken@8972
  1219
}
slouken@8972
  1220
slouken@8972
  1221
void
slouken@8972
  1222
SDL_DINPUT_HapticClose(SDL_Haptic * haptic)
slouken@8972
  1223
{
slouken@8972
  1224
}
slouken@8972
  1225
slouken@8972
  1226
void
slouken@8972
  1227
SDL_DINPUT_HapticQuit(void)
slouken@8972
  1228
{
slouken@8972
  1229
}
slouken@8972
  1230
slouken@8972
  1231
int
slouken@8972
  1232
SDL_DINPUT_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * base)
slouken@8972
  1233
{
slouken@8972
  1234
    return SDL_Unsupported();
slouken@8972
  1235
}
slouken@8972
  1236
slouken@8972
  1237
int
slouken@8972
  1238
SDL_DINPUT_HapticUpdateEffect(SDL_Haptic * haptic, struct haptic_effect *effect, SDL_HapticEffect * data)
slouken@8972
  1239
{
slouken@8972
  1240
    return SDL_Unsupported();
slouken@8972
  1241
}
slouken@8972
  1242
slouken@8972
  1243
int
slouken@8972
  1244
SDL_DINPUT_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, Uint32 iterations)
slouken@8972
  1245
{
slouken@8972
  1246
    return SDL_Unsupported();
slouken@8972
  1247
}
slouken@8972
  1248
slouken@8972
  1249
int
slouken@8972
  1250
SDL_DINPUT_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1251
{
slouken@8972
  1252
    return SDL_Unsupported();
slouken@8972
  1253
}
slouken@8972
  1254
slouken@8972
  1255
void
slouken@8972
  1256
SDL_DINPUT_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1257
{
slouken@8972
  1258
}
slouken@8972
  1259
slouken@8972
  1260
int
slouken@8972
  1261
SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic * haptic, struct haptic_effect *effect)
slouken@8972
  1262
{
slouken@8972
  1263
    return SDL_Unsupported();
slouken@8972
  1264
}
slouken@8972
  1265
slouken@8972
  1266
int
slouken@8972
  1267
SDL_DINPUT_HapticSetGain(SDL_Haptic * haptic, int gain)
slouken@8972
  1268
{
slouken@8972
  1269
    return SDL_Unsupported();
slouken@8972
  1270
}
slouken@8972
  1271
slouken@8972
  1272
int
slouken@8972
  1273
SDL_DINPUT_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
slouken@8972
  1274
{
slouken@8972
  1275
    return SDL_Unsupported();
slouken@8972
  1276
}
slouken@8972
  1277
slouken@8972
  1278
int
slouken@8972
  1279
SDL_DINPUT_HapticPause(SDL_Haptic * haptic)
slouken@8972
  1280
{
slouken@8972
  1281
    return SDL_Unsupported();
slouken@8972
  1282
}
slouken@8972
  1283
slouken@8972
  1284
int
slouken@8972
  1285
SDL_DINPUT_HapticUnpause(SDL_Haptic * haptic)
slouken@8972
  1286
{
slouken@8972
  1287
    return SDL_Unsupported();
slouken@8972
  1288
}
slouken@8972
  1289
slouken@8972
  1290
int
slouken@8972
  1291
SDL_DINPUT_HapticStopAll(SDL_Haptic * haptic)
slouken@8972
  1292
{
slouken@8972
  1293
    return SDL_Unsupported();
slouken@8972
  1294
}
slouken@8972
  1295
slouken@8972
  1296
#endif /* SDL_HAPTIC_DINPUT */
slouken@8972
  1297
slouken@8972
  1298
/* vi: set ts=4 sw=4 expandtab: */