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 #include "SDL_config.h"
24
25 #ifdef SDL_SENSOR_ANDROID
26
27 /* This is the system specific header for the SDL sensor API */
28 #include <android/sensor.h>
29
30 #include "SDL_error.h"
31 #include "SDL_sensor.h"
32 #include "SDL_androidsensor.h"
33 #include "../SDL_syssensor.h"
34 #include "../SDL_sensor_c.h"
35 //#include "../../core/android/SDL_android.h"
36
37 #ifndef LOOPER_ID_USER
38 #define LOOPER_ID_USER 3
39 #endif
40
41 typedef struct
42 {
43 ASensorRef asensor;
44 SDL_SensorID instance_id;
45 } SDL_AndroidSensor;
46
47 static ASensorManager* SDL_sensor_manager;
48 static ALooper* SDL_sensor_looper;
49 static SDL_AndroidSensor *SDL_sensors;
50 static int SDL_sensors_count;
51
52 static int
SDL_ANDROID_SensorInit(void)53 SDL_ANDROID_SensorInit(void)
54 {
55 int i, sensors_count;
56 ASensorList sensors;
57
58 SDL_sensor_manager = ASensorManager_getInstance();
59 if (!SDL_sensor_manager) {
60 return SDL_SetError("Couldn't create sensor manager");
61 }
62
63 SDL_sensor_looper = ALooper_forThread();
64 if (!SDL_sensor_looper) {
65 SDL_sensor_looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
66 if (!SDL_sensor_looper) {
67 return SDL_SetError("Couldn't create sensor event loop");
68 }
69 }
70
71 /* FIXME: Is the sensor list dynamic? */
72 sensors_count = ASensorManager_getSensorList(SDL_sensor_manager, &sensors);
73 if (sensors_count > 0) {
74 SDL_sensors = (SDL_AndroidSensor *)SDL_calloc(sensors_count, sizeof(*SDL_sensors));
75 if (!SDL_sensors) {
76 return SDL_OutOfMemory();
77 }
78
79 for (i = 0; i < sensors_count; ++i) {
80 SDL_sensors[i].asensor = sensors[i];
81 SDL_sensors[i].instance_id = SDL_GetNextSensorInstanceID();
82 }
83 SDL_sensors_count = sensors_count;
84 }
85 return 0;
86 }
87
88 static int
SDL_ANDROID_SensorGetCount(void)89 SDL_ANDROID_SensorGetCount(void)
90 {
91 return SDL_sensors_count;
92 }
93
94 static void
SDL_ANDROID_SensorDetect(void)95 SDL_ANDROID_SensorDetect(void)
96 {
97 }
98
99 static const char *
SDL_ANDROID_SensorGetDeviceName(int device_index)100 SDL_ANDROID_SensorGetDeviceName(int device_index)
101 {
102 return ASensor_getName(SDL_sensors[device_index].asensor);
103 }
104
105 static SDL_SensorType
SDL_ANDROID_SensorGetDeviceType(int device_index)106 SDL_ANDROID_SensorGetDeviceType(int device_index)
107 {
108 switch (ASensor_getType(SDL_sensors[device_index].asensor)) {
109 case 0x00000001:
110 return SDL_SENSOR_ACCEL;
111 case 0x00000004:
112 return SDL_SENSOR_GYRO;
113 default:
114 return SDL_SENSOR_UNKNOWN;
115 }
116 }
117
118 static int
SDL_ANDROID_SensorGetDeviceNonPortableType(int device_index)119 SDL_ANDROID_SensorGetDeviceNonPortableType(int device_index)
120 {
121 return ASensor_getType(SDL_sensors[device_index].asensor);
122 }
123
124 static SDL_SensorID
SDL_ANDROID_SensorGetDeviceInstanceID(int device_index)125 SDL_ANDROID_SensorGetDeviceInstanceID(int device_index)
126 {
127 return SDL_sensors[device_index].instance_id;
128 }
129
130 static int
SDL_ANDROID_SensorOpen(SDL_Sensor * sensor,int device_index)131 SDL_ANDROID_SensorOpen(SDL_Sensor *sensor, int device_index)
132 {
133 struct sensor_hwdata *hwdata;
134 int delay_us, min_delay_us;
135
136 hwdata = (struct sensor_hwdata *)SDL_calloc(1, sizeof(*hwdata));
137 if (hwdata == NULL) {
138 return SDL_OutOfMemory();
139 }
140
141 hwdata->asensor = SDL_sensors[device_index].asensor;
142 hwdata->eventqueue = ASensorManager_createEventQueue(SDL_sensor_manager, SDL_sensor_looper, LOOPER_ID_USER, NULL, NULL);
143 if (!hwdata->eventqueue) {
144 SDL_free(hwdata);
145 return SDL_SetError("Couldn't create sensor event queue");
146 }
147
148 if (ASensorEventQueue_enableSensor(hwdata->eventqueue, hwdata->asensor) < 0) {
149 ASensorManager_destroyEventQueue(SDL_sensor_manager, hwdata->eventqueue);
150 SDL_free(hwdata);
151 return SDL_SetError("Couldn't enable sensor");
152 }
153
154 /* Use 60 Hz update rate if possible */
155 /* FIXME: Maybe add a hint for this? */
156 delay_us = 1000000 / 60;
157 min_delay_us = ASensor_getMinDelay(hwdata->asensor);
158 if (delay_us < min_delay_us) {
159 delay_us = min_delay_us;
160 }
161 ASensorEventQueue_setEventRate(hwdata->eventqueue, hwdata->asensor, delay_us);
162
163 sensor->hwdata = hwdata;
164 return 0;
165 }
166
167 static void
SDL_ANDROID_SensorUpdate(SDL_Sensor * sensor)168 SDL_ANDROID_SensorUpdate(SDL_Sensor *sensor)
169 {
170 int events;
171 ASensorEvent event;
172 struct android_poll_source* source;
173
174 if (ALooper_pollAll(0, NULL, &events, (void**)&source) == LOOPER_ID_USER) {
175 SDL_zero(event);
176 while (ASensorEventQueue_getEvents(sensor->hwdata->eventqueue, &event, 1) > 0) {
177 SDL_PrivateSensorUpdate(sensor, event.data, SDL_arraysize(event.data));
178 }
179 }
180 }
181
182 static void
SDL_ANDROID_SensorClose(SDL_Sensor * sensor)183 SDL_ANDROID_SensorClose(SDL_Sensor *sensor)
184 {
185 if (sensor->hwdata) {
186 ASensorEventQueue_disableSensor(sensor->hwdata->eventqueue, sensor->hwdata->asensor);
187 ASensorManager_destroyEventQueue(SDL_sensor_manager, sensor->hwdata->eventqueue);
188 SDL_free(sensor->hwdata);
189 sensor->hwdata = NULL;
190 }
191 }
192
193 static void
SDL_ANDROID_SensorQuit(void)194 SDL_ANDROID_SensorQuit(void)
195 {
196 if (SDL_sensors) {
197 SDL_free(SDL_sensors);
198 SDL_sensors = NULL;
199 SDL_sensors_count = 0;
200 }
201 }
202
203 SDL_SensorDriver SDL_ANDROID_SensorDriver =
204 {
205 SDL_ANDROID_SensorInit,
206 SDL_ANDROID_SensorGetCount,
207 SDL_ANDROID_SensorDetect,
208 SDL_ANDROID_SensorGetDeviceName,
209 SDL_ANDROID_SensorGetDeviceType,
210 SDL_ANDROID_SensorGetDeviceNonPortableType,
211 SDL_ANDROID_SensorGetDeviceInstanceID,
212 SDL_ANDROID_SensorOpen,
213 SDL_ANDROID_SensorUpdate,
214 SDL_ANDROID_SensorClose,
215 SDL_ANDROID_SensorQuit,
216 };
217
218 #endif /* SDL_SENSOR_ANDROID */
219
220 /* vi: set ts=4 sw=4 expandtab: */
221