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. */ 38 struct 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. */ 59 static 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 */ 81 static 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 */ 142 static 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 */ 162 static 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 176 #include "android/sdk-controller-socket.h" 177 178 static AsyncIOAction 179 _on_sdkctl_connection(void* client_opaque, SDKCtlSocket* sdkctl, AsyncIOState status) 180 { 181 if (status == ASIO_STATE_FAILED) { 182 sdkctl_socket_reconnect(sdkctl, 1970, 20); 183 } 184 return ASIO_ACTION_DONE; 185 } 186 187 void on_sdkctl_handshake(void* client_opaque, 188 SDKCtlSocket* sdkctl, 189 void* handshake, 190 uint32_t handshake_size, 191 AsyncIOState status) 192 { 193 if (status == ASIO_STATE_SUCCEEDED) { 194 printf("---------- Handshake %d bytes received.\n", handshake_size); 195 } else { 196 printf("!!!!!!!!!! Handshake failed with status %d: %d -> %s\n", 197 status, errno, strerror(errno)); 198 sdkctl_socket_reconnect(sdkctl, 1970, 20); 199 } 200 } 201 202 void on_sdkctl_message(void* client_opaque, 203 SDKCtlSocket* sdkctl, 204 SDKCtlPacket* message, 205 int msg_type, 206 void* msg_data, 207 int msg_size) 208 { 209 printf("########################################################\n"); 210 } 211 212 AndroidSensorsPort* 213 sensors_port_create(void* opaque) 214 { 215 AndroidSensorsPort* asp; 216 char* wrk; 217 int res; 218 219 SDKCtlSocket* sdkctl = sdkctl_socket_new(20, "test", _on_sdkctl_connection, 220 on_sdkctl_handshake, on_sdkctl_message, 221 NULL); 222 // sdkctl_init_recycler(sdkctl, 64, 8); 223 sdkctl_socket_connect(sdkctl, 1970, 20); 224 225 ANEW0(asp); 226 asp->opaque = opaque; 227 asp->is_connected = 0; 228 229 asp->device = android_device_init(asp, AD_SENSOR_PORT, _on_io_failure); 230 if (asp->device == NULL) { 231 _sensors_port_free(asp); 232 return NULL; 233 } 234 235 res = android_device_connect_sync(asp->device, ASP_QUERY_TIMEOUT); 236 if (res != 0) { 237 sensors_port_destroy(asp); 238 return NULL; 239 } 240 241 res = android_device_query(asp->device, "list", 242 asp->sensors, sizeof(asp->sensors), 243 ASP_QUERY_TIMEOUT); 244 if (res != 0) { 245 sensors_port_destroy(asp); 246 return NULL; 247 } 248 249 /* Parse sensor list. */ 250 asp->sensors_num = 0; 251 wrk = asp->sensors; 252 253 while (wrk != NULL && *wrk != '\0' && *wrk != '\n') { 254 asp->sensor_list[asp->sensors_num] = wrk; 255 asp->sensors_num++; 256 wrk = strchr(wrk, '\n'); 257 if (wrk != NULL) { 258 *wrk = '\0'; wrk++; 259 } 260 } 261 262 android_device_listen(asp->device, asp->events, sizeof(asp->events), 263 _on_sensor_received); 264 return asp; 265 } 266 267 int 268 sensors_port_init_sensors(AndroidSensorsPort* asp) 269 { 270 int res, id; 271 272 /* Disable all sensors for now. Reenable only those that are emulated. */ 273 res = sensors_port_disable_sensor(asp, "all"); 274 if (res) { 275 return res; 276 } 277 278 /* Start listening on sensor events. */ 279 res = android_device_listen(asp->device, asp->events, sizeof(asp->events), 280 _on_sensor_received); 281 if (res) { 282 return res; 283 } 284 285 /* Walk throuh the list of enabled sensors enabling them on the device. */ 286 for (id = 0; id < MAX_SENSORS; id++) { 287 if (android_sensors_get_sensor_status(id) == 1) { 288 res = sensors_port_enable_sensor(asp, android_sensors_get_name_from_id(id)); 289 if (res == 0) { 290 D("Sensor '%s' is enabled on the device.", 291 android_sensors_get_name_from_id(id)); 292 } 293 } 294 } 295 296 /* Start sensor events. */ 297 return sensors_port_start(asp); 298 } 299 300 void 301 sensors_port_destroy(AndroidSensorsPort* asp) 302 { 303 _sensors_port_free(asp); 304 } 305 306 int 307 sensors_port_is_connected(AndroidSensorsPort* asp) 308 { 309 return asp->is_connected; 310 } 311 312 int 313 sensors_port_enable_sensor(AndroidSensorsPort* asp, const char* name) 314 { 315 char query[1024]; 316 char qresp[1024]; 317 snprintf(query, sizeof(query), "enable:%s", name); 318 const int res = 319 android_device_query(asp->device, query, qresp, sizeof(qresp), 320 ASP_QUERY_TIMEOUT); 321 if (res) { 322 if (errno) { 323 D("Query '%s' failed on I/O: %s", query, strerror(errno)); 324 } else { 325 D("Query '%s' failed on device: %s", query, qresp); 326 } 327 } 328 return res; 329 } 330 331 int 332 sensors_port_disable_sensor(AndroidSensorsPort* asp, const char* name) 333 { 334 char query[1024]; 335 char qresp[1024]; 336 snprintf(query, sizeof(query), "disable:%s", name); 337 const int res = 338 android_device_query(asp->device, query, qresp, sizeof(qresp), 339 ASP_QUERY_TIMEOUT); 340 if (res) { 341 if (errno) { 342 D("Query '%s' failed on I/O: %s", query, strerror(errno)); 343 } else { 344 D("Query '%s' failed on device: %s", query, qresp); 345 } 346 } 347 return res; 348 } 349 350 int 351 sensors_port_start(AndroidSensorsPort* asp) 352 { 353 char qresp[ASP_MAX_SENSOR_MSG]; 354 const int res = 355 android_device_query(asp->device, "start", qresp, sizeof(qresp), 356 ASP_QUERY_TIMEOUT); 357 if (res) { 358 if (errno) { 359 D("Query 'start' failed on I/O: %s", strerror(errno)); 360 } else { 361 D("Query 'start' failed on device: %s", qresp); 362 } 363 } 364 return res; 365 } 366 367 int 368 sensors_port_stop(AndroidSensorsPort* asp) 369 { 370 char qresp[ASP_MAX_SENSOR_MSG]; 371 const int res = 372 android_device_query(asp->device, "stop", qresp, sizeof(qresp), 373 ASP_QUERY_TIMEOUT); 374 if (res) { 375 if (errno) { 376 D("Query 'stop' failed on I/O: %s", strerror(errno)); 377 } else { 378 D("Query 'stop' failed on device: %s", qresp); 379 } 380 } 381 382 return res; 383 } 384