SDL_sensor.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../SDL_internal.h"
/* This is the sensor API for Simple DirectMedia Layer */
#include "SDL.h"
#include "SDL_atomic.h"
#include "SDL_events.h"
#include "SDL_syssensor.h"
#include "SDL_assert.h"
#if !SDL_EVENTS_DISABLED
#include "../events/SDL_events_c.h"
#endif
static SDL_SensorDriver *SDL_sensor_drivers[] = {
#ifdef SDL_SENSOR_ANDROID
&SDL_ANDROID_SensorDriver,
#endif
#ifdef SDL_SENSOR_COREMOTION
&SDL_COREMOTION_SensorDriver,
#endif
#if defined(SDL_SENSOR_DUMMY) || defined(SDL_SENSOR_DISABLED)
&SDL_DUMMY_SensorDriver
#endif
};
static SDL_Sensor *SDL_sensors = NULL;
static SDL_bool SDL_updating_sensor = SDL_FALSE;
static SDL_mutex *SDL_sensor_lock = NULL; /* This needs to support recursive locks */
static SDL_atomic_t SDL_next_sensor_instance_id;
static void
SDL_LockSensors(void)
{
if (SDL_sensor_lock) {
SDL_LockMutex(SDL_sensor_lock);
}
}
static void
SDL_UnlockSensors(void)
{
if (SDL_sensor_lock) {
SDL_UnlockMutex(SDL_sensor_lock);
}
}
int
SDL_SensorInit(void)
{
int i, status;
/* Create the sensor list lock */
if (!SDL_sensor_lock) {
SDL_sensor_lock = SDL_CreateMutex();
}
#if !SDL_EVENTS_DISABLED
if (SDL_InitSubSystem(SDL_INIT_EVENTS) < 0) {
return -1;
}
#endif /* !SDL_EVENTS_DISABLED */
status = -1;
for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
if (SDL_sensor_drivers[i]->Init() >= 0) {
status = 0;
}
}
return status;
}
/*
* Count the number of sensors attached to the system
*/
int
SDL_NumSensors(void)
{
int i, total_sensors = 0;
SDL_LockSensors();
for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
total_sensors += SDL_sensor_drivers[i]->GetCount();
}
SDL_UnlockSensors();
return total_sensors;
}
/*
* Return the next available sensor instance ID
* This may be called by drivers from multiple threads, unprotected by any locks
*/
SDL_SensorID SDL_GetNextSensorInstanceID()
{
return SDL_AtomicIncRef(&SDL_next_sensor_instance_id);
}
/*
* Get the driver and device index for an API device index
* This should be called while the sensor lock is held, to prevent another thread from updating the list
*/
static SDL_bool
SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver **driver, int *driver_index)
{
int i, num_sensors, total_sensors = 0;
if (device_index >= 0) {
for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
num_sensors = SDL_sensor_drivers[i]->GetCount();
if (device_index < num_sensors) {
*driver = SDL_sensor_drivers[i];
*driver_index = device_index;
return SDL_TRUE;
}
device_index -= num_sensors;
total_sensors += num_sensors;
}
}
SDL_SetError("There are %d sensors available", total_sensors);
return SDL_FALSE;
}
/*
* Get the implementation dependent name of a sensor
*/
const char *
SDL_SensorGetDeviceName(int device_index)
{
SDL_SensorDriver *driver;
const char *name = NULL;
SDL_LockSensors();
if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
name = driver->GetDeviceName(device_index);
}
SDL_UnlockSensors();
/* FIXME: Really we should reference count this name so it doesn't go away after unlock */
return name;
}
SDL_SensorType
SDL_SensorGetDeviceType(int device_index)
{
SDL_SensorDriver *driver;
SDL_SensorType type = SDL_SENSOR_INVALID;
SDL_LockSensors();
if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
type = driver->GetDeviceType(device_index);
}
SDL_UnlockSensors();
return type;
}
SDL_SensorType
SDL_SensorGetDeviceNonPortableType(int device_index)
{
SDL_SensorDriver *driver;
int type = -1;
SDL_LockSensors();
if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
type = driver->GetDeviceNonPortableType(device_index);
}
SDL_UnlockSensors();
return type;
}
SDL_SensorID
SDL_SensorGetDeviceInstanceID(int device_index)
{
SDL_SensorDriver *driver;
SDL_SensorID instance_id = -1;
SDL_LockSensors();
if (SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
instance_id = driver->GetDeviceInstanceID(device_index);
}
SDL_UnlockSensors();
return instance_id;
}
/*
* Open a sensor for use - the index passed as an argument refers to
* the N'th sensor on the system. This index is the value which will
* identify this sensor in future sensor events.
*
* This function returns a sensor identifier, or NULL if an error occurred.
*/
SDL_Sensor *
SDL_SensorOpen(int device_index)
{
SDL_SensorDriver *driver;
SDL_SensorID instance_id;
SDL_Sensor *sensor;
SDL_Sensor *sensorlist;
const char *sensorname = NULL;
SDL_LockSensors();
if (!SDL_GetDriverAndSensorIndex(device_index, &driver, &device_index)) {
SDL_UnlockSensors();
return NULL;
}
sensorlist = SDL_sensors;
/* If the sensor is already open, return it
* it is important that we have a single sensor * for each instance id
*/
instance_id = driver->GetDeviceInstanceID(device_index);
while (sensorlist) {
if (instance_id == sensorlist->instance_id) {
sensor = sensorlist;
++sensor->ref_count;
SDL_UnlockSensors();
return sensor;
}
sensorlist = sensorlist->next;
}
/* Create and initialize the sensor */
sensor = (SDL_Sensor *) SDL_calloc(sizeof(*sensor), 1);
if (sensor == NULL) {
SDL_OutOfMemory();
SDL_UnlockSensors();
return NULL;
}
sensor->driver = driver;
sensor->instance_id = instance_id;
sensor->type = driver->GetDeviceType(device_index);
sensor->non_portable_type = driver->GetDeviceNonPortableType(device_index);
if (driver->Open(sensor, device_index) < 0) {
SDL_free(sensor);
SDL_UnlockSensors();
return NULL;
}
sensorname = driver->GetDeviceName(device_index);
if (sensorname) {
sensor->name = SDL_strdup(sensorname);
} else {
sensor->name = NULL;
}
/* Add sensor to list */
++sensor->ref_count;
/* Link the sensor in the list */
sensor->next = SDL_sensors;
SDL_sensors = sensor;
SDL_UnlockSensors();
driver->Update(sensor);
return sensor;
}
/*
* Find the SDL_Sensor that owns this instance id
*/
SDL_Sensor *
SDL_SensorFromInstanceID(SDL_SensorID instance_id)
{
SDL_Sensor *sensor;
SDL_LockSensors();
for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
if (sensor->instance_id == instance_id) {
break;
}
}
SDL_UnlockSensors();
return sensor;
}
/*
* Checks to make sure the sensor is valid.
*/
static int
SDL_PrivateSensorValid(SDL_Sensor * sensor)
{
int valid;
if (sensor == NULL) {
SDL_SetError("Sensor hasn't been opened yet");
valid = 0;
} else {
valid = 1;
}
return valid;
}
/*
* Get the friendly name of this sensor
*/
const char *
SDL_SensorGetName(SDL_Sensor * sensor)
{
if (!SDL_PrivateSensorValid(sensor)) {
return NULL;
}
return sensor->name;
}
/*
* Get the type of this sensor
*/
SDL_SensorType
SDL_SensorGetType(SDL_Sensor * sensor)
{
if (!SDL_PrivateSensorValid(sensor)) {
return SDL_SENSOR_INVALID;
}
return sensor->type;
}
/*
* Get the platform dependent type of this sensor
*/
int
SDL_SensorGetNonPortableType(SDL_Sensor * sensor)
{
if (!SDL_PrivateSensorValid(sensor)) {
return -1;
}
return sensor->non_portable_type;
}
/*
* Get the instance id for this opened sensor
*/
SDL_SensorID
SDL_SensorGetInstanceID(SDL_Sensor * sensor)
{
if (!SDL_PrivateSensorValid(sensor)) {
return -1;
}
return sensor->instance_id;
}
/*
* Get the current state of this sensor
*/
int
SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values)
{
if (!SDL_PrivateSensorValid(sensor)) {
return -1;
}
num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
SDL_memcpy(data, sensor->data, num_values*sizeof(*data));
return 0;
}
/*
* Close a sensor previously opened with SDL_SensorOpen()
*/
void
SDL_SensorClose(SDL_Sensor * sensor)
{
SDL_Sensor *sensorlist;
SDL_Sensor *sensorlistprev;
if (!SDL_PrivateSensorValid(sensor)) {
return;
}
SDL_LockSensors();
/* First decrement ref count */
if (--sensor->ref_count > 0) {
SDL_UnlockSensors();
return;
}
if (SDL_updating_sensor) {
SDL_UnlockSensors();
return;
}
sensor->driver->Close(sensor);
sensor->hwdata = NULL;
sensorlist = SDL_sensors;
sensorlistprev = NULL;
while (sensorlist) {
if (sensor == sensorlist) {
if (sensorlistprev) {
/* unlink this entry */
sensorlistprev->next = sensorlist->next;
} else {
SDL_sensors = sensor->next;
}
break;
}
sensorlistprev = sensorlist;
sensorlist = sensorlist->next;
}
SDL_free(sensor->name);
/* Free the data associated with this sensor */
SDL_free(sensor);
SDL_UnlockSensors();
}
void
SDL_SensorQuit(void)
{
int i;
/* Make sure we're not getting called in the middle of updating sensors */
SDL_assert(!SDL_updating_sensor);
SDL_LockSensors();
/* Stop the event polling */
while (SDL_sensors) {
SDL_sensors->ref_count = 1;
SDL_SensorClose(SDL_sensors);
}
/* Quit the sensor setup */
for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
SDL_sensor_drivers[i]->Quit();
}
SDL_UnlockSensors();
#if !SDL_EVENTS_DISABLED
SDL_QuitSubSystem(SDL_INIT_EVENTS);
#endif
if (SDL_sensor_lock) {
SDL_DestroyMutex(SDL_sensor_lock);
SDL_sensor_lock = NULL;
}
}
/* These are global for SDL_syssensor.c and SDL_events.c */
int
SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values)
{
int posted;
/* Allow duplicate events, for things like steps and heartbeats */
/* Update internal sensor state */
num_values = SDL_min(num_values, SDL_arraysize(sensor->data));
SDL_memcpy(sensor->data, data, num_values*sizeof(*data));
/* Post the event, if desired */
posted = 0;
#if !SDL_EVENTS_DISABLED
if (SDL_GetEventState(SDL_JOYAXISMOTION) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_SENSORUPDATE;
event.sensor.which = sensor->instance_id;
num_values = SDL_min(num_values, SDL_arraysize(event.sensor.data));
SDL_memset(event.sensor.data, 0, sizeof(event.sensor.data));
SDL_memcpy(event.sensor.data, data, num_values*sizeof(*data));
posted = SDL_PushEvent(&event) == 1;
}
#endif /* !SDL_EVENTS_DISABLED */
return posted;
}
void
SDL_SensorUpdate(void)
{
int i;
SDL_Sensor *sensor;
if (!SDL_WasInit(SDL_INIT_SENSOR)) {
return;
}
SDL_LockSensors();
if (SDL_updating_sensor) {
/* The sensors are already being updated */
SDL_UnlockSensors();
return;
}
SDL_updating_sensor = SDL_TRUE;
/* Make sure the list is unlocked while dispatching events to prevent application deadlocks */
SDL_UnlockSensors();
for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
sensor->driver->Update(sensor);
}
SDL_LockSensors();
SDL_updating_sensor = SDL_FALSE;
/* If any sensors were closed while updating, free them here */
for (sensor = SDL_sensors; sensor; sensor = sensor->next) {
if (sensor->ref_count <= 0) {
SDL_SensorClose(sensor);
}
}
/* this needs to happen AFTER walking the sensor list above, so that any
dangling hardware data from removed devices can be free'd
*/
for (i = 0; i < SDL_arraysize(SDL_sensor_drivers); ++i) {
SDL_sensor_drivers[i]->Detect();
}
SDL_UnlockSensors();
}
/* vi: set ts=4 sw=4 expandtab: */
SDL.h
SDL_memset
#define SDL_memset
Definition: SDL_dynapi_overrides.h:386
SDL_PrivateSensorUpdate
int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values)
Definition: SDL_sensor.c:476
SDL_events.h
SDL_updating_sensor
static SDL_bool SDL_updating_sensor
Definition: SDL_sensor.c:47
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:260
SDL_atomic.h
NULL
#define NULL
Definition: begin_code.h:167
SDL_DUMMY_SensorDriver
SDL_SensorDriver SDL_DUMMY_SensorDriver
SDL_LockSensors
static void SDL_LockSensors(void)
Definition: SDL_sensor.c:52
SDL_INIT_EVENTS
#define SDL_INIT_EVENTS
Definition: SDL.h:83
SDL_mutex
Definition: SDL_sysmutex.c:29
SDL_SensorInit
int SDL_SensorInit(void)
Definition: SDL_sensor.c:69
SDL_AtomicIncRef
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:252
SDL_QuitSubSystem
#define SDL_QuitSubSystem
Definition: SDL_dynapi_overrides.h:56
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:259
SDL_SensorGetDeviceName
const char * SDL_SensorGetDeviceName(int device_index)
Get the implementation dependent name of a sensor.
Definition: SDL_sensor.c:147
SDL_syssensor.h
SDL_ENABLE
#define SDL_ENABLE
Definition: SDL_events.h:759
SDL_GetDriverAndSensorIndex
static SDL_bool SDL_GetDriverAndSensorIndex(int device_index, SDL_SensorDriver **driver, int *driver_index)
Definition: SDL_sensor.c:122
SDL_InitSubSystem
#define SDL_InitSubSystem
Definition: SDL_dynapi_overrides.h:55
SDL_SensorGetName
const char * SDL_SensorGetName(SDL_Sensor *sensor)
Get the implementation dependent name of a sensor.
Definition: SDL_sensor.c:323
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_SensorQuit
void SDL_SensorQuit(void)
Definition: SDL_sensor.c:440
SDL_SensorFromInstanceID
SDL_Sensor * SDL_SensorFromInstanceID(SDL_SensorID instance_id)
Definition: SDL_sensor.c:287
SDL_INIT_SENSOR
#define SDL_INIT_SENSOR
Definition: SDL.h:84
SDL_SensorType
SDL_SensorType
Definition: SDL_sensor.h:69
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
SDL_SensorUpdate
void SDL_SensorUpdate(void)
Definition: SDL_sensor.c:503
SDL_SensorGetDeviceType
SDL_SensorType SDL_SensorGetDeviceType(int device_index)
Get the type of a sensor.
Definition: SDL_sensor.c:163
SDL_COREMOTION_SensorDriver
SDL_SensorDriver SDL_COREMOTION_SensorDriver
SDL_GetEventState
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_SENSORUPDATE
@ SDL_SENSORUPDATE
Definition: SDL_events.h:151
SDL_PushEvent
#define SDL_PushEvent
Definition: SDL_dynapi_overrides.h:125
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_assert.h
SDL_min
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
SDL_JOYAXISMOTION
@ SDL_JOYAXISMOTION
Definition: SDL_events.h:111
SDL_SensorGetInstanceID
SDL_SensorID SDL_SensorGetInstanceID(SDL_Sensor *sensor)
Get the instance ID of a sensor.
Definition: SDL_sensor.c:362
SDL_SENSOR_INVALID
@ SDL_SENSOR_INVALID
Definition: SDL_sensor.h:71
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_SensorGetDeviceInstanceID
SDL_SensorID SDL_SensorGetDeviceInstanceID(int device_index)
Get the instance ID of a sensor.
Definition: SDL_sensor.c:193
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_ANDROID_SensorDriver
SDL_SensorDriver SDL_ANDROID_SensorDriver
SDL_sensor_drivers
static SDL_SensorDriver * SDL_sensor_drivers[]
Definition: SDL_sensor.c:35
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_next_sensor_instance_id
static SDL_atomic_t SDL_next_sensor_instance_id
Definition: SDL_sensor.c:49
SDL_SensorClose
void SDL_SensorClose(SDL_Sensor *sensor)
Definition: SDL_sensor.c:390
SDL_SensorGetDeviceNonPortableType
SDL_SensorType SDL_SensorGetDeviceNonPortableType(int device_index)
Get the platform dependent type of a sensor.
Definition: SDL_sensor.c:178
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_atomic_t
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric ...
Definition: SDL_atomic.h:216
SDL_sensors
static SDL_Sensor * SDL_sensors
Definition: SDL_sensor.c:46
SDL_PrivateSensorValid
static int SDL_PrivateSensorValid(SDL_Sensor *sensor)
Definition: SDL_sensor.c:305
SDL_DestroyMutex
#define SDL_DestroyMutex
Definition: SDL_dynapi_overrides.h:263
SDL_strdup
#define SDL_strdup
Definition: SDL_dynapi_overrides.h:397
SDL_sensor_lock
static SDL_mutex * SDL_sensor_lock
Definition: SDL_sensor.c:48
SDL_SensorOpen
SDL_Sensor * SDL_SensorOpen(int device_index)
Open a sensor for use.
Definition: SDL_sensor.c:215
SDL_NumSensors
int SDL_NumSensors(void)
Count the number of sensors attached to the system right now.
Definition: SDL_sensor.c:97
SDL_GetNextSensorInstanceID
SDL_SensorID SDL_GetNextSensorInstanceID()
Definition: SDL_sensor.c:112
SDL_Event
General event structure.
Definition: SDL_events.h:557
SDL_SensorGetData
int SDL_SensorGetData(SDL_Sensor *sensor, float *data, int num_values)
Definition: SDL_sensor.c:375
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
SDL_WasInit
#define SDL_WasInit
Definition: SDL_dynapi_overrides.h:57
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
i
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
SDL_SensorGetNonPortableType
int SDL_SensorGetNonPortableType(SDL_Sensor *sensor)
Get the platform dependent type of a sensor.
Definition: SDL_sensor.c:349
SDL_UnlockSensors
static void SDL_UnlockSensors(void)
Definition: SDL_sensor.c:60
SDL_SensorGetType
SDL_SensorType SDL_SensorGetType(SDL_Sensor *sensor)
Get the type of a sensor.
Definition: SDL_sensor.c:336
SDL_SensorID
Sint32 SDL_SensorID
Definition: SDL_sensor.h:60
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161