cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

SDL_dinputhaptic.c (38343B)


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