sensors-port.c revision 9ef86366e076f45bb9a6e6e98651062bc3ad7da8
1/* 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(sensors_port) 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} 342