Atlas - SDL_hidapihaptic.c
Home / ext / SDL / src / haptic / hidapi Lines: 1 | Size: 9038 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 148 // outside of SYS_HAPTIC 149 haptic->instance_id = 255; 150 151 list_node->haptic = haptic; 152 list_node->next = NULL; 153 154 // grab a joystick ref so that it doesn't get fully destroyed before the haptic is closed 155 SDL_OpenJoystick(SDL_GetJoystickID(joystick)); 156 157 SDL_LockMutex(haptic_list_mutex); 158 if (haptic_list_head == NULL) { 159 haptic_list_head = list_node; 160 } else { 161 haptic_list_node *cur = haptic_list_head; 162 while(cur->next != NULL) { 163 cur = cur->next; 164 } 165 cur->next = list_node; 166 } 167 SDL_UnlockMutex(haptic_list_mutex); 168 169 return true; 170 } 171 } 172 173 return SDL_SetError("No supported HIDAPI haptic driver found for joystick"); 174} 175 176bool SDL_HIDAPI_JoystickSameHaptic(SDL_Haptic *haptic, SDL_Joystick *joystick) 177{ 178 SDL_HIDAPI_HapticDevice *device; 179 180 SDL_AssertJoysticksLocked(); 181 if (joystick->driver != &SDL_HIDAPI_JoystickDriver) { 182 return false; 183 } 184 185 device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 186 187 if (joystick == device->joystick) { 188 return true; 189 } 190 return false; 191} 192 193void SDL_HIDAPI_HapticClose(SDL_Haptic *haptic) 194{ 195 haptic_list_node *cur, *last; 196 197 SDL_LockMutex(haptic_list_mutex); 198 199 cur = haptic_list_head; 200 last = NULL; 201 while (cur != NULL) { 202 if (cur->haptic == haptic) { 203 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 204 205 device->driver->Close(device); 206 207 // a reference was grabbed during open, now release it 208 SDL_CloseJoystick(device->joystick); 209 210 if (cur == haptic_list_head) { 211 haptic_list_head = cur->next; 212 } else { 213 last->next = cur->next; 214 } 215 216 SDL_free(device->ctx); 217 SDL_free(device); 218 SDL_free(cur); 219 SDL_UnlockMutex(haptic_list_mutex); 220 return; 221 } 222 last = cur; 223 cur = cur->next; 224 } 225 226 SDL_UnlockMutex(haptic_list_mutex); 227} 228 229void SDL_HIDAPI_HapticQuit(void) 230{ 231 // the list is cleared in SDL_haptic.c 232 if (haptic_list_mutex != NULL) { 233 SDL_DestroyMutex(haptic_list_mutex); 234 haptic_list_mutex = NULL; 235 } 236} 237 238SDL_HapticEffectID SDL_HIDAPI_HapticNewEffect(SDL_Haptic *haptic, const SDL_HapticEffect *base) 239{ 240 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 241 return device->driver->CreateEffect(device, base); 242} 243 244bool SDL_HIDAPI_HapticUpdateEffect(SDL_Haptic *haptic, SDL_HapticEffectID id, const SDL_HapticEffect *data) 245{ 246 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 247 return device->driver->UpdateEffect(device, id, data); 248} 249 250bool SDL_HIDAPI_HapticRunEffect(SDL_Haptic *haptic, SDL_HapticEffectID id, Uint32 iterations) 251{ 252 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 253 return device->driver->RunEffect(device, id, iterations); 254} 255 256bool SDL_HIDAPI_HapticStopEffect(SDL_Haptic *haptic, SDL_HapticEffectID id) 257{ 258 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 259 return device->driver->StopEffect(device, id); 260} 261 262void SDL_HIDAPI_HapticDestroyEffect(SDL_Haptic *haptic, SDL_HapticEffectID id) 263{ 264 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 265 device->driver->DestroyEffect(device, id); 266} 267 268bool SDL_HIDAPI_HapticGetEffectStatus(SDL_Haptic *haptic, SDL_HapticEffectID id) 269{ 270 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 271 return device->driver->GetEffectStatus(device, id); 272} 273 274bool SDL_HIDAPI_HapticSetGain(SDL_Haptic *haptic, int gain) 275{ 276 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 277 return device->driver->SetGain(device, gain); 278} 279 280bool SDL_HIDAPI_HapticSetAutocenter(SDL_Haptic *haptic, int autocenter) 281{ 282 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 283 return device->driver->SetAutocenter(device, autocenter); 284} 285 286bool SDL_HIDAPI_HapticPause(SDL_Haptic *haptic) 287{ 288 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 289 return device->driver->Pause(device); 290} 291 292bool SDL_HIDAPI_HapticResume(SDL_Haptic *haptic) 293{ 294 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 295 return device->driver->Resume(device); 296} 297 298bool SDL_HIDAPI_HapticStopAll(SDL_Haptic *haptic) 299{ 300 SDL_HIDAPI_HapticDevice *device = (SDL_HIDAPI_HapticDevice *)haptic->hwdata; 301 return device->driver->StopEffects(device); 302} 303 304#endif //SDL_JOYSTICK_HIDAPI 305[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.