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