SDL  2.0
SDL_sensor.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2018 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 /* This is the sensor API for Simple DirectMedia Layer */
24 
25 #include "SDL.h"
26 #include "SDL_atomic.h"
27 #include "SDL_events.h"
28 #include "SDL_syssensor.h"
29 #include "SDL_assert.h"
30 
31 #if !SDL_EVENTS_DISABLED
32 #include "../events/SDL_events_c.h"
33 #endif
34 
36 #ifdef SDL_SENSOR_ANDROID
38 #endif
39 #ifdef SDL_SENSOR_COREMOTION
41 #endif
42 #if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED)
44 #endif
45 };
46 static SDL_Sensor *SDL_sensors = NULL;
48 static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */
50 
51 static void
53 {
54  if (SDL_sensor_lock) {
55  SDL_LockMutex(SDL_sensor_lock);
56  }
57 }
58 
59 static void
61 {
62  if (SDL_sensor_lock) {
63  SDL_UnlockMutex(SDL_sensor_lock);
64  }
65 }
66 
67 
68 int
70 {
71  int i, status;
72 
73  /* Create the sensor list lock */
74  if (!SDL_sensor_lock) {
75  SDL_sensor_lock = SDL_CreateMutex();
76  }
77 
78 #if !SDL_EVENTS_DISABLED
80  return -1;
81  }
82 #endif /* !SDL_EVENTS_DISABLED */
83 
84  status = -1;
85  for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
86  if (SDL_sensor_drivers[i]->Init() >= 0) {
87  status = 0;
88  }
89  }
90  return status;
91 }
92 
93 /*
94  * Count the number of sensors attached to the system
95  */
96 int
98 {
99  int i, total_sensors = 0;
100  SDL_LockSensors();
101  for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
102  total_sensors += SDL_sensor_drivers[i]->GetCount();
103  }
105  return total_sensors;
106 }
107 
108 /*
109  * Return the next available sensor instance ID
110  * This may be called by drivers from multiple threads, unprotected by any locks
111  */
113 {
114  return SDL_AtomicIncRef(&SDL_next_sensor_instance_id);
115 }
116 
117 /*
118  * Get the driver and device index for an API device index
119  * This should be called while the sensor lock is held, to prevent another thread from updating the list
120  */
121 static SDL_bool
122 SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver **driver, int *driver_index)
123 {
124  int i, num_sensors, total_sensors = 0;
125 
126  if (device_index >= 0) {
127  for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
128  num_sensors = SDL_sensor_drivers[i]->GetCount();
129  if (device_index < num_sensors) {
130  *driver = SDL_sensor_drivers[i];
131  *driver_index = device_index;
132  return SDL_TRUE;
133  }
134  device_index -= num_sensors;
135  total_sensors += num_sensors;
136  }
137  }
138 
139  SDL_SetError("There are %d sensors available", total_sensors);
140  return SDL_FALSE;
141 }
142 
143 /*
144  * Get the implementation dependent name of a sensor
145  */
146 const char *
147 SDL_SensorGetDeviceName(int device_index)
148 {
149  SDL_SensorDriver *driver;
150  const char *name = NULL;
151 
152  SDL_LockSensors();
153  if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
154  name = driver->GetDeviceName(device_index);
155  }
157 
158  /* FIXME: Really we should reference count this name so it doesn't go away after unlock */
159  return name;
160 }
161 
163 SDL_SensorGetDeviceType(int device_index)
164 {
165  SDL_SensorDriver *driver;
167 
168  SDL_LockSensors();
169  if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
170  type = driver->GetDeviceType(device_index);
171  }
173 
174  return type;
175 }
176 
179 {
180  SDL_SensorDriver *driver;
181  int type = -1;
182 
183  SDL_LockSensors();
184  if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
185  type = driver->GetDeviceNonPortableType(device_index);
186  }
188 
189  return type;
190 }
191 
194 {
195  SDL_SensorDriver *driver;
196  SDL_SensorID instance_id = -1;
197 
198  SDL_LockSensors();
199  if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
200  instance_id = driver->GetDeviceInstanceID(device_index);
201  }
203 
204  return instance_id;
205 }
206 
207 /*
208  * Open a sensor for use - the index passed as an argument refers to
209  * the N'th sensor on the system. This index is the value which will
210  * identify this sensor in future sensor events.
211  *
212  * This function returns a sensor identifier, or NULL if an error occurred.
213  */
214 SDL_Sensor *
215 SDL_SensorOpen(int device_index)
216 {
217  SDL_SensorDriver *driver;
218  SDL_SensorID instance_id;
219  SDL_Sensor *sensor;
220  SDL_Sensor *sensorlist;
221  const char *sensorname = NULL;
222 
223  SDL_LockSensors();
224 
225  if (!SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
227  return NULL;
228  }
229 
230  sensorlist = SDL_sensors;
231  /* If the sensor is already open, return it
232  * it is important that we have a single sensor * for each instance id
233  */
234  instance_id = driver->GetDeviceInstanceID(device_index);
235  while (sensorlist) {
236  if (instance_id == sensorlist->instance_id) {
237  sensor = sensorlist;
238  ++sensor->ref_count;
240  return sensor;
241  }
242  sensorlist = sensorlist->next;
243  }
244 
245  /* Create and initialize the sensor */
246  sensor = (SDL_Sensor *) SDL_calloc(sizeof(*sensor), 1);
247  if (sensor == NULL) {
248  SDL_OutOfMemory();
250  return NULL;
251  }
252  sensor->driver = driver;
253  sensor->instance_id = instance_id;
254  sensor->type = driver->GetDeviceType(device_index);
255  sensor->non_portable_type = driver->GetDeviceNonPortableType(device_index);
256 
257  if (driver->Open(sensor, device_index) < 0) {
258  SDL_free(sensor);
260  return NULL;
261  }
262 
263  sensorname = driver->GetDeviceName(device_index);
264  if (sensorname) {
265  sensor->name = SDL_strdup(sensorname);
266  } else {
267  sensor->name = NULL;
268  }
269 
270  /* Add sensor to list */
271  ++sensor->ref_count;
272  /* Link the sensor in the list */
273  sensor->next = SDL_sensors;
274  SDL_sensors = sensor;
275 
277 
278  driver->Update(sensor);
279 
280  return sensor;
281 }
282 
283 /*
284  * Find the SDL_Sensor that owns this instance id
285  */
286 SDL_Sensor *
288 {
289  SDL_Sensor *sensor;
290 
291  SDL_LockSensors();
292  for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
293  if (sensor->instance_id == instance_id) {
294  break;
295  }
296  }
298  return sensor;
299 }
300 
301 /*
302  * Checks to make sure the sensor is valid.
303  */
304 static int
305 SDL_PrivateSensorValid(SDL_Sensor * sensor)
306 {
307  int valid;
308 
309  if (sensor == NULL) {
310  SDL_SetError("Sensor hasn't been opened yet");
311  valid = 0;
312  } else {
313  valid = 1;
314  }
315 
316  return valid;
317 }
318 
319 /*
320  * Get the friendly name of this sensor
321  */
322 const char *
323 SDL_SensorGetName(SDL_Sensor * sensor)
324 {
325  if (!SDL_PrivateSensorValid(sensor)) {
326  return NULL;
327  }
328 
329  return sensor->name;
330 }
331 
332 /*
333  * Get the type of this sensor
334  */
336 SDL_SensorGetType(SDL_Sensor * sensor)
337 {
338  if (!SDL_PrivateSensorValid(sensor)) {
339  return SDL_SENSOR_INVALID;
340  }
341 
342  return sensor->type;
343 }
344 
345 /*
346  * Get the platform dependent type of this sensor
347  */
348 int
349 SDL_SensorGetNonPortableType(SDL_Sensor * sensor)
350 {
351  if (!SDL_PrivateSensorValid(sensor)) {
352  return -1;
353  }
354 
355  return sensor->non_portable_type;
356 }
357 
358 /*
359  * Get the instance id for this opened sensor
360  */
362 SDL_SensorGetInstanceID(SDL_Sensor * sensor)
363 {
364  if (!SDL_PrivateSensorValid(sensor)) {
365  return -1;
366  }
367 
368  return sensor->instance_id;
369 }
370 
371 /*
372  * Get the current state of this sensor
373  */
374 int
375 SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values)
376 {
377  if (!SDL_PrivateSensorValid(sensor)) {
378  return -1;
379  }
380 
381  num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
382  SDL_memcpy(data, sensor->data, num_values*sizeof(*data));
383  return 0;
384 }
385 
386 /*
387  * Close a sensor previously opened with SDL_SensorOpen()
388  */
389 void
390 SDL_SensorClose(SDL_Sensor * sensor)
391 {
392  SDL_Sensor *sensorlist;
393  SDL_Sensor *sensorlistprev;
394 
395  if (!SDL_PrivateSensorValid(sensor)) {
396  return;
397  }
398 
399  SDL_LockSensors();
400 
401  /* First decrement ref count */
402  if (--sensor->ref_count > 0) {
404  return;
405  }
406 
407  if (SDL_updating_sensor) {
409  return;
410  }
411 
412  sensor->driver->Close(sensor);
413  sensor->hwdata = NULL;
414 
415  sensorlist = SDL_sensors;
416  sensorlistprev = NULL;
417  while (sensorlist) {
418  if (sensor == sensorlist) {
419  if (sensorlistprev) {
420  /* unlink this entry */
421  sensorlistprev->next = sensorlist->next;
422  } else {
423  SDL_sensors = sensor->next;
424  }
425  break;
426  }
427  sensorlistprev = sensorlist;
428  sensorlist = sensorlist->next;
429  }
430 
431  SDL_free(sensor->name);
432 
433  /* Free the data associated with this sensor */
434  SDL_free(sensor);
435 
437 }
438 
439 void
441 {
442  int i;
443 
444  /* Make sure we're not getting called in the middle of updating sensors */
446 
447  SDL_LockSensors();
448 
449  /* Stop the event polling */
450  while (SDL_sensors) {
451  SDL_sensors->ref_count = 1;
453  }
454 
455  /* Quit the sensor setup */
456  for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
457  SDL_sensor_drivers[i]->Quit();
458  }
459 
461 
462 #if !SDL_EVENTS_DISABLED
464 #endif
465 
466  if (SDL_sensor_lock) {
467  SDL_DestroyMutex(SDL_sensor_lock);
468  SDL_sensor_lock = NULL;
469  }
470 }
471 
472 
473 /* These are global for SDL_syssensor.c and SDL_events.c */
474 
475 int
476 SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values)
477 {
478  int posted;
479 
480  /* Allow duplicate events, for things like steps and heartbeats */
481 
482  /* Update internal sensor state */
483  num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
484  SDL_memcpy(sensor->data, data, num_values*sizeof(*data));
485 
486  /* Post the event, if desired */
487  posted = 0;
488 #if !SDL_EVENTS_DISABLED
491  event.type = SDL_SENSORUPDATE;
492  event.sensor.which = sensor->instance_id;
493  num_values = SDL_min(num_values, SDL_arraysize(event.sensor.data));
494  SDL_memset(event.sensor.data, 0, sizeof(event.sensor.data));
495  SDL_memcpy(event.sensor.data, data, num_values*sizeof(*data));
496  posted = SDL_PushEvent(&event) == 1;
497  }
498 #endif /* !SDL_EVENTS_DISABLED */
499  return posted;
500 }
501 
502 void
504 {
505  int i;
506  SDL_Sensor *sensor;
507 
508  SDL_LockSensors();
509 
510  if (SDL_updating_sensor) {
511  /* The sensors are already being updated */
513  return;
514  }
515 
517 
518  /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
520 
521  for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
522  sensor->driver->Update(sensor);
523  }
524 
525  SDL_LockSensors();
526 
528 
529  /* If any sensors were closed while updating, free them here */
530  for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
531  if (sensor->ref_count <= 0) {
532  SDL_SensorClose(sensor);
533  }
534  }
535 
536  /* this needs to happen AFTER walking the sensor list above, so that any
537  dangling hardware data from removed devices can be free'd
538  */
539  for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
540  SDL_sensor_drivers[i]->Detect();
541  }
542 
544 }
545 
546 /* vi: set ts=4 sw=4 expandtab: */
SDL_SensorID(* GetDeviceInstanceID)(int device_index)
Definition: SDL_syssensor.h:75
#define SDL_INIT_EVENTS
Definition: SDL.h:83
#define SDL_LockMutex
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
static SDL_mutex * SDL_sensor_lock
Definition: SDL_sensor.c:48
int SDL_SensorGetData(SDL_Sensor *sensor, float *data, int num_values)
Definition: SDL_sensor.c:375
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:198
int(* GetDeviceNonPortableType)(int device_index)
Definition: SDL_syssensor.h:72
#define SDL_CreateMutex
#define SDL_QuitSubSystem
void SDL_SensorClose(SDL_Sensor *sensor)
Definition: SDL_sensor.c:390
int(* Open)(SDL_Sensor *sensor, int device_index)
Definition: SDL_syssensor.h:81
SDL_SensorType SDL_SensorGetType(SDL_Sensor *sensor)
Get the type of a sensor.
Definition: SDL_sensor.c:336
SDL_SensorDriver SDL_ANDROID_SensorDriver
#define SDL_ENABLE
Definition: SDL_events.h:756
SDL_SensorType(* GetDeviceType)(int device_index)
Definition: SDL_syssensor.h:69
#define SDL_InitSubSystem
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
const char *(* GetDeviceName)(int device_index)
Definition: SDL_syssensor.h:66
int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values)
Definition: SDL_sensor.c:476
void(* Quit)(void)
Definition: SDL_syssensor.h:94
SDL_SensorDriver SDL_DUMMY_SensorDriver
void(* Update)(SDL_Sensor *sensor)
Definition: SDL_syssensor.h:88
GLuint const GLchar * name
int SDL_SensorGetNonPortableType(SDL_Sensor *sensor)
Get the platform dependent type of a sensor.
Definition: SDL_sensor.c:349
static void SDL_LockSensors(void)
Definition: SDL_sensor.c:52
SDL_SensorEvent sensor
Definition: SDL_events.h:578
#define SDL_memcpy
Sint32 SDL_SensorID
Definition: SDL_sensor.h:60
#define SDL_GetEventState(type)
Definition: SDL_events.h:769
void(* Detect)(void)
Definition: SDL_syssensor.h:63
#define SDL_free
struct _cl_event * event
static SDL_bool SDL_updating_sensor
Definition: SDL_sensor.c:47
int SDL_NumSensors(void)
Count the number of sensors attached to the system right now.
Definition: SDL_sensor.c:97
SDL_SensorID SDL_GetNextSensorInstanceID()
Definition: SDL_sensor.c:112
SDL_SensorType SDL_SensorGetDeviceNonPortableType(int device_index)
Get the platform dependent type of a sensor.
Definition: SDL_sensor.c:178
SDL_Sensor * SDL_SensorOpen(int device_index)
Open a sensor for use.
Definition: SDL_sensor.c:215
SDL_SensorID SDL_SensorGetDeviceInstanceID(int device_index)
Get the instance ID of a sensor.
Definition: SDL_sensor.c:193
void SDL_SensorUpdate(void)
Definition: SDL_sensor.c:503
#define SDL_PushEvent
SDL_SensorType SDL_SensorGetDeviceType(int device_index)
Get the type of a sensor.
Definition: SDL_sensor.c:163
static SDL_atomic_t SDL_next_sensor_instance_id
Definition: SDL_sensor.c:49
static SDL_Sensor * SDL_sensors
Definition: SDL_sensor.c:46
int SDL_SensorInit(void)
Definition: SDL_sensor.c:69
const char * SDL_SensorGetDeviceName(int device_index)
Get the implementation dependent name of a sensor.
Definition: SDL_sensor.c:147
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:234
SDL_SensorID SDL_SensorGetInstanceID(SDL_Sensor *sensor)
Get the instance ID of a sensor.
Definition: SDL_sensor.c:362
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
Definition: SDL_stdinc.h:161
float data[6]
Definition: SDL_events.h:503
SDL_SensorType
Definition: SDL_sensor.h:69
#define SDL_SetError
SDL_SensorDriver SDL_COREMOTION_SensorDriver
#define SDL_DestroyMutex
#define SDL_calloc
#define SDL_strdup
static SDL_SensorDriver * SDL_sensor_drivers[]
Definition: SDL_sensor.c:35
void SDL_SensorQuit(void)
Definition: SDL_sensor.c:440
static SDL_bool SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver **driver, int *driver_index)
Definition: SDL_sensor.c:122
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
static void SDL_UnlockSensors(void)
Definition: SDL_sensor.c:60
#define SDL_UnlockMutex
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
General event structure.
Definition: SDL_events.h:557
static int SDL_PrivateSensorValid(SDL_Sensor *sensor)
Definition: SDL_sensor.c:305
const char * SDL_SensorGetName(SDL_Sensor *sensor)
Get the implementation dependent name of a sensor.
Definition: SDL_sensor.c:323
SDL_Sensor * SDL_SensorFromInstanceID(SDL_SensorID instance_id)
Definition: SDL_sensor.c:287
#define SDL_memset
int(* GetCount)(void)
Definition: SDL_syssensor.h:60