Atlas - SDL_hidapihaptic.c
Home / ext / SDL / src / haptic / hidapi Lines: 1 | Size: 9685 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 2025 Katharine Chui <[email protected]> 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#ifdef SDL_JOYSTICK_HIDAPI 24 25#include "SDL_hidapihaptic.h" 26#include "SDL_hidapihaptic_c.h" 27#include "SDL3/SDL_mutex.h" 28#include "SDL3/SDL_error.h" 29 30typedef struct haptic_list_node 31{ 32 SDL_Haptic *haptic; 33 struct haptic_list_node *next; 34} haptic_list_node; 35 36static haptic_list_node *haptic_list_head = NULL; 37static SDL_Mutex *haptic_list_mutex = NULL; 38 39static SDL_HIDAPI_HapticDriver *drivers[] = { 40 #ifdef SDL_HAPTIC_HIDAPI_LG4FF 41 &SDL_HIDAPI_HapticDriverLg4ff, 42 #endif 43 NULL 44}; 45 46bool SDL_HIDAPI_HapticInit(void) 47{ 48 haptic_list_head = NULL; 49 haptic_list_mutex = SDL_CreateMutex(); 50 if (haptic_list_mutex == NULL) { 51 return SDL_OutOfMemory(); 52 } 53 return true; 54} 55 56bool SDL_HIDAPI_HapticIsHidapi(SDL_Haptic *haptic) 57{ 58 haptic_list_node *cur; 59 bool ret = false; 60 61 SDL_LockMutex(haptic_list_mutex); 62 cur = haptic_list_head; 63 while (cur != NULL) { 64 if (cur->haptic == haptic) { 65 ret = true; 66 break; 67 } 68 cur = cur->next; 69 } 70 71 SDL_UnlockMutex(haptic_list_mutex); 72 73 return ret; 74} 75 76 77bool SDL_HIDAPI_JoystickIsHaptic(SDL_Joystick *joystick) 78{ 79 const int numdrivers = SDL_arraysize(drivers) - 1; 80 int i; 81 82 SDL_AssertJoysticksLocked(); 83 84 if (joystick->driver != &SDL_HIDAPI_JoystickDriver) { 85 return false; 86 } 87 88 for (i = 0; i < numdrivers; ++i) { 89 if (drivers[i]->JoystickSupported(joystick)) { 90 return true; 91 } 92 } 93 return false; 94} 95 96bool SDL_HIDAPI_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) 97{ 98 const int numdrivers = SDL_arraysize(drivers) - 1; 99 int i; 100 101 SDL_AssertJoysticksLocked(); 102 103 if (joystick->driver != &SDL_HIDAPI_JoystickDriver) { 104 return SDL_SetError("Cannot open hidapi haptic from non hidapi joystick"); 105 } 106 107 for (i = 0; i < numdrivers; ++i) { 108 if (drivers[i]->JoystickSupported(joystick)) { 109 SDL_HIDAPI_HapticDevice *device; 110 haptic_list_node *list_node; 111 // the driver is responsible for calling SDL_SetError 112 void *ctx = drivers[i]->Open(joystick); 113 if (ctx == NULL) { 114 return false; 115 } 116 117 device = SDL_malloc(sizeof(SDL_HIDAPI_HapticDevice)); 118 if (device == NULL) { 119 SDL_HIDAPI_HapticDevice temp; 120 temp.ctx = ctx; 121 temp.driver = drivers[i]; 122 temp.joystick = joystick; 123 temp.driver->Close(&temp); 124 return SDL_OutOfMemory(); 125 } 126 127 device->driver = drivers[i]; 128 device->haptic = haptic; 129 device->joystick = joystick; 130 device->ctx = ctx; 131 132 list_node = SDL_malloc(sizeof(haptic_list_node)); 133 if (list_node == NULL) { 134 device->driver->Close(device); 135 SDL_free(device); 136 return SDL_OutOfMemory(); 137 } 138 139 haptic->hwdata = (struct haptic_hwdata *)device; 140 141 // this is outside of the syshaptic driver 142 143 haptic->neffects = device->driver->NumEffects(device); 144 haptic->nplaying = device->driver->NumEffectsPlaying(device); 145 haptic->supported = device->driver->GetFeatures(device); 146 haptic->naxes = device->driver->NumAxes(device); 147 haptic->neffects = device->driver->NumEffects(device); 148 haptic->effects = (struct haptic_effect *)SDL_malloc(sizeof(struct haptic_effect) * haptic->neffects); 149 if (haptic->effects == NULL) { 150 SDL_free(list_node); 151 device->driver->Close(device); 152 SDL_free(device); 153 return SDL_OutOfMemory(); 154 } 155 SDL_memset(haptic->effects, 0, sizeof(struct haptic_effect) * haptic->neffects); 156 157 // outside of SYS_HAPTIC 158 haptic->instance_id = 255; 159 160 list_node->haptic = haptic; 161 list_node->next = NULL; 162 163 // grab a joystick ref so that it doesn't get fully destroyed before the haptic is closed 164 SDL_OpenJoystick(SDL_GetJoystickID(joystick)); 165 166 SDL_LockMutex(haptic_list_mutex); 167 if (haptic_list_head == NULL) { 168 haptic_list_head = list_node; 169 } else { 170 haptic_list_node *cur = haptic_list_head; 171 while(cur->next != NULL) { 172 cur = cur->next; 173 } 174 cur->next = list_node; 175 } 176 SDL_UnlockMutex(haptic_list_mutex); 177 178 return true; 179 } 180 } 181 182 return SDL_SetError("No supported HIDAPI haptic driver found for joystick"); 183} 184 185bool SDL_HIDAPI_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) 186{ 187 SDL_HIDAPI_HapticDevice *device; 188 189 SDL_AssertJoysticksLocked(); 190 if (joystick->driver != &SDL_HIDAPI_JoystickDriver) { 191 return false; 192 } 193 194 device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 195 196 if (joystick == device->joystick) { 197 return true; 198 } 199 return false; 200} 201 202void SDL_HIDAPI_HapticClose(SDL_Haptic *haptic) 203{ 204 haptic_list_node *cur, *last; 205 206 SDL_LockMutex(haptic_list_mutex); 207 208 cur = haptic_list_head; 209 last = NULL; 210 while (cur != NULL) { 211 if (cur->haptic == haptic) { 212 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 213 214 device->driver->Close(device); 215 216 // a reference was grabbed during open, now release it 217 SDL_CloseJoystick(device->joystick); 218 219 if (cur == haptic_list_head) { 220 haptic_list_head = cur->next; 221 } else { 222 last->next = cur->next; 223 } 224 225 SDL_free(device->ctx); 226 SDL_free(device); 227 SDL_free(haptic->effects); 228 SDL_free(cur); 229 SDL_UnlockMutex(haptic_list_mutex); 230 return; 231 } 232 last = cur; 233 cur = cur->next; 234 } 235 236 SDL_UnlockMutex(haptic_list_mutex); 237} 238 239void SDL_HIDAPI_HapticQuit(void) 240{ 241 // the list is cleared in SDL_haptic.c 242 if (haptic_list_mutex != NULL) { 243 SDL_DestroyMutex(haptic_list_mutex); 244 haptic_list_mutex = NULL; 245 } 246} 247 248SDL_HapticEffectID SDL_HIDAPI_HapticNewEffect(SDL_Haptic *haptic, const SDL_HapticEffect *base) 249{ 250 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 251 SDL_HapticEffectID new_id = device->driver->CreateEffect(device, base); 252 if (new_id >= 0){ 253 haptic->effects[new_id].effect = *base; 254 } 255 return new_id; 256} 257 258bool SDL_HIDAPI_HapticUpdateEffect(SDL_Haptic *haptic, SDL_HapticEffectID id, const SDL_HapticEffect *data) 259{ 260 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 261 return device->driver->UpdateEffect(device, id, data); 262} 263 264bool SDL_HIDAPI_HapticRunEffect(SDL_Haptic *haptic, SDL_HapticEffectID id, Uint32 iterations) 265{ 266 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 267 return device->driver->RunEffect(device, id, iterations); 268} 269 270bool SDL_HIDAPI_HapticStopEffect(SDL_Haptic *haptic, SDL_HapticEffectID id) 271{ 272 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 273 return device->driver->StopEffect(device, id); 274} 275 276void SDL_HIDAPI_HapticDestroyEffect(SDL_Haptic *haptic, SDL_HapticEffectID id) 277{ 278 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 279 device->driver->DestroyEffect(device, id); 280} 281 282bool SDL_HIDAPI_HapticGetEffectStatus(SDL_Haptic *haptic, SDL_HapticEffectID id) 283{ 284 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 285 return device->driver->GetEffectStatus(device, id); 286} 287 288bool SDL_HIDAPI_HapticSetGain(SDL_Haptic *haptic, int gain) 289{ 290 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 291 return device->driver->SetGain(device, gain); 292} 293 294bool SDL_HIDAPI_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) 295{ 296 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 297 return device->driver->SetAutocenter(device, autocenter); 298} 299 300bool SDL_HIDAPI_HapticPause(SDL_Haptic *haptic) 301{ 302 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 303 return device->driver->Pause(device); 304} 305 306bool SDL_HIDAPI_HapticResume(SDL_Haptic *haptic) 307{ 308 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 309 return device->driver->Resume(device); 310} 311 312bool SDL_HIDAPI_HapticStopAll(SDL_Haptic *haptic) 313{ 314 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 315 return device->driver->StopEffects(device); 316} 317 318#endif //SDL_JOYSTICK_HIDAPI 319[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.