SDL 2.0
SDL_windowshaptic.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 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#if SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT
24
25#include "SDL_assert.h"
26#include "SDL_thread.h"
27#include "SDL_mutex.h"
28#include "SDL_timer.h"
29#include "SDL_hints.h"
30#include "SDL_haptic.h"
31#include "../SDL_syshaptic.h"
32#include "SDL_joystick.h"
33#include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */
34#include "../../joystick/windows/SDL_windowsjoystick_c.h" /* For joystick hwdata */
35#include "../../joystick/windows/SDL_xinputjoystick_c.h" /* For xinput rumble */
36
37#include "SDL_windowshaptic_c.h"
38#include "SDL_dinputhaptic_c.h"
39#include "SDL_xinputhaptic_c.h"
40
41
42/*
43 * Internal stuff.
44 */
46static SDL_hapticlist_item *SDL_hapticlist_tail = NULL;
47static int numhaptics = 0;
48
49
50/*
51 * Initializes the haptic subsystem.
52 */
53int
55{
56 if (SDL_DINPUT_HapticInit() < 0) {
57 return -1;
58 }
59 if (SDL_XINPUT_HapticInit() < 0) {
60 return -1;
61 }
62 return numhaptics;
63}
64
65int
67{
68 if (SDL_hapticlist_tail == NULL) {
69 SDL_hapticlist = SDL_hapticlist_tail = item;
70 } else {
71 SDL_hapticlist_tail->next = item;
72 SDL_hapticlist_tail = item;
73 }
74
75 /* Device has been added. */
76 ++numhaptics;
77
78 return numhaptics;
79}
80
81int
83{
84 const int retval = item->haptic ? item->haptic->index : -1;
85 if (prev != NULL) {
86 prev->next = item->next;
87 } else {
89 SDL_hapticlist = item->next;
90 }
91 if (item == SDL_hapticlist_tail) {
92 SDL_hapticlist_tail = prev;
93 }
94 --numhaptics;
95 /* !!! TODO: Send a haptic remove event? */
96 SDL_free(item);
97 return retval;
98}
99
100int
102{
103 return numhaptics;
104}
105
106static SDL_hapticlist_item *
107HapticByDevIndex(int device_index)
108{
110
111 if ((device_index < 0) || (device_index >= numhaptics)) {
112 return NULL;
113 }
114
115 while (device_index > 0) {
116 SDL_assert(item != NULL);
117 --device_index;
118 item = item->next;
119 }
120 return item;
121}
122
123/*
124 * Return the name of a haptic device, does not need to be opened.
125 */
126const char *
128{
129 SDL_hapticlist_item *item = HapticByDevIndex(index);
130 return item->name;
131}
132
133/*
134 * Opens a haptic device for usage.
135 */
136int
137SDL_SYS_HapticOpen(SDL_Haptic * haptic)
138{
139 SDL_hapticlist_item *item = HapticByDevIndex(haptic->index);
140 if (item->bXInputHaptic) {
141 return SDL_XINPUT_HapticOpen(haptic, item);
142 } else {
143 return SDL_DINPUT_HapticOpen(haptic, item);
144 }
145}
146
147
148/*
149 * Opens a haptic device from first mouse it finds for usage.
150 */
151int
153{
154#if SDL_HAPTIC_DINPUT
156 int index = 0;
157
158 /* Grab the first mouse haptic device we find. */
159 for (item = SDL_hapticlist; item != NULL; item = item->next) {
160 if (item->capabilities.dwDevType == DI8DEVCLASS_POINTER) {
161 return index;
162 }
163 ++index;
164 }
165#endif /* SDL_HAPTIC_DINPUT */
166 return -1;
167}
168
169
170/*
171 * Checks to see if a joystick has haptic features.
172 */
173int
174SDL_SYS_JoystickIsHaptic(SDL_Joystick * joystick)
175{
176 if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
177 return 0;
178 }
179#if SDL_HAPTIC_XINPUT
180 if (joystick->hwdata->bXInputHaptic) {
181 return 1;
182 }
183#endif
184#if SDL_HAPTIC_DINPUT
185 if (joystick->hwdata->Capabilities.dwFlags & DIDC_FORCEFEEDBACK) {
186 return 1;
187 }
188#endif
189 return 0;
190}
191
192/*
193 * Checks to see if the haptic device and joystick are in reality the same.
194 */
195int
196SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick)
197{
198 if (joystick->driver != &SDL_WINDOWS_JoystickDriver) {
199 return 0;
200 }
201 if (joystick->hwdata->bXInputHaptic != haptic->hwdata->bXInputHaptic) {
202 return 0; /* one is XInput, one is not; not the same device. */
203 } else if (joystick->hwdata->bXInputHaptic) {
204 return SDL_XINPUT_JoystickSameHaptic(haptic, joystick);
205 } else {
206 return SDL_DINPUT_JoystickSameHaptic(haptic, joystick);
207 }
208}
209
210/*
211 * Opens a SDL_Haptic from a SDL_Joystick.
212 */
213int
214SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
215{
216 SDL_assert(joystick->driver == &SDL_WINDOWS_JoystickDriver);
217
218 if (joystick->hwdata->bXInputDevice) {
220 } else {
222 }
223}
224
225/*
226 * Closes the haptic device.
227 */
228void
229SDL_SYS_HapticClose(SDL_Haptic * haptic)
230{
231 if (haptic->hwdata) {
232
233 /* Free effects. */
234 SDL_free(haptic->effects);
235 haptic->effects = NULL;
236 haptic->neffects = 0;
237
238 /* Clean up */
239 if (haptic->hwdata->bXInputHaptic) {
241 } else {
243 }
244
245 /* Free */
246 SDL_free(haptic->hwdata);
247 haptic->hwdata = NULL;
248 }
249}
250
251/*
252 * Clean up after system specific haptic stuff
253 */
254void
256{
259 SDL_Haptic *hapticitem = NULL;
260
261 extern SDL_Haptic *SDL_haptics;
262 for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
263 if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
264 /* we _have_ to stop the thread before we free the XInput DLL! */
265 SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
266 SDL_WaitThread(hapticitem->hwdata->thread, NULL);
267 hapticitem->hwdata->thread = NULL;
268 }
269 }
270
271 for (item = SDL_hapticlist; item; item = next) {
272 /* Opened and not closed haptics are leaked, this is on purpose.
273 * Close your haptic devices after usage. */
274 /* !!! FIXME: (...is leaking on purpose a good idea?) - No, of course not. */
275 next = item->next;
276 SDL_free(item->name);
277 SDL_free(item);
278 }
279
282
283 numhaptics = 0;
285 SDL_hapticlist_tail = NULL;
286}
287
288/*
289 * Creates a new haptic effect.
290 */
291int
292SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
293 SDL_HapticEffect * base)
294{
295 int result;
296
297 /* Alloc the effect. */
298 effect->hweffect = (struct haptic_hweffect *)
299 SDL_malloc(sizeof(struct haptic_hweffect));
300 if (effect->hweffect == NULL) {
302 return -1;
303 }
304 SDL_zerop(effect->hweffect);
305
306 if (haptic->hwdata->bXInputHaptic) {
308 } else {
310 }
311 if (result < 0) {
312 SDL_free(effect->hweffect);
313 effect->hweffect = NULL;
314 }
315 return result;
316}
317
318/*
319 * Updates an effect.
320 */
321int
323 struct haptic_effect *effect,
325{
326 if (haptic->hwdata->bXInputHaptic) {
328 } else {
330 }
331}
332
333/*
334 * Runs an effect.
335 */
336int
337SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect,
339{
340 if (haptic->hwdata->bXInputHaptic) {
342 } else {
344 }
345}
346
347/*
348 * Stops an effect.
349 */
350int
351SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
352{
353 if (haptic->hwdata->bXInputHaptic) {
354 return SDL_XINPUT_HapticStopEffect(haptic, effect);
355 } else {
356 return SDL_DINPUT_HapticStopEffect(haptic, effect);
357 }
358}
359
360/*
361 * Frees the effect.
362 */
363void
364SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect)
365{
366 if (haptic->hwdata->bXInputHaptic) {
368 } else {
370 }
371 SDL_free(effect->hweffect);
372 effect->hweffect = NULL;
373}
374
375/*
376 * Gets the status of a haptic effect.
377 */
378int
380 struct haptic_effect *effect)
381{
382 if (haptic->hwdata->bXInputHaptic) {
384 } else {
386 }
387}
388
389/*
390 * Sets the gain.
391 */
392int
393SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain)
394{
395 if (haptic->hwdata->bXInputHaptic) {
396 return SDL_XINPUT_HapticSetGain(haptic, gain);
397 } else {
398 return SDL_DINPUT_HapticSetGain(haptic, gain);
399 }
400}
401
402/*
403 * Sets the autocentering.
404 */
405int
406SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter)
407{
408 if (haptic->hwdata->bXInputHaptic) {
409 return SDL_XINPUT_HapticSetAutocenter(haptic, autocenter);
410 } else {
411 return SDL_DINPUT_HapticSetAutocenter(haptic, autocenter);
412 }
413}
414
415/*
416 * Pauses the device.
417 */
418int
419SDL_SYS_HapticPause(SDL_Haptic * haptic)
420{
421 if (haptic->hwdata->bXInputHaptic) {
423 } else {
425 }
426}
427
428/*
429 * Pauses the device.
430 */
431int
432SDL_SYS_HapticUnpause(SDL_Haptic * haptic)
433{
434 if (haptic->hwdata->bXInputHaptic) {
436 } else {
438 }
439}
440
441/*
442 * Stops all the playing effects on the device.
443 */
444int
445SDL_SYS_HapticStopAll(SDL_Haptic * haptic)
446{
447 if (haptic->hwdata->bXInputHaptic) {
449 } else {
451 }
452}
453
454#endif /* SDL_HAPTIC_DINPUT || SDL_HAPTIC_XINPUT */
455
456/* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
void SDL_DINPUT_HapticQuit(void)
int SDL_DINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_DINPUT_HapticStopAll(SDL_Haptic *haptic)
int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_DINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_DINPUT_HapticPause(SDL_Haptic *haptic)
int SDL_DINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
int SDL_DINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
void SDL_DINPUT_HapticClose(SDL_Haptic *haptic)
void SDL_DINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_DINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_DINPUT_HapticUnpause(SDL_Haptic *haptic)
int SDL_DINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_DINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_DINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_DINPUT_HapticInit(void)
#define SDL_AtomicSet
#define SDL_malloc
#define SDL_free
#define SDL_WaitThread
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
static SDL_Haptic * SDL_haptics
Definition: SDL_haptic.c:32
The SDL haptic subsystem allows you to control haptic (force feedback) devices.
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint64EXT * result
GLuint index
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
void SDL_SYS_HapticClose(SDL_Haptic *haptic)
int SDL_SYS_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticPause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetGain(SDL_Haptic *haptic, int gain)
void SDL_SYS_HapticQuit(void)
int SDL_SYS_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticMouse(void)
int SDL_SYS_HapticUnpause(SDL_Haptic *haptic)
int SDL_SYS_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_SYS_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
int SDL_SYS_HapticStopAll(SDL_Haptic *haptic)
int SDL_SYS_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_SYS_NumHaptics(void)
const char * SDL_SYS_HapticName(int index)
void SDL_SYS_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
int SDL_SYS_HapticOpen(SDL_Haptic *haptic)
int SDL_SYS_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_SYS_HapticInit(void)
int SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick)
SDL_JoystickDriver SDL_WINDOWS_JoystickDriver
int SDL_SYS_AddHapticDevice(SDL_hapticlist_item *item)
SDL_hapticlist_item * SDL_hapticlist
int SDL_SYS_RemoveHapticDevice(SDL_hapticlist_item *prev, SDL_hapticlist_item *item)
int SDL_XINPUT_HapticPause(SDL_Haptic *haptic)
int SDL_XINPUT_HapticStopEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticUpdateEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *data)
void SDL_XINPUT_HapticDestroyEffect(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticSetGain(SDL_Haptic *haptic, int gain)
int SDL_XINPUT_HapticNewEffect(SDL_Haptic *haptic, struct haptic_effect *effect, SDL_HapticEffect *base)
int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick)
void SDL_XINPUT_HapticQuit(void)
int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick)
void SDL_XINPUT_HapticClose(SDL_Haptic *haptic)
int SDL_XINPUT_HapticOpen(SDL_Haptic *haptic, SDL_hapticlist_item *item)
int SDL_XINPUT_HapticInit(void)
int SDL_XINPUT_HapticStopAll(SDL_Haptic *haptic)
int SDL_XINPUT_HapticRunEffect(SDL_Haptic *haptic, struct haptic_effect *effect, Uint32 iterations)
int SDL_XINPUT_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter)
int SDL_XINPUT_HapticGetEffectStatus(SDL_Haptic *haptic, struct haptic_effect *effect)
int SDL_XINPUT_HapticUnpause(SDL_Haptic *haptic)
#define NULL
Definition: begin_code.h:167
struct SDL_hapticlist_item * next
struct haptic_hweffect * hweffect
Definition: SDL_syshaptic.h:33
SDL_bool retval
static SDL_Haptic * haptic
Definition: testhaptic.c:25
static int iterations
Definition: testsprite2.c:45
The generic template for any haptic effect.
Definition: SDL_haptic.h:801