sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_sensor.c (13243B)


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