Path: blob/master/thirdparty/sdl/haptic/windows/SDL_windowshaptic.c
9912 views
/*1Simple DirectMedia Layer2Copyright (C) 1997-2025 Sam Lantinga <[email protected]>34This software is provided 'as-is', without any express or implied5warranty. In no event will the authors be held liable for any damages6arising from the use of this software.78Permission is granted to anyone to use this software for any purpose,9including commercial applications, and to alter it and redistribute it10freely, subject to the following restrictions:11121. The origin of this software must not be misrepresented; you must not13claim that you wrote the original software. If you use this software14in a product, an acknowledgment in the product documentation would be15appreciated but is not required.162. Altered source versions must be plainly marked as such, and must not be17misrepresented as being the original software.183. This notice may not be removed or altered from any source distribution.19*/20#include "SDL_internal.h"2122#ifdef SDL_HAPTIC_DINPUT2324#include "../SDL_syshaptic.h"25#include "../../joystick/SDL_sysjoystick.h" // For the real SDL_Joystick26#include "../../joystick/windows/SDL_windowsjoystick_c.h" // For joystick hwdata27#include "../../joystick/windows/SDL_xinputjoystick_c.h" // For xinput rumble2829#include "SDL_windowshaptic_c.h"30#include "SDL_dinputhaptic_c.h"3132// Set up for C function definitions, even when using C++33#ifdef __cplusplus34extern "C" {35#endif3637/*38* Internal stuff.39*/40SDL_hapticlist_item *SDL_hapticlist = NULL;41static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;42static int numhaptics = 0;4344/*45* Initializes the haptic subsystem.46*/47bool SDL_SYS_HapticInit(void)48{49JoyStick_DeviceData *device;5051if (!SDL_DINPUT_HapticInit()) {52return false;53}5455/* The joystick subsystem will usually be initialized before haptics,56* so the initial HapticMaybeAddDevice() calls from the joystick57* subsystem will arrive too early to create haptic devices. We will58* invoke those callbacks again here to pick up any joysticks that59* were added prior to haptics initialization. */60for (device = SYS_Joystick; device; device = device->pNext) {61SDL_DINPUT_HapticMaybeAddDevice(&device->dxdevice);62}6364return true;65}6667bool SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)68{69if (!SDL_hapticlist_tail) {70SDL_hapticlist = SDL_hapticlist_tail = item;71} else {72SDL_hapticlist_tail->next = item;73SDL_hapticlist_tail = item;74}7576// Device has been added.77++numhaptics;7879return true;80}8182bool SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)83{84const bool result = item->haptic ? true : false;85if (prev) {86prev->next = item->next;87} else {88SDL_assert(SDL_hapticlist == item);89SDL_hapticlist = item->next;90}91if (item == SDL_hapticlist_tail) {92SDL_hapticlist_tail = prev;93}94--numhaptics;95// !!! TODO: Send a haptic remove event?96SDL_free(item);97return result;98}99100int SDL_SYS_NumHaptics(void)101{102return numhaptics;103}104105static SDL_hapticlist_item *HapticByDevIndex(int device_index)106{107SDL_hapticlist_item *item = SDL_hapticlist;108109if ((device_index < 0) || (device_index >= numhaptics)) {110return NULL;111}112113while (device_index > 0) {114SDL_assert(item != NULL);115--device_index;116item = item->next;117}118return item;119}120121static SDL_hapticlist_item *HapticByInstanceID(SDL_HapticID instance_id)122{123SDL_hapticlist_item *item;124for (item = SDL_hapticlist; item; item = item->next) {125if (instance_id == item->instance_id) {126return item;127}128}129return NULL;130}131132SDL_HapticID SDL_SYS_HapticInstanceID(int index)133{134SDL_hapticlist_item *item = HapticByDevIndex(index);135if (item) {136return item->instance_id;137}138return 0;139}140141/*142* Return the name of a haptic device, does not need to be opened.143*/144const char *SDL_SYS_HapticName(int index)145{146SDL_hapticlist_item *item = HapticByDevIndex(index);147return item->name;148}149150/*151* Opens a haptic device for usage.152*/153bool SDL_SYS_HapticOpen(SDL_Haptic *haptic)154{155SDL_hapticlist_item *item = HapticByInstanceID(haptic->instance_id);156return SDL_DINPUT_HapticOpen(haptic, item);157}158159/*160* Opens a haptic device from first mouse it finds for usage.161*/162int SDL_SYS_HapticMouse(void)163{164#ifdef SDL_HAPTIC_DINPUT165SDL_hapticlist_item *item;166int index = 0;167168// Grab the first mouse haptic device we find.169for (item = SDL_hapticlist; item; item = item->next) {170if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {171return index;172}173++index;174}175#endif // SDL_HAPTIC_DINPUT176return -1;177}178179/*180* Checks to see if a joystick has haptic features.181*/182bool SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)183{184if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {185return false;186}187if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {188return true;189}190return false;191}192193/*194* Checks to see if the haptic device and joystick are in reality the same.195*/196bool SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)197{198if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {199return false;200}201return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);202}203204/*205* Opens a SDL_Haptic from a SDL_Joystick.206*/207bool SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)208{209SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);210211return SDL_DINPUT_HapticOpenFromJoystick(haptic, joystick);212}213214/*215* Closes the haptic device.216*/217void SDL_SYS_HapticClose(SDL_Haptic *haptic)218{219if (haptic->hwdata) {220221// Free effects.222SDL_free(haptic->effects);223haptic->effects = NULL;224haptic->neffects = 0;225226// Clean up227SDL_DINPUT_HapticClose(haptic);228229// Free230SDL_free(haptic->hwdata);231haptic->hwdata = NULL;232}233}234235/*236* Clean up after system specific haptic stuff237*/238void SDL_SYS_HapticQuit(void)239{240SDL_hapticlist_item *item;241SDL_hapticlist_item *next = NULL;242243for (item = SDL_hapticlist; item; item = next) {244/* Opened and not closed haptics are leaked, this is on purpose.245* Close your haptic devices after usage. */246// !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not.247next = item->next;248SDL_free(item->name);249SDL_free(item);250}251252SDL_DINPUT_HapticQuit();253254numhaptics = 0;255SDL_hapticlist = NULL;256SDL_hapticlist_tail = NULL;257}258259/*260* Creates a new haptic effect.261*/262bool SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect,263const SDL_HapticEffect *base)264{265bool result;266267// Alloc the effect.268effect->hweffect = (struct haptic_hweffect *) SDL_calloc(1, sizeof(struct haptic_hweffect));269if (!effect->hweffect) {270return false;271}272273result = SDL_DINPUT_HapticNewEffect(haptic, effect, base);274if (!result) {275SDL_free(effect->hweffect);276effect->hweffect = NULL;277}278return result;279}280281/*282* Updates an effect.283*/284bool SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, const SDL_HapticEffect *data)285{286return SDL_DINPUT_HapticUpdateEffect(haptic, effect, data);287}288289/*290* Runs an effect.291*/292bool SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)293{294return SDL_DINPUT_HapticRunEffect(haptic, effect, iterations);295}296297/*298* Stops an effect.299*/300bool SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)301{302return SDL_DINPUT_HapticStopEffect(haptic, effect);303}304305/*306* Frees the effect.307*/308void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)309{310SDL_DINPUT_HapticDestroyEffect(haptic, effect);311SDL_free(effect->hweffect);312effect->hweffect = NULL;313}314315/*316* Gets the status of a haptic effect.317*/318int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)319{320return SDL_DINPUT_HapticGetEffectStatus(haptic, effect);321}322323/*324* Sets the gain.325*/326bool SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)327{328return SDL_DINPUT_HapticSetGain(haptic, gain);329}330331/*332* Sets the autocentering.333*/334bool SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)335{336return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);337}338339/*340* Pauses the device.341*/342bool SDL_SYS_HapticPause(SDL_Haptic *haptic)343{344return SDL_DINPUT_HapticPause(haptic);345}346347/*348* Pauses the device.349*/350bool SDL_SYS_HapticResume(SDL_Haptic *haptic)351{352return SDL_DINPUT_HapticResume(haptic);353}354355/*356* Stops all the playing effects on the device.357*/358bool SDL_SYS_HapticStopAll(SDL_Haptic *haptic)359{360return SDL_DINPUT_HapticStopAll(haptic);361}362363// Ends C function definitions when using C++364#ifdef __cplusplus365}366#endif367368#endif // SDL_HAPTIC_DINPUT369370371