blob: 7422f9615918ed1227c0c86c6e3391c8199e9a17 [file] [log] [blame]
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "android/sensors-port.h"
18#include "android/hw-sensors.h"
19
20#define E(...) derror(__VA_ARGS__)
21#define W(...) dwarning(__VA_ARGS__)
22#define D(...) VERBOSE_PRINT(sensors_port,__VA_ARGS__)
23#define D_ACTIVE VERBOSE_CHECK(camera)
24
25/* Maximum number of sensors supported. */
26#define ASP_MAX_SENSOR 12
27
28/* Maximum length of a sensor message. */
29#define ASP_MAX_SENSOR_MSG 1024
30
31/* Maximum length of a sensor event. */
32#define ASP_MAX_SENSOR_EVENT 256
33
34/* Query timeout in milliseconds. */
35#define ASP_QUERY_TIMEOUT 3000
36
37/* Sensors port descriptor. */
38struct AndroidSensorsPort {
39 /* Caller identifier. */
40 void* opaque;
41 /* Connected android device. */
42 AndroidDevice* device;
43 /* String containing list of all available sensors. */
44 char sensors[ASP_MAX_SENSOR * 64];
45 /* Array of available sensor names. Note that each string in this array
46 * points inside the 'sensors' buffer. */
47 const char* sensor_list[ASP_MAX_SENSOR];
48 /* Number of available sensors. */
49 int sensors_num;
50 /* Connection status: 1 connected, 0 - disconnected. */
51 int is_connected;
52 /* Buffer where to receive sensor messages. */
53 char sensor_msg[ASP_MAX_SENSOR_MSG];
54 /* Buffer where to receive sensor events. */
55 char events[ASP_MAX_SENSOR_EVENT];
56};
57
58/* Destroys and frees the descriptor. */
59static void
60_sensors_port_free(AndroidSensorsPort* asp)
61{
62 if (asp != NULL) {
63 if (asp->device != NULL) {
64 android_device_destroy(asp->device);
65 }
66 AFREE(asp);
67 }
68}
69
70/********************************************************************************
71 * Sensors port callbacks
72 *******************************************************************************/
73
74/* A callback that invoked on sensor events.
75 * Param:
76 * opaque - AndroidSensorsPort instance.
77 * ad - Android device used by this sensors port.
78 * msg, msgsize - Sensor event message
79 * failure - Message receiving status.
80 */
81static void
82_on_sensor_received(void* opaque, AndroidDevice* ad, char* msg, int msgsize)
83{
84 float fvalues[3] = {0, 0, 0};
85 char sensor[ASP_MAX_SENSOR_MSG];
86 char* value;
87 int id;
88 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
89
90 if (errno) {
91 D("Sensors notification has failed on sensors port: %s", strerror(errno));
92 return;
93 }
94
95 /* Parse notification, separating sensor name from parameters. */
96 memcpy(sensor, msg, msgsize);
97 value = strchr(sensor, ':');
98 if (value == NULL) {
99 W("Bad format for sensor notification: %s", msg);
100 return;
101 }
102 sensor[value-sensor] = '\0';
103 value++;
104
105 id = android_sensors_get_id_from_name(sensor);
106 if (id >= 0) {
107 /* Parse the value part to get the sensor values(a, b, c) */
108 int i;
109 char* pnext;
110 char* pend = value + strlen(value);
111 for (i = 0; i < 3; i++, value = pnext + 1) {
112 pnext=strchr( value, ':' );
113 if (pnext) {
114 *pnext = 0;
115 } else {
116 pnext = pend;
117 }
118
119 if (pnext > value) {
120 if (1 != sscanf( value,"%g", &fvalues[i] )) {
121 W("Bad parameters in sensor notification %s", msg);
122 return;
123 }
124 }
125 }
126 android_sensors_set(id, fvalues[0], fvalues[1], fvalues[2]);
127 } else {
128 W("Unknown sensor name '%s' in '%s'", sensor, msg);
129 }
130
131 /* Listen to the next event. */
132 android_device_listen(ad, asp->events, sizeof(asp->events), _on_sensor_received);
133}
134
135/* A callback that is invoked when android device is connected (i.e. both, command
136 * and event channels have been stablished.
137 * Param:
138 * opaque - AndroidSensorsPort instance.
139 * ad - Android device used by this sensors port.
140 * failure - Connections status.
141 */
142static void
143_on_device_connected(void* opaque, AndroidDevice* ad, int failure)
144{
145 if (!failure) {
146 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
147 asp->is_connected = 1;
148 D("Sensor emulation has started");
149 /* Initialize sensors on device. */
150 sensors_port_init_sensors(asp);
151 }
152}
153
154/* Invoked when an I/O failure occurs on a socket.
155 * Note that this callback will not be invoked on connection failures.
156 * Param:
157 * opaque - AndroidSensorsPort instance.
158 * ad - Android device instance
159 * ads - Connection socket where failure has occured.
160 * failure - Contains 'errno' indicating the reason for failure.
161 */
162static void
163_on_io_failure(void* opaque, AndroidDevice* ad, int failure)
164{
165 AndroidSensorsPort* asp = (AndroidSensorsPort*)opaque;
166 E("Sensors port got disconnected: %s", strerror(failure));
167 asp->is_connected = false;
168 android_device_disconnect(ad);
169 android_device_connect_async(ad, _on_device_connected);
170}
171
172/********************************************************************************
173 * Sensors port API
174 *******************************************************************************/
175
176AndroidSensorsPort*
177sensors_port_create(void* opaque)
178{
179 AndroidSensorsPort* asp;
180 char* wrk;
181 int res;
182
183 ANEW0(asp);
184 asp->opaque = opaque;
185 asp->is_connected = 0;
186
187 asp->device = android_device_init(asp, AD_SENSOR_PORT, _on_io_failure);
188 if (asp->device == NULL) {
189 _sensors_port_free(asp);
190 return NULL;
191 }
192
193 res = android_device_connect_sync(asp->device, ASP_QUERY_TIMEOUT);
194 if (res != 0) {
195 sensors_port_destroy(asp);
196 return NULL;
197 }
198
199 res = android_device_query(asp->device, "list",
200 asp->sensors, sizeof(asp->sensors),
201 ASP_QUERY_TIMEOUT);
202 if (res != 0) {
203 sensors_port_destroy(asp);
204 return NULL;
205 }
206
207 /* Parse sensor list. */
208 asp->sensors_num = 0;
209 wrk = asp->sensors;
210
211 while (wrk != NULL && *wrk != '\0' && *wrk != '\n') {
212 asp->sensor_list[asp->sensors_num] = wrk;
213 asp->sensors_num++;
214 wrk = strchr(wrk, '\n');
215 if (wrk != NULL) {
216 *wrk = '\0'; wrk++;
217 }
218 }
219
220 android_device_listen(asp->device, asp->events, sizeof(asp->events),
221 _on_sensor_received);
222 return asp;
223}
224
225int
226sensors_port_init_sensors(AndroidSensorsPort* asp)
227{
228 int res, id;
229
230 /* Disable all sensors for now. Reenable only those that are emulated. */
231 res = sensors_port_disable_sensor(asp, "all");
232 if (res) {
233 return res;
234 }
235
236 /* Start listening on sensor events. */
237 res = android_device_listen(asp->device, asp->events, sizeof(asp->events),
238 _on_sensor_received);
239 if (res) {
240 return res;
241 }
242
243 /* Walk throuh the list of enabled sensors enabling them on the device. */
244 for (id = 0; id < MAX_SENSORS; id++) {
245 if (android_sensors_get_sensor_status(id) == 1) {
246 res = sensors_port_enable_sensor(asp, android_sensors_get_name_from_id(id));
247 if (res == 0) {
248 D("Sensor '%s' is enabled on the device.",
249 android_sensors_get_name_from_id(id));
250 }
251 }
252 }
253
254 /* Start sensor events. */
255 return sensors_port_start(asp);
256}
257
258void
259sensors_port_destroy(AndroidSensorsPort* asp)
260{
261 _sensors_port_free(asp);
262}
263
264int
265sensors_port_is_connected(AndroidSensorsPort* asp)
266{
267 return asp->is_connected;
268}
269
270int
271sensors_port_enable_sensor(AndroidSensorsPort* asp, const char* name)
272{
273 char query[1024];
274 char qresp[1024];
275 snprintf(query, sizeof(query), "enable:%s", name);
276 const int res =
277 android_device_query(asp->device, query, qresp, sizeof(qresp),
278 ASP_QUERY_TIMEOUT);
279 if (res) {
280 if (errno) {
281 D("Query '%s' failed on I/O: %s", query, strerror(errno));
282 } else {
283 D("Query '%s' failed on device: %s", query, qresp);
284 }
285 }
286 return res;
287}
288
289int
290sensors_port_disable_sensor(AndroidSensorsPort* asp, const char* name)
291{
292 char query[1024];
293 char qresp[1024];
294 snprintf(query, sizeof(query), "disable:%s", name);
295 const int res =
296 android_device_query(asp->device, query, qresp, sizeof(qresp),
297 ASP_QUERY_TIMEOUT);
298 if (res) {
299 if (errno) {
300 D("Query '%s' failed on I/O: %s", query, strerror(errno));
301 } else {
302 D("Query '%s' failed on device: %s", query, qresp);
303 }
304 }
305 return res;
306}
307
308int
309sensors_port_start(AndroidSensorsPort* asp)
310{
311 char qresp[ASP_MAX_SENSOR_MSG];
312 const int res =
313 android_device_query(asp->device, "start", qresp, sizeof(qresp),
314 ASP_QUERY_TIMEOUT);
315 if (res) {
316 if (errno) {
317 D("Query 'start' failed on I/O: %s", strerror(errno));
318 } else {
319 D("Query 'start' failed on device: %s", qresp);
320 }
321 }
322 return res;
323}
324
325int
326sensors_port_stop(AndroidSensorsPort* asp)
327{
328 char qresp[ASP_MAX_SENSOR_MSG];
329 const int res =
330 android_device_query(asp->device, "stop", qresp, sizeof(qresp),
331 ASP_QUERY_TIMEOUT);
332 if (res) {
333 if (errno) {
334 D("Query 'stop' failed on I/O: %s", strerror(errno));
335 } else {
336 D("Query 'stop' failed on device: %s", qresp);
337 }
338 }
339
340 return res;
341}