Atlas - SDL_sensor.c

Home / ext / SDL / src / sensor Lines: 1 | Size: 15809 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[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// This is the sensor API for Simple DirectMedia Layer 24 25#include "SDL_syssensor.h" 26 27#include "../events/SDL_events_c.h" 28#include "../joystick/SDL_gamepad_c.h" 29 30static SDL_SensorDriver *SDL_sensor_drivers[] = { 31#ifdef SDL_SENSOR_ANDROID 32 &SDL_ANDROID_SensorDriver, 33#endif 34#ifdef SDL_SENSOR_COREMOTION 35 &SDL_COREMOTION_SensorDriver, 36#endif 37#ifdef SDL_SENSOR_WINDOWS 38 &SDL_WINDOWS_SensorDriver, 39#endif 40#ifdef SDL_SENSOR_VITA 41 &SDL_VITA_SensorDriver, 42#endif 43#ifdef SDL_SENSOR_N3DS 44 &SDL_N3DS_SensorDriver, 45#endif 46#ifdef SDL_SENSOR_EMSCRIPTEN 47 &SDL_EMSCRIPTEN_SensorDriver, 48#endif 49#if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED) 50 &SDL_DUMMY_SensorDriver 51#endif 52}; 53 54#ifndef SDL_THREAD_SAFETY_ANALYSIS 55static 56#endif 57SDL_Mutex *SDL_sensor_lock = NULL; // This needs to support recursive locks 58static SDL_AtomicInt SDL_sensor_lock_pending; 59static int SDL_sensors_locked; 60static bool SDL_sensors_initialized; 61static SDL_Sensor *SDL_sensors SDL_GUARDED_BY(SDL_sensor_lock) = NULL; 62 63#define CHECK_SENSOR_MAGIC(sensor, result) \ 64 CHECK_PARAM(!SDL_ObjectValid(sensor, SDL_OBJECT_TYPE_SENSOR)) { \ 65 SDL_InvalidParamError("sensor"); \ 66 SDL_UnlockSensors(); \ 67 return result; \ 68 } 69 70bool SDL_SensorsInitialized(void) 71{ 72 return SDL_sensors_initialized; 73} 74 75void SDL_LockSensors(void) 76{ 77 (void)SDL_AtomicIncRef(&SDL_sensor_lock_pending); 78 SDL_LockMutex(SDL_sensor_lock); 79 (void)SDL_AtomicDecRef(&SDL_sensor_lock_pending); 80 81 ++SDL_sensors_locked; 82} 83 84void SDL_UnlockSensors(void) 85{ 86 bool last_unlock = false; 87 88 --SDL_sensors_locked; 89 90 if (!SDL_sensors_initialized) { 91 // NOTE: There's a small window here where another thread could lock the mutex after we've checked for pending locks 92 if (!SDL_sensors_locked && SDL_GetAtomicInt(&SDL_sensor_lock_pending) == 0) { 93 last_unlock = true; 94 } 95 } 96 97 /* The last unlock after sensors are uninitialized will cleanup the mutex, 98 * allowing applications to lock sensors while reinitializing the system. 99 */ 100 if (last_unlock) { 101 SDL_Mutex *sensor_lock = SDL_sensor_lock; 102 103 SDL_LockMutex(sensor_lock); 104 { 105 SDL_UnlockMutex(SDL_sensor_lock); 106 107 SDL_sensor_lock = NULL; 108 } 109 SDL_UnlockMutex(sensor_lock); 110 SDL_DestroyMutex(sensor_lock); 111 } else { 112 SDL_UnlockMutex(SDL_sensor_lock); 113 } 114} 115 116bool SDL_SensorsLocked(void) 117{ 118 return (SDL_sensors_locked > 0); 119} 120 121void SDL_AssertSensorsLocked(void) 122{ 123 SDL_assert(SDL_SensorsLocked()); 124} 125 126bool SDL_InitSensors(void) 127{ 128 int i; 129 bool status; 130 131 // Create the sensor list lock 132 if (SDL_sensor_lock == NULL) { 133 SDL_sensor_lock = SDL_CreateMutex(); 134 } 135 136 if (!SDL_InitSubSystem(SDL_INIT_EVENTS)) { 137 return false; 138 } 139 140 SDL_LockSensors(); 141 142 SDL_sensors_initialized = true; 143 144 status = false; 145 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 146 if (SDL_sensor_drivers[i]->Init()) { 147 status = true; 148 } 149 } 150 151 SDL_UnlockSensors(); 152 153 if (!status) { 154 SDL_QuitSensors(); 155 } 156 157 return status; 158} 159 160bool SDL_SensorsOpened(void) 161{ 162 bool opened; 163 164 SDL_LockSensors(); 165 { 166 if (SDL_sensors != NULL) { 167 opened = true; 168 } else { 169 opened = false; 170 } 171 } 172 SDL_UnlockSensors(); 173 174 return opened; 175} 176 177SDL_SensorID *SDL_GetSensors(int *count) 178{ 179 int i, num_sensors, device_index; 180 int sensor_index = 0, total_sensors = 0; 181 SDL_SensorID *sensors; 182 183 SDL_LockSensors(); 184 { 185 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 186 total_sensors += SDL_sensor_drivers[i]->GetCount(); 187 } 188 189 sensors = (SDL_SensorID *)SDL_malloc((total_sensors + 1) * sizeof(*sensors)); 190 if (sensors) { 191 if (count) { 192 *count = total_sensors; 193 } 194 195 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 196 num_sensors = SDL_sensor_drivers[i]->GetCount(); 197 for (device_index = 0; device_index < num_sensors; ++device_index) { 198 SDL_assert(sensor_index < total_sensors); 199 sensors[sensor_index] = SDL_sensor_drivers[i]->GetDeviceInstanceID(device_index); 200 SDL_assert(sensors[sensor_index] > 0); 201 ++sensor_index; 202 } 203 } 204 SDL_assert(sensor_index == total_sensors); 205 sensors[sensor_index] = 0; 206 } else { 207 if (count) { 208 *count = 0; 209 } 210 } 211 } 212 SDL_UnlockSensors(); 213 214 return sensors; 215} 216 217/* 218 * Get the driver and device index for a sensor instance ID 219 * This should be called while the sensor lock is held, to prevent another thread from updating the list 220 */ 221static bool SDL_GetDriverAndSensorIndex(SDL_SensorID instance_id, SDL_SensorDriver **driver, int *driver_index) 222{ 223 int i, num_sensors, device_index; 224 225 if (instance_id > 0) { 226 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 227 num_sensors = SDL_sensor_drivers[i]->GetCount(); 228 for (device_index = 0; device_index < num_sensors; ++device_index) { 229 SDL_SensorID sensor_id = SDL_sensor_drivers[i]->GetDeviceInstanceID(device_index); 230 if (sensor_id == instance_id) { 231 *driver = SDL_sensor_drivers[i]; 232 *driver_index = device_index; 233 return true; 234 } 235 } 236 } 237 } 238 SDL_SetError("Sensor %" SDL_PRIu32 " not found", instance_id); 239 return false; 240} 241 242/* 243 * Get the implementation dependent name of a sensor 244 */ 245const char *SDL_GetSensorNameForID(SDL_SensorID instance_id) 246{ 247 SDL_SensorDriver *driver; 248 int device_index; 249 const char *name = NULL; 250 251 SDL_LockSensors(); 252 if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) { 253 name = SDL_GetPersistentString(driver->GetDeviceName(device_index)); 254 } 255 SDL_UnlockSensors(); 256 257 return name; 258} 259 260SDL_SensorType SDL_GetSensorTypeForID(SDL_SensorID instance_id) 261{ 262 SDL_SensorDriver *driver; 263 int device_index; 264 SDL_SensorType type = SDL_SENSOR_INVALID; 265 266 SDL_LockSensors(); 267 if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) { 268 type = driver->GetDeviceType(device_index); 269 } 270 SDL_UnlockSensors(); 271 272 return type; 273} 274 275int SDL_GetSensorNonPortableTypeForID(SDL_SensorID instance_id) 276{ 277 SDL_SensorDriver *driver; 278 int device_index; 279 int type = -1; 280 281 SDL_LockSensors(); 282 if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) { 283 type = driver->GetDeviceNonPortableType(device_index); 284 } 285 SDL_UnlockSensors(); 286 287 return type; 288} 289 290/* 291 * Open a sensor for use - the index passed as an argument refers to 292 * the N'th sensor on the system. This index is the value which will 293 * identify this sensor in future sensor events. 294 * 295 * This function returns a sensor identifier, or NULL if an error occurred. 296 */ 297SDL_Sensor *SDL_OpenSensor(SDL_SensorID instance_id) 298{ 299 SDL_SensorDriver *driver; 300 int device_index; 301 SDL_Sensor *sensor; 302 SDL_Sensor *sensorlist; 303 const char *sensorname = NULL; 304 305 SDL_LockSensors(); 306 307 if (!SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) { 308 SDL_UnlockSensors(); 309 return NULL; 310 } 311 312 sensorlist = SDL_sensors; 313 /* If the sensor is already open, return it 314 * it is important that we have a single sensor * for each instance id 315 */ 316 while (sensorlist) { 317 if (instance_id == sensorlist->instance_id) { 318 sensor = sensorlist; 319 ++sensor->ref_count; 320 SDL_UnlockSensors(); 321 return sensor; 322 } 323 sensorlist = sensorlist->next; 324 } 325 326 // Create and initialize the sensor 327 sensor = (SDL_Sensor *)SDL_calloc(1, sizeof(*sensor)); 328 if (!sensor) { 329 SDL_UnlockSensors(); 330 return NULL; 331 } 332 SDL_SetObjectValid(sensor, SDL_OBJECT_TYPE_SENSOR, true); 333 sensor->driver = driver; 334 sensor->instance_id = instance_id; 335 sensor->type = driver->GetDeviceType(device_index); 336 sensor->non_portable_type = driver->GetDeviceNonPortableType(device_index); 337 338 if (!driver->Open(sensor, device_index)) { 339 SDL_SetObjectValid(sensor, SDL_OBJECT_TYPE_SENSOR, false); 340 SDL_free(sensor); 341 SDL_UnlockSensors(); 342 return NULL; 343 } 344 345 sensorname = driver->GetDeviceName(device_index); 346 if (sensorname) { 347 sensor->name = SDL_strdup(sensorname); 348 } else { 349 sensor->name = NULL; 350 } 351 352 // Add sensor to list 353 ++sensor->ref_count; 354 // Link the sensor in the list 355 sensor->next = SDL_sensors; 356 SDL_sensors = sensor; 357 358 driver->Update(sensor); 359 360 SDL_UnlockSensors(); 361 362 return sensor; 363} 364 365/* 366 * Find the SDL_Sensor that owns this instance id 367 */ 368SDL_Sensor *SDL_GetSensorFromID(SDL_SensorID instance_id) 369{ 370 SDL_Sensor *sensor; 371 372 SDL_LockSensors(); 373 for (sensor = SDL_sensors; sensor; sensor = sensor->next) { 374 if (sensor->instance_id == instance_id) { 375 break; 376 } 377 } 378 SDL_UnlockSensors(); 379 return sensor; 380} 381 382/* 383 * Get the properties associated with a sensor. 384 */ 385SDL_PropertiesID SDL_GetSensorProperties(SDL_Sensor *sensor) 386{ 387 SDL_PropertiesID result; 388 389 SDL_LockSensors(); 390 { 391 CHECK_SENSOR_MAGIC(sensor, 0); 392 393 if (sensor->props == 0) { 394 sensor->props = SDL_CreateProperties(); 395 } 396 result = sensor->props; 397 } 398 SDL_UnlockSensors(); 399 400 return result; 401} 402 403/* 404 * Get the friendly name of this sensor 405 */ 406const char *SDL_GetSensorName(SDL_Sensor *sensor) 407{ 408 const char *result; 409 410 SDL_LockSensors(); 411 { 412 CHECK_SENSOR_MAGIC(sensor, NULL); 413 414 result = SDL_GetPersistentString(sensor->name); 415 } 416 SDL_UnlockSensors(); 417 418 return result; 419} 420 421/* 422 * Get the type of this sensor 423 */ 424SDL_SensorType SDL_GetSensorType(SDL_Sensor *sensor) 425{ 426 SDL_SensorType result; 427 428 SDL_LockSensors(); 429 { 430 CHECK_SENSOR_MAGIC(sensor, SDL_SENSOR_INVALID); 431 432 result = sensor->type; 433 } 434 SDL_UnlockSensors(); 435 436 return result; 437} 438 439/* 440 * Get the platform dependent type of this sensor 441 */ 442int SDL_GetSensorNonPortableType(SDL_Sensor *sensor) 443{ 444 int result; 445 446 SDL_LockSensors(); 447 { 448 CHECK_SENSOR_MAGIC(sensor, -1); 449 450 result = sensor->non_portable_type; 451 } 452 SDL_UnlockSensors(); 453 454 return result; 455} 456 457/* 458 * Get the instance id for this opened sensor 459 */ 460SDL_SensorID SDL_GetSensorID(SDL_Sensor *sensor) 461{ 462 SDL_SensorID result; 463 464 SDL_LockSensors(); 465 { 466 CHECK_SENSOR_MAGIC(sensor, 0); 467 468 result = sensor->instance_id; 469 } 470 SDL_UnlockSensors(); 471 472 return result; 473} 474 475/* 476 * Get the current state of this sensor 477 */ 478bool SDL_GetSensorData(SDL_Sensor *sensor, float *data, int num_values) 479{ 480 SDL_LockSensors(); 481 { 482 CHECK_SENSOR_MAGIC(sensor, false); 483 484 num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); 485 SDL_memcpy(data, sensor->data, num_values * sizeof(*data)); 486 } 487 SDL_UnlockSensors(); 488 489 return true; 490} 491 492/* 493 * Close a sensor previously opened with SDL_OpenSensor() 494 */ 495void SDL_CloseSensor(SDL_Sensor *sensor) 496{ 497 SDL_Sensor *sensorlist; 498 SDL_Sensor *sensorlistprev; 499 500 SDL_LockSensors(); 501 { 502 CHECK_SENSOR_MAGIC(sensor,); 503 504 // First decrement ref count 505 if (--sensor->ref_count > 0) { 506 SDL_UnlockSensors(); 507 return; 508 } 509 510 SDL_DestroyProperties(sensor->props); 511 512 sensor->driver->Close(sensor); 513 sensor->hwdata = NULL; 514 SDL_SetObjectValid(sensor, SDL_OBJECT_TYPE_SENSOR, false); 515 516 sensorlist = SDL_sensors; 517 sensorlistprev = NULL; 518 while (sensorlist) { 519 if (sensor == sensorlist) { 520 if (sensorlistprev) { 521 // unlink this entry 522 sensorlistprev->next = sensorlist->next; 523 } else { 524 SDL_sensors = sensor->next; 525 } 526 break; 527 } 528 sensorlistprev = sensorlist; 529 sensorlist = sensorlist->next; 530 } 531 532 // Free the data associated with this sensor 533 SDL_free(sensor->name); 534 SDL_free(sensor); 535 } 536 SDL_UnlockSensors(); 537} 538 539void SDL_QuitSensors(void) 540{ 541 int i; 542 543 SDL_LockSensors(); 544 545 // Stop the event polling 546 while (SDL_sensors) { 547 SDL_sensors->ref_count = 1; 548 SDL_CloseSensor(SDL_sensors); 549 } 550 551 // Quit the sensor setup 552 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 553 SDL_sensor_drivers[i]->Quit(); 554 } 555 556 SDL_QuitSubSystem(SDL_INIT_EVENTS); 557 558 SDL_sensors_initialized = false; 559 560 SDL_UnlockSensors(); 561} 562 563// These are global for SDL_syssensor.c and SDL_events.c 564 565void SDL_SendSensorUpdate(Uint64 timestamp, SDL_Sensor *sensor, Uint64 sensor_timestamp, float *data, int num_values) 566{ 567 SDL_AssertSensorsLocked(); 568 569 // Allow duplicate events, for things like steps and heartbeats 570 571 // Update internal sensor state 572 num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); 573 SDL_memcpy(sensor->data, data, num_values * sizeof(*data)); 574 575 // Post the event, if desired 576 if (SDL_EventEnabled(SDL_EVENT_SENSOR_UPDATE)) { 577 SDL_Event event; 578 event.type = SDL_EVENT_SENSOR_UPDATE; 579 event.common.timestamp = timestamp; 580 event.sensor.which = sensor->instance_id; 581 num_values = SDL_min(num_values, SDL_arraysize(event.sensor.data)); 582 SDL_memset(event.sensor.data, 0, sizeof(event.sensor.data)); 583 SDL_memcpy(event.sensor.data, data, num_values * sizeof(*data)); 584 event.sensor.sensor_timestamp = sensor_timestamp; 585 SDL_PushEvent(&event); 586 } 587 588 SDL_GamepadSensorWatcher(timestamp, sensor->instance_id, sensor_timestamp, data, num_values); 589} 590 591void SDL_UpdateSensor(SDL_Sensor *sensor) 592{ 593 SDL_LockSensors(); 594 { 595 CHECK_SENSOR_MAGIC(sensor,); 596 597 sensor->driver->Update(sensor); 598 } 599 SDL_UnlockSensors(); 600} 601 602void SDL_UpdateSensors(void) 603{ 604 int i; 605 SDL_Sensor *sensor; 606 607 if (!SDL_WasInit(SDL_INIT_SENSOR)) { 608 return; 609 } 610 611 SDL_LockSensors(); 612 613 for (sensor = SDL_sensors; sensor; sensor = sensor->next) { 614 sensor->driver->Update(sensor); 615 } 616 617 /* this needs to happen AFTER walking the sensor list above, so that any 618 dangling hardware data from removed devices can be free'd 619 */ 620 for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) { 621 SDL_sensor_drivers[i]->Detect(); 622 } 623 624 SDL_UnlockSensors(); 625} 626
[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.