SDL_syshaptic.c (8629B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 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 #ifdef SDL_HAPTIC_ANDROID 24 25 #include "SDL_timer.h" 26 #include "SDL_syshaptic_c.h" 27 #include "../SDL_syshaptic.h" 28 #include "SDL_haptic.h" 29 #include "../../core/android/SDL_android.h" 30 #include "SDL_joystick.h" 31 #include "../../joystick/SDL_sysjoystick.h" /* For the real SDL_Joystick */ 32 #include "../../joystick/android/SDL_sysjoystick_c.h" /* For joystick hwdata */ 33 34 35 typedef struct SDL_hapticlist_item 36 { 37 int device_id; 38 char *name; 39 SDL_Haptic *haptic; 40 struct SDL_hapticlist_item *next; 41 } SDL_hapticlist_item; 42 43 static SDL_hapticlist_item *SDL_hapticlist = NULL; 44 static SDL_hapticlist_item *SDL_hapticlist_tail = NULL; 45 static int numhaptics = 0; 46 47 48 int 49 SDL_SYS_HapticInit(void) 50 { 51 /* Support for device connect/disconnect is API >= 16 only, 52 * so we poll every three seconds 53 * Ref: http://developer.android.com/reference/android/hardware/input/InputManager.InputDeviceListener.html 54 */ 55 static Uint32 timeout = 0; 56 if (SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) { 57 timeout = SDL_GetTicks() + 3000; 58 Android_JNI_PollHapticDevices(); 59 } 60 return (numhaptics); 61 } 62 63 int 64 SDL_SYS_NumHaptics(void) 65 { 66 return (numhaptics); 67 } 68 69 static SDL_hapticlist_item * 70 HapticByOrder(int index) 71 { 72 SDL_hapticlist_item *item = SDL_hapticlist; 73 if ((index < 0) || (index >= numhaptics)) { 74 return NULL; 75 } 76 while (index > 0) { 77 SDL_assert(item != NULL); 78 --index; 79 item = item->next; 80 } 81 return item; 82 } 83 84 static SDL_hapticlist_item * 85 HapticByDevId (int device_id) 86 { 87 SDL_hapticlist_item *item; 88 for (item = SDL_hapticlist; item != NULL; item = item->next) { 89 if (device_id == item->device_id) { 90 /*SDL_Log("=+=+=+=+=+= HapticByDevId id [%d]", device_id);*/ 91 return item; 92 } 93 } 94 return NULL; 95 } 96 97 const char * 98 SDL_SYS_HapticName(int index) 99 { 100 SDL_hapticlist_item *item = HapticByOrder(index); 101 if (item == NULL ) { 102 SDL_SetError("No such device"); 103 return NULL; 104 } 105 return item->name; 106 } 107 108 109 static SDL_hapticlist_item * 110 OpenHaptic(SDL_Haptic *haptic, SDL_hapticlist_item *item) 111 { 112 if (item == NULL ) { 113 SDL_SetError("No such device"); 114 return NULL; 115 } 116 if (item->haptic != NULL) { 117 SDL_SetError("Haptic already opened"); 118 return NULL; 119 } 120 121 haptic->hwdata = (struct haptic_hwdata *)item; 122 item->haptic = haptic; 123 124 haptic->supported = SDL_HAPTIC_LEFTRIGHT; 125 haptic->neffects = 1; 126 haptic->nplaying = haptic->neffects; 127 haptic->effects = (struct haptic_effect *)SDL_malloc (sizeof (struct haptic_effect) * haptic->neffects); 128 if (haptic->effects == NULL) { 129 SDL_OutOfMemory(); 130 return NULL; 131 } 132 SDL_memset(haptic->effects, 0, sizeof (struct haptic_effect) * haptic->neffects); 133 return item; 134 } 135 136 static SDL_hapticlist_item * 137 OpenHapticByOrder(SDL_Haptic *haptic, int index) 138 { 139 return OpenHaptic (haptic, HapticByOrder(index)); 140 } 141 142 static SDL_hapticlist_item * 143 OpenHapticByDevId(SDL_Haptic *haptic, int device_id) 144 { 145 return OpenHaptic (haptic, HapticByDevId(device_id)); 146 } 147 148 int 149 SDL_SYS_HapticOpen(SDL_Haptic *haptic) 150 { 151 return (OpenHapticByOrder(haptic, haptic->index) == NULL ? -1 : 0); 152 } 153 154 155 int 156 SDL_SYS_HapticMouse(void) 157 { 158 return 0; 159 } 160 161 162 int 163 SDL_SYS_JoystickIsHaptic(SDL_Joystick *joystick) 164 { 165 SDL_hapticlist_item *item; 166 item = HapticByDevId(((joystick_hwdata *)joystick->hwdata)->device_id); 167 return (item != NULL) ? 1 : 0; 168 } 169 170 171 int 172 SDL_SYS_HapticOpenFromJoystick(SDL_Haptic *haptic, SDL_Joystick *joystick) 173 { 174 return (OpenHapticByDevId(haptic, ((joystick_hwdata *)joystick->hwdata)->device_id) == NULL ? -1 : 0); 175 } 176 177 178 int 179 SDL_SYS_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick) 180 { 181 return (((SDL_hapticlist_item *)haptic->hwdata)->device_id == ((joystick_hwdata *)joystick->hwdata)->device_id ? 1 : 0); 182 } 183 184 185 void 186 SDL_SYS_HapticClose(SDL_Haptic * haptic) 187 { 188 ((SDL_hapticlist_item *)haptic->hwdata)->haptic = NULL; 189 haptic->hwdata = NULL; 190 return; 191 } 192 193 194 void 195 SDL_SYS_HapticQuit(void) 196 { 197 /* We don't have any way to scan for joysticks (and their vibrators) at init, so don't wipe the list 198 * of joysticks here in case this is a reinit. 199 */ 200 #if 0 201 SDL_hapticlist_item *item = NULL; 202 SDL_hapticlist_item *next = NULL; 203 204 for (item = SDL_hapticlist; item; item = next) { 205 next = item->next; 206 SDL_free(item); 207 } 208 209 SDL_hapticlist = SDL_hapticlist_tail = NULL; 210 numhaptics = 0; 211 return; 212 #endif 213 } 214 215 216 int 217 SDL_SYS_HapticNewEffect(SDL_Haptic * haptic, 218 struct haptic_effect *effect, SDL_HapticEffect * base) 219 { 220 return 0; 221 } 222 223 224 int 225 SDL_SYS_HapticUpdateEffect(SDL_Haptic * haptic, 226 struct haptic_effect *effect, 227 SDL_HapticEffect * data) 228 { 229 return 0; 230 } 231 232 233 int 234 SDL_SYS_HapticRunEffect(SDL_Haptic * haptic, struct haptic_effect *effect, 235 Uint32 iterations) 236 { 237 float large = effect->effect.leftright.large_magnitude / 32767.0f; 238 float small = effect->effect.leftright.small_magnitude / 32767.0f; 239 240 float total = (large * 0.6f) + (small * 0.4f); 241 242 Android_JNI_HapticRun (((SDL_hapticlist_item *)haptic->hwdata)->device_id, total, effect->effect.leftright.length); 243 return 0; 244 } 245 246 247 int 248 SDL_SYS_HapticStopEffect(SDL_Haptic * haptic, struct haptic_effect *effect) 249 { 250 Android_JNI_HapticStop (((SDL_hapticlist_item *)haptic->hwdata)->device_id); 251 return 0; 252 } 253 254 255 void 256 SDL_SYS_HapticDestroyEffect(SDL_Haptic * haptic, struct haptic_effect *effect) 257 { 258 return; 259 } 260 261 262 int 263 SDL_SYS_HapticGetEffectStatus(SDL_Haptic * haptic, 264 struct haptic_effect *effect) 265 { 266 return 0; 267 } 268 269 270 int 271 SDL_SYS_HapticSetGain(SDL_Haptic * haptic, int gain) 272 { 273 return 0; 274 } 275 276 277 int 278 SDL_SYS_HapticSetAutocenter(SDL_Haptic * haptic, int autocenter) 279 { 280 return 0; 281 } 282 283 int 284 SDL_SYS_HapticPause(SDL_Haptic * haptic) 285 { 286 return 0; 287 } 288 289 int 290 SDL_SYS_HapticUnpause(SDL_Haptic * haptic) 291 { 292 return 0; 293 } 294 295 int 296 SDL_SYS_HapticStopAll(SDL_Haptic * haptic) 297 { 298 return 0; 299 } 300 301 302 303 int 304 Android_AddHaptic(int device_id, const char *name) 305 { 306 SDL_hapticlist_item *item; 307 item = (SDL_hapticlist_item *) SDL_calloc(1, sizeof (SDL_hapticlist_item)); 308 if (item == NULL) { 309 return -1; 310 } 311 312 item->device_id = device_id; 313 item->name = SDL_strdup (name); 314 if (item->name == NULL) { 315 SDL_free (item); 316 return -1; 317 } 318 319 if (SDL_hapticlist_tail == NULL) { 320 SDL_hapticlist = SDL_hapticlist_tail = item; 321 } else { 322 SDL_hapticlist_tail->next = item; 323 SDL_hapticlist_tail = item; 324 } 325 326 ++numhaptics; 327 return numhaptics; 328 } 329 330 int 331 Android_RemoveHaptic(int device_id) 332 { 333 SDL_hapticlist_item *item; 334 SDL_hapticlist_item *prev = NULL; 335 336 for (item = SDL_hapticlist; item != NULL; item = item->next) { 337 /* found it, remove it. */ 338 if (device_id == item->device_id) { 339 const int retval = item->haptic ? item->haptic->index : -1; 340 341 if (prev != NULL) { 342 prev->next = item->next; 343 } else { 344 SDL_assert(SDL_hapticlist == item); 345 SDL_hapticlist = item->next; 346 } 347 if (item == SDL_hapticlist_tail) { 348 SDL_hapticlist_tail = prev; 349 } 350 351 /* Need to decrement the haptic count */ 352 --numhaptics; 353 /* !!! TODO: Send a haptic remove event? */ 354 355 SDL_free(item->name); 356 SDL_free(item); 357 return retval; 358 } 359 prev = item; 360 } 361 return -1; 362 } 363 364 365 #endif /* SDL_HAPTIC_ANDROID */ 366 367 /* vi: set ts=4 sw=4 expandtab: */