blob: 6831fe35faa69928150a6171b958d114a0811129 [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
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070017#include "android/sdk-controller-socket.h"
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070018#include "android/sensors-port.h"
19#include "android/hw-sensors.h"
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070020#include "android/utils/debug.h"
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070021
22#define E(...) derror(__VA_ARGS__)
23#define W(...) dwarning(__VA_ARGS__)
24#define D(...) VERBOSE_PRINT(sensors_port,__VA_ARGS__)
Vladimir Chtchetkine9ef86362011-11-15 08:18:40 -080025#define D_ACTIVE VERBOSE_CHECK(sensors_port)
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070026
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070027#define TRACE_ON 1
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070028
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070029#if TRACE_ON
30#define T(...) VERBOSE_PRINT(sensors_port,__VA_ARGS__)
31#else
32#define T(...)
33#endif
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070034
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070035/* Timeout (millisec) to use when communicating with SDK controller. */
36#define SDKCTL_SENSORS_TIMEOUT 3000
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070037
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070038/*
39 * Queries sent to sensors port of the SDK controller.
40 */
41
42/* Queries the port for list of available sensors. */
43#define SDKCTL_SENSORS_QUERY_LIST 1
44
45/*
46 * Messages sent between the emuator, and sensors port of the SDK controller.
47 */
48
49/* Starts sensor emulation. */
50#define SDKCTL_SENSORS_START 1
51/* Stops sensor emulation. */
52#define SENSOR_SENSORS_STOP 2
53/* Enables emulation for a sensor. */
54#define SDKCTL_SENSORS_ENABLE 3
55/* Disables emulation for a sensor. */
56#define SDKCTL_SENSORS_DISABLE 4
57/* This message delivers sensor values. */
58#define SDKCTL_SENSORS_SENSOR_EVENT 5
59
60
61/* Describes a sensor on the device.
62 * When SDK controller sensors port replies to a "list" query, it replies with
63 * a flat buffer containing entries of this type following each other. End of
64 * each entry is a zero-terminator for its 'sensor_name' field. The end of the
65 * entire list is marked with an entry, containing -1 at its 'sensor_id' field.
66 */
67typedef struct SensorEntry {
68 /* Identifies sensor on the device. Value -1 indicates list terminator,
69 * rather than a valid sensor descriptor. */
70 int sensor_id;
71 /* Beginning of zero-terminated sensor name. */
72 char sensor_name[1];
73} SensorEntry;
74
75/* Describes a sensor in the array of emulated sensors. */
76typedef struct SensorDescriptor {
77 /* Identifies sensor on the device. */
78 int sensor_id;
79 /* Identifies sensor in emulator. */
80 int emulator_id;
81 /* Sensor name. */
82 char* sensor_name;
83} SensorDescriptor;
84
85/* Sensor event message descriptor.
86 * Entries of this type are sent along with SDKCTL_SENSORS_SENSOR_EVENT message
87 */
88typedef struct SensorEvent {
89 /* Identifies a device sensor for which values have been delivered. */
90 int sensor_id;
91 /* Sensor values. */
92 float fvalues[3];
93} SensorEvent;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070094
95/* Sensors port descriptor. */
96struct AndroidSensorsPort {
97 /* Caller identifier. */
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -070098 void* opaque;
99 /* Communication socket. */
100 SDKCtlSocket* sdkctl;
101 /* Lists sensors available for emulation. */
102 SensorDescriptor** sensors;
103 /* Number of sensors in 'sensors' list. */
104 int sensors_count;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700105};
106
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700107/********************************************************************************
108 * Sensors port internals
109 *******************************************************************************/
110
111/* Checks if sensor descriptor is the terminator.
112 * Return:
113 * Boolean, 1 if it is a terminator, 0 if it is not.
114 */
115static int
116_sensor_entry_is_terminator(const SensorEntry* entry)
117{
118 return entry == NULL || entry->sensor_id == -1;
119}
120
121/* Gets next sensor descriptor.
122 * Return:
123 * Next sensor desciptor, or NULL if there are no more descriptors in the list.
124 */
125static const SensorEntry*
126_sensor_entry_next(const SensorEntry* entry)
127{
128 if (!_sensor_entry_is_terminator(entry)) {
129 /* Next descriptor begins right after zero-terminator for the sensor_name
130 * field of this descriptor. */
131 entry = (const SensorEntry*)(entry->sensor_name + strlen(entry->sensor_name) + 1);
132 if (!_sensor_entry_is_terminator(entry)) {
133 return entry;
134 }
135 }
136 return NULL;
137}
138
139/* Gets number of entries in the list. */
140static int
141_sensor_entry_list_size(const SensorEntry* entry) {
142 int ret = 0;
143 while (!_sensor_entry_is_terminator(entry)) {
144 ret++;
145 entry = _sensor_entry_next(entry);
146 }
147 return ret;
148}
149
150/* Discards sensors saved in AndroidSensorsPort's array. */
151static void
152_sensors_port_discard_sensors(AndroidSensorsPort* asp)
153{
154 if (asp->sensors != NULL) {
155 int n;
156 for (n = 0; n < asp->sensors_count; n++) {
157 if (asp->sensors[n] != NULL) {
158 free(asp->sensors[n]->sensor_name);
159 AFREE(asp->sensors[n]);
160 }
161 }
162 free(asp->sensors);
163 asp->sensors = NULL;
164 }
165 asp->sensors_count = 0;
166}
167
168
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700169/* Destroys and frees the descriptor. */
170static void
171_sensors_port_free(AndroidSensorsPort* asp)
172{
173 if (asp != NULL) {
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700174 _sensors_port_discard_sensors(asp);
175 if (asp->sdkctl != NULL) {
176 sdkctl_socket_release(asp->sdkctl);
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700177 }
178 AFREE(asp);
179 }
180}
181
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700182/* Parses flat sensor list, and saves its entries into 'sensors' array filed of
183 * the AndroidSensorsPort descriptor. */
184static void
185_sensors_port_save_sensors(AndroidSensorsPort* asp, const SensorEntry* list)
186{
187 const int count = _sensor_entry_list_size(list);
188 if (count != 0) {
189 int n;
190 /* Allocate array for sensor descriptors. */
191 asp->sensors = malloc(sizeof(SensorDescriptor*) * count);
192
193 /* Iterate through the flat sensor list, filling up array of emulated
194 * sensors. */
195 const SensorEntry* entry = _sensor_entry_is_terminator(list) ? NULL : list;
196 for (n = 0; n < count && entry != NULL; n++) {
197 /* Get emulator-side ID for the sensor. < 0 value indicates that
198 * sensor is not supported by the emulator. */
199 const int emulator_id =
200 android_sensors_get_id_from_name((char*)entry->sensor_name);
201 if (emulator_id >= 0) {
202 SensorDescriptor* desc;
203 ANEW0(desc);
204 desc->emulator_id = emulator_id;
205 desc->sensor_id = entry->sensor_id;
206 desc->sensor_name = ASTRDUP(entry->sensor_name);
207
208 asp->sensors[asp->sensors_count++] = desc;
209 D("Sensors: Emulated sensor '%s': Device id = %d, Emulator id = %d",
210 desc->sensor_name, desc->sensor_id, desc->emulator_id);
211 } else {
212 D("Sensors: Sensor '%s' is not support by emulator",
213 entry->sensor_name);
214 }
215 entry = _sensor_entry_next(entry);
216 }
217 D("Sensors: Emulating %d sensors", asp->sensors_count);
218 }
219}
220
221/* Finds sensor descriptor for an SDK controller-side ID. */
222static const SensorDescriptor*
223_sensor_from_sdkctl_id(AndroidSensorsPort* asp, int id)
224{
225 int n;
226 for (n = 0; n < asp->sensors_count; n++) {
227 if (asp->sensors[n]->sensor_id == id) {
228 return asp->sensors[n];
229 }
230 }
231 return NULL;
232}
233
234/* Initiates sensor emulation.
235 * Param:
236 * asp - Android sensors port instance returned from sensors_port_create.
237 * Return:
238 * Zero on success, failure otherwise.
239 */
240static void
241_sensors_port_start(AndroidSensorsPort* asp)
242{
243 int n;
244
245 if (!sdkctl_socket_is_port_ready(asp->sdkctl)) {
246 /* SDK controller side is not ready for emulation. Retreat... */
247 D("Sensors: SDK controller side is not ready for emulation.");
248 return;
249 }
250
251 /* Disable all sensors, and reenable only those that are emulated by
252 * hardware. */
253 sensors_port_disable_sensor(asp, "all");
254
255 /* Walk throuh the list of enabled sensors enabling them on the device. */
256 for (n = 0; n < asp->sensors_count; n++) {
257 if (android_sensors_get_sensor_status(asp->sensors[n]->emulator_id) == 1) {
258 /* Reenable emulation for this sensor. */
259 sensors_port_enable_sensor(asp, asp->sensors[n]->sensor_name);
260 D("Sensors: Sensor '%s' is enabled on SDK controller.",
261 asp->sensors[n]->sensor_name);
262 }
263 }
264
265 /* Start the emulation. */
266 SDKCtlMessage* const msg =
267 sdkctl_message_send(asp->sdkctl, SDKCTL_SENSORS_START, NULL, 0);
268 sdkctl_message_release(msg);
269
270 D("Sensors: Emulation has been started.");
271}
272
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700273/********************************************************************************
274 * Sensors port callbacks
275 *******************************************************************************/
276
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700277/* Completion for the "list" query. */
278static AsyncIOAction
279_on_sensor_list_query(void* query_opaque,
280 SDKCtlQuery* query,
281 AsyncIOState status)
282{
283 AndroidSensorsPort* const asp = (AndroidSensorsPort*)(query_opaque);
284 if (status != ASIO_STATE_SUCCEEDED) {
285 /* We don't really care about failures at this point. They will
286 * eventually surface up in another place. */
287 return ASIO_ACTION_DONE;
288 }
289
290 /* Parse query response which is a flat list of SensorEntry entries. */
291 const SensorEntry* const list =
292 (const SensorEntry*)sdkctl_query_get_buffer_out(query);
293 D("Sensors: Sensor list received with %d sensors.",
294 _sensor_entry_list_size(list));
295 _sensors_port_save_sensors(asp, list);
296
297 /* At this point we are ready to statr sensor emulation. */
298 _sensors_port_start(asp);
299
300 return ASIO_ACTION_DONE;
301}
302
303/* A callback that is invoked on sensor events.
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700304 * Param:
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700305 * asp - AndroidSensorsPort instance.
306 * event - Sensor event.
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700307 */
308static void
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700309_on_sensor_event(AndroidSensorsPort* asp, const SensorEvent* event)
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700310{
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700311 /* Find corresponding server descriptor. */
312 const SensorDescriptor* const desc =
313 _sensor_from_sdkctl_id(asp, event->sensor_id);
314 if (desc != NULL) {
315 T("Sensors: %s -> %f, %f, %f", desc->sensor_name,
316 event->fvalues[0], event->fvalues[1],
317 event->fvalues[2]);
318 /* Fire up sensor change in the guest. */
319 android_sensors_set(desc->emulator_id, event->fvalues[0],
320 event->fvalues[1], event->fvalues[2]);
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700321 } else {
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700322 W("Sensors: No descriptor for sensor %d", event->sensor_id);
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700323 }
324}
325
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700326/* A callback that is invoked on SDK controller socket connection events. */
327static AsyncIOAction
328_on_sensors_socket_connection(void* client_opaque,
329 SDKCtlSocket* sdkctl,
330 AsyncIOState status)
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700331{
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700332 AndroidSensorsPort* const asp = (AndroidSensorsPort*)client_opaque;
333 if (status == ASIO_STATE_FAILED) {
334 /* Disconnection could mean that user is swapping devices. New device may
335 * have different set of sensors, so we need to re-query sensor list on
336 * reconnection. */
337 _sensors_port_discard_sensors(asp);
338
339 /* Reconnect (after timeout delay) on failures */
340 if (sdkctl_socket_is_handshake_ok(sdkctl)) {
341 sdkctl_socket_reconnect(sdkctl, SDKCTL_DEFAULT_TCP_PORT,
342 SDKCTL_SENSORS_TIMEOUT);
343 }
344 }
345 return ASIO_ACTION_DONE;
346}
347
348/* A callback that is invoked on SDK controller port connection events. */
349static void
350_on_sensors_port_connection(void* client_opaque,
351 SDKCtlSocket* sdkctl,
352 SdkCtlPortStatus status)
353{
354 AndroidSensorsPort* const asp = (AndroidSensorsPort*)client_opaque;
355 switch (status) {
356 case SDKCTL_PORT_CONNECTED: {
357 D("Sensors: SDK Controller is connected.");
358 /* Query list of available sensors. */
359 SDKCtlQuery* const query =
360 sdkctl_query_build_and_send(asp->sdkctl, SDKCTL_SENSORS_QUERY_LIST,
361 0, NULL, NULL, NULL,
362 _on_sensor_list_query, asp,
363 SDKCTL_SENSORS_TIMEOUT);
364 sdkctl_query_release(query);
365 break;
366 }
367
368 case SDKCTL_PORT_DISCONNECTED:
369 _sensors_port_discard_sensors(asp);
370 D("Sensors: SDK Controller is disconnected.");
371 break;
372
373 case SDKCTL_PORT_ENABLED:
374 _sensors_port_start(asp);
375 D("Sensors: SDK Controller is enabled.");
376 break;
377
378 case SDKCTL_PORT_DISABLED:
379 D("Sensors: SDK Controller is disabled.");
380 break;
381
382 case SDKCTL_HANDSHAKE_CONNECTED:
383 D("Sensors: SDK Controller has succeeded handshake, and port is connected.");
384 break;
385
386 case SDKCTL_HANDSHAKE_NO_PORT:
387 D("Sensors: SDK Controller has succeeded handshake, and port is not connected.");
388 break;
389
390 case SDKCTL_HANDSHAKE_DUP:
391 E("Sensors: SDK Controller has failed the handshake due to port duplication.");
392 sdkctl_socket_disconnect(sdkctl);
393 break;
394
395 case SDKCTL_HANDSHAKE_UNKNOWN_QUERY:
396 E("Sensors: SDK Controller has failed the handshake due to unknown query.");
397 sdkctl_socket_disconnect(sdkctl);
398 break;
399
400 case SDKCTL_HANDSHAKE_UNKNOWN_RESPONSE:
401 default:
402 E("Sensors: Handshake has failed due to unknown reasons.");
403 sdkctl_socket_disconnect(sdkctl);
404 break;
405 }
406}
407
408/* A callback that is invoked when a message is received from SDK controller. */
409static void
410_on_sensors_message(void* client_opaque,
411 SDKCtlSocket* sdkctl,
412 SDKCtlMessage* message,
413 int msg_type,
414 void* msg_data,
415 int msg_size)
416{
417 AndroidSensorsPort* const asp = (AndroidSensorsPort*)client_opaque;
418 switch (msg_type) {
419 case SDKCTL_SENSORS_SENSOR_EVENT:
420 _on_sensor_event(asp, (const SensorEvent*)msg_data);
421 break;
422
423 default:
424 E("Sensors: Unknown message type %d", msg_type);
425 break;
426 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700427}
428
429/********************************************************************************
430 * Sensors port API
431 *******************************************************************************/
432
433AndroidSensorsPort*
434sensors_port_create(void* opaque)
435{
436 AndroidSensorsPort* asp;
Vladimir Chtchetkinec8aa2c52012-04-05 16:22:55 -0700437
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700438 ANEW0(asp);
439 asp->opaque = opaque;
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700440 asp->sensors = NULL;
441 asp->sensors_count = 0;
442 asp->sdkctl = sdkctl_socket_new(SDKCTL_SENSORS_TIMEOUT, "sensors",
443 _on_sensors_socket_connection,
444 _on_sensors_port_connection,
445 _on_sensors_message, asp);
446 sdkctl_init_recycler(asp->sdkctl, 76, 8);
447 sdkctl_socket_connect(asp->sdkctl, SDKCTL_DEFAULT_TCP_PORT,
448 SDKCTL_SENSORS_TIMEOUT);
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700449 return asp;
450}
451
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700452void
453sensors_port_destroy(AndroidSensorsPort* asp)
454{
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700455 if (asp->sdkctl != NULL) {
456 sdkctl_socket_disconnect(asp->sdkctl);
457 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700458 _sensors_port_free(asp);
459}
460
461int
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700462sensors_port_enable_sensor(AndroidSensorsPort* asp, const char* name)
463{
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700464 if (asp->sdkctl != NULL && sdkctl_socket_is_port_ready(asp->sdkctl)) {
465 SDKCtlMessage* const msg = sdkctl_message_send(asp->sdkctl,
466 SDKCTL_SENSORS_ENABLE,
467 name, strlen(name));
468 sdkctl_message_release(msg);
469 return 0;
470 } else {
471 return -1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700472 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700473}
474
475int
476sensors_port_disable_sensor(AndroidSensorsPort* asp, const char* name)
477{
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700478 if (asp->sdkctl != NULL && sdkctl_socket_is_port_ready(asp->sdkctl)) {
479 SDKCtlMessage* const msg = sdkctl_message_send(asp->sdkctl,
480 SDKCTL_SENSORS_DISABLE,
481 name, strlen(name));
482 sdkctl_message_release(msg);
483 return 0;
484 } else {
485 return -1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700486 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700487}