hw-sensors.c revision c7389bd69e570a2c8432b37399aff1976b021f0f
1/* Copyright (C) 2009 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12
13#include <math.h>
14#include "android/hw-sensors.h"
15#include "android/utils/debug.h"
16#include "android/utils/misc.h"
17#include "android/utils/system.h"
18#include "android/hw-qemud.h"
19#include "android/globals.h"
20#include "hw/hw.h"
21#include "qemu-char.h"
22#include "qemu-timer.h"
23#include "android/sensors-port.h"
24
25#define  E(...)    derror(__VA_ARGS__)
26#define  W(...)    dwarning(__VA_ARGS__)
27#define  D(...)  VERBOSE_PRINT(sensors,__VA_ARGS__)
28#define  V(...)  VERBOSE_PRINT(init,__VA_ARGS__)
29
30/* define T_ACTIVE to 1 to debug transport communications */
31#define  T_ACTIVE  0
32
33#if T_ACTIVE
34#define  T(...)  VERBOSE_PRINT(sensors,__VA_ARGS__)
35#else
36#define  T(...)   ((void)0)
37#endif
38
39/* this code supports emulated sensor hardware
40 *
41 * Note that currently, only the accelerometer is really emulated, and only
42 * for the purpose of allowing auto-rotating the screen in keyboard-less
43 * configurations.
44 *
45 *
46 */
47
48
49static const struct {
50    const char*  name;
51    int          id;
52} _sSensors[MAX_SENSORS] = {
53#define SENSOR_(x,y)  { y, ANDROID_SENSOR_##x },
54  SENSORS_LIST
55#undef SENSOR_
56};
57
58
59static int
60_sensorIdFromName( const char*  name )
61{
62    int  nn;
63    for (nn = 0; nn < MAX_SENSORS; nn++)
64        if (!strcmp(_sSensors[nn].name,name))
65            return _sSensors[nn].id;
66    return -1;
67}
68
69static const char*
70_sensorNameFromId( int  id )
71{
72    int  nn;
73    for (nn = 0; nn < MAX_SENSORS; nn++)
74        if (id == _sSensors[nn].id)
75            return _sSensors[nn].name;
76    return NULL;
77}
78
79/* For common Sensor Value struct */
80typedef struct {
81    float a, b, c;
82} SensorValues;
83
84typedef struct {
85    float   x, y, z;
86} Acceleration;
87
88
89typedef struct {
90    float  x, y, z;
91} MagneticField;
92
93
94typedef struct {
95    float  azimuth;
96    float  pitch;
97    float  roll;
98} Orientation;
99
100
101typedef struct {
102    float  celsius;
103} Temperature;
104
105
106typedef struct {
107    float  value;
108} Proximity;
109
110typedef struct {
111    char       enabled;
112    union {
113        SensorValues   value;
114        Acceleration   acceleration;
115        MagneticField  magnetic;
116        Orientation    orientation;
117        Temperature    temperature;
118        Proximity      proximity;
119    } u;
120} Sensor;
121
122/*
123 * - when the qemu-specific sensors HAL module starts, it sends
124 *   "list-sensors"
125 *
126 * - this code replies with a string containing an integer corresponding
127 *   to a bitmap of available hardware sensors in the current AVD
128 *   configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
129 *
130 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
131 *   the report of a given sensor state. <sensor> must be the name of
132 *   a given sensor (e.g. "accelerometer"), and <flag> must be either
133 *   "1" (to enable) or "0" (to disable).
134 *
135 * - Once at least one sensor is "enabled", this code should periodically
136 *   send information about the corresponding enabled sensors. The default
137 *   period is 200ms.
138 *
139 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
140 *   corresponding to a time delay in milli-seconds. This corresponds to
141 *   a new interval between sensor events sent by this code to the HAL
142 *   module.
143 *
144 * - the HAL module can also send a "wake" command. This code should simply
145 *   send the "wake" back to the module. This is used internally to wake a
146 *   blocking read that happens in a different thread. This ping-pong makes
147 *   the code in the HAL module very simple.
148 *
149 * - each timer tick, this code sends sensor reports in the following
150 *   format (each line corresponds to a different line sent to the module):
151 *
152 *      acceleration:<x>:<y>:<z>
153 *      magnetic-field:<x>:<y>:<z>
154 *      orientation:<azimuth>:<pitch>:<roll>
155 *      temperature:<celsius>
156 *      sync:<time_us>
157 *
158 *   Where each line before the sync:<time_us> is optional and will only
159 *   appear if the corresponding sensor has been enabled by the HAL module.
160 *
161 *   Note that <time_us> is the VM time in micro-seconds when the report
162 *   was "taken" by this code. This is adjusted by the HAL module to
163 *   emulated system time (using the first sync: to compute an adjustment
164 *   offset).
165 */
166#define  HEADER_SIZE  4
167#define  BUFFER_SIZE  512
168
169typedef struct HwSensorClient   HwSensorClient;
170
171typedef struct {
172    QemudService*       service;
173    Sensor              sensors[MAX_SENSORS];
174    HwSensorClient*     clients;
175    AndroidSensorsPort* sensors_port;
176} HwSensors;
177
178struct HwSensorClient {
179    HwSensorClient*  next;
180    HwSensors*       sensors;
181    QemudClient*     client;
182    QEMUTimer*       timer;
183    uint32_t         enabledMask;
184    int32_t          delay_ms;
185};
186
187static void
188_hwSensorClient_free( HwSensorClient*  cl )
189{
190    /* remove from sensors's list */
191    if (cl->sensors) {
192        HwSensorClient**  pnode = &cl->sensors->clients;
193        for (;;) {
194            HwSensorClient*  node = *pnode;
195            if (node == NULL)
196                break;
197            if (node == cl) {
198                *pnode = cl->next;
199                break;
200            }
201            pnode = &node->next;
202        }
203        cl->next    = NULL;
204        cl->sensors = NULL;
205    }
206
207    /* close QEMUD client, if any */
208    if (cl->client) {
209        qemud_client_close(cl->client);
210        cl->client = NULL;
211    }
212    /* remove timer, if any */
213    if (cl->timer) {
214        qemu_del_timer(cl->timer);
215        qemu_free_timer(cl->timer);
216        cl->timer = NULL;
217    }
218    AFREE(cl);
219}
220
221/* forward */
222static void  _hwSensorClient_tick(void*  opaque);
223
224
225static HwSensorClient*
226_hwSensorClient_new( HwSensors*  sensors )
227{
228    HwSensorClient*  cl;
229
230    ANEW0(cl);
231
232    cl->sensors     = sensors;
233    cl->enabledMask = 0;
234    cl->delay_ms    = 800;
235    cl->timer       = qemu_new_timer_ns(vm_clock, _hwSensorClient_tick, cl);
236
237    cl->next         = sensors->clients;
238    sensors->clients = cl;
239
240    return cl;
241}
242
243/* forward */
244
245static void  _hwSensorClient_receive( HwSensorClient*  cl,
246                                      uint8_t*         query,
247                                      int              querylen );
248
249/* Qemud service management */
250
251static void
252_hwSensorClient_recv( void*  opaque, uint8_t*  msg, int  msglen,
253                      QemudClient*  client )
254{
255    HwSensorClient*  cl = opaque;
256
257    _hwSensorClient_receive(cl, msg, msglen);
258}
259
260static void
261_hwSensorClient_close( void*  opaque )
262{
263    HwSensorClient*  cl = opaque;
264
265    /* the client is already closed here */
266    cl->client = NULL;
267    _hwSensorClient_free(cl);
268}
269
270/* send a one-line message to the HAL module through a qemud channel */
271static void
272_hwSensorClient_send( HwSensorClient*  cl, const uint8_t*  msg, int  msglen )
273{
274    D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
275    qemud_client_send(cl->client, msg, msglen);
276}
277
278static int
279_hwSensorClient_enabled( HwSensorClient*  cl, int  sensorId )
280{
281    return (cl->enabledMask & (1 << sensorId)) != 0;
282}
283
284/* this function is called periodically to send sensor reports
285 * to the HAL module, and re-arm the timer if necessary
286 */
287static void
288_hwSensorClient_tick( void*  opaque )
289{
290    HwSensorClient*  cl = opaque;
291    HwSensors*       hw  = cl->sensors;
292    int64_t          delay = cl->delay_ms;
293    int64_t          now_ns;
294    uint32_t         mask  = cl->enabledMask;
295    Sensor*          sensor;
296    char             buffer[128];
297
298    if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
299        sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
300        snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
301                 sensor->u.acceleration.x,
302                 sensor->u.acceleration.y,
303                 sensor->u.acceleration.z);
304        _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
305    }
306
307    if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
308        sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
309        /* NOTE: sensors HAL expects "magnetic", not "magnetic-field" name here. */
310        snprintf(buffer, sizeof buffer, "magnetic:%g:%g:%g",
311                 sensor->u.magnetic.x,
312                 sensor->u.magnetic.y,
313                 sensor->u.magnetic.z);
314        _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
315    }
316
317    if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
318        sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
319        snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
320                 sensor->u.orientation.azimuth,
321                 sensor->u.orientation.pitch,
322                 sensor->u.orientation.roll);
323        _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
324    }
325
326    if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
327        sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
328        snprintf(buffer, sizeof buffer, "temperature:%g",
329                 sensor->u.temperature.celsius);
330        _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
331    }
332
333    if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
334        sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
335        snprintf(buffer, sizeof buffer, "proximity:%g",
336                 sensor->u.proximity.value);
337        _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
338    }
339
340    now_ns = qemu_get_clock_ns(vm_clock);
341
342    snprintf(buffer, sizeof buffer, "sync:%" PRId64, now_ns/1000);
343    _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
344
345    /* rearm timer, use a minimum delay of 20 ms, just to
346     * be safe.
347     */
348    if (mask == 0)
349        return;
350
351    if (delay < 20)
352        delay = 20;
353
354    delay *= 1000000LL;  /* convert to nanoseconds */
355    qemu_mod_timer(cl->timer, now_ns + delay);
356}
357
358/* handle incoming messages from the HAL module */
359static void
360_hwSensorClient_receive( HwSensorClient*  cl, uint8_t*  msg, int  msglen )
361{
362    HwSensors*  hw = cl->sensors;
363
364    D("%s: '%.*s'", __FUNCTION__, msglen, msg);
365
366    /* "list-sensors" is used to get an integer bit map of
367     * available emulated sensors. We compute the mask from the
368     * current hardware configuration.
369     */
370    if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
371        char  buff[12];
372        int   mask = 0;
373        int   nn;
374
375        for (nn = 0; nn < MAX_SENSORS; nn++) {
376            if (hw->sensors[nn].enabled)
377                mask |= (1 << nn);
378        }
379
380        snprintf(buff, sizeof buff, "%d", mask);
381        _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
382        return;
383    }
384
385    /* "wake" is a special message that must be sent back through
386     * the channel. It is used to exit a blocking read.
387     */
388    if (msglen == 4 && !memcmp(msg, "wake", 4)) {
389        _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
390        return;
391    }
392
393    /* "set-delay:<delay>" is used to set the delay in milliseconds
394     * between sensor events
395     */
396    if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
397        cl->delay_ms = atoi((const char*)msg+10);
398        if (cl->enabledMask != 0)
399            _hwSensorClient_tick(cl);
400
401        return;
402    }
403
404    /* "set:<name>:<state>" is used to enable/disable a given
405     * sensor. <state> must be 0 or 1
406     */
407    if (msglen > 4 && !memcmp(msg, "set:", 4)) {
408        char*  q;
409        int    id, enabled, oldEnabledMask = cl->enabledMask;
410        msg += 4;
411        q    = strchr((char*)msg, ':');
412        if (q == NULL) {  /* should not happen */
413            D("%s: ignore bad 'set' command", __FUNCTION__);
414            return;
415        }
416        *q++ = 0;
417
418        id = _sensorIdFromName((const char*)msg);
419        if (id < 0 || id >= MAX_SENSORS) {
420            D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
421            return;
422        }
423
424        if (!hw->sensors[id].enabled) {
425            D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
426            return;
427        }
428        enabled = (q[0] == '1');
429
430        if (enabled)
431            cl->enabledMask |= (1 << id);
432        else
433            cl->enabledMask &= ~(1 << id);
434
435        if (cl->enabledMask != oldEnabledMask) {
436            D("%s: %s %s sensor", __FUNCTION__,
437                (cl->enabledMask & (1 << id))  ? "enabling" : "disabling",  msg);
438        }
439
440        /* If emulating device is connected update sensor state there too. */
441        if (hw->sensors_port != NULL && sensors_port_is_connected(hw->sensors_port)) {
442            if (enabled) {
443                sensors_port_enable_sensor(hw->sensors_port, (const char*)msg);
444            } else {
445                sensors_port_disable_sensor(hw->sensors_port, (const char*)msg);
446            }
447        }
448
449        _hwSensorClient_tick(cl);
450        return;
451    }
452
453    D("%s: ignoring unknown query", __FUNCTION__);
454}
455
456/* Saves sensor-specific client data to snapshot */
457static void
458_hwSensorClient_save( QEMUFile*  f, QemudClient*  client, void*  opaque  )
459{
460    HwSensorClient* sc = opaque;
461
462    qemu_put_be32(f, sc->delay_ms);
463    qemu_put_be32(f, sc->enabledMask);
464    qemu_put_timer(f, sc->timer);
465}
466
467/* Loads sensor-specific client data from snapshot */
468static int
469_hwSensorClient_load( QEMUFile*  f, QemudClient*  client, void*  opaque  )
470{
471    HwSensorClient* sc = opaque;
472
473    sc->delay_ms = qemu_get_be32(f);
474    sc->enabledMask = qemu_get_be32(f);
475    qemu_get_timer(f, sc->timer);
476
477    return 0;
478}
479
480static QemudClient*
481_hwSensors_connect( void*  opaque,
482                    QemudService*  service,
483                    int  channel,
484                    const char* client_param )
485{
486    HwSensors*       sensors = opaque;
487    HwSensorClient*  cl      = _hwSensorClient_new(sensors);
488    QemudClient*     client  = qemud_client_new(service, channel, client_param, cl,
489                                                _hwSensorClient_recv,
490                                                _hwSensorClient_close,
491                                                _hwSensorClient_save,
492                                                _hwSensorClient_load );
493    qemud_client_set_framing(client, 1);
494    cl->client = client;
495
496    return client;
497}
498
499/* change the value of the emulated sensor vector */
500static void
501_hwSensors_setSensorValue( HwSensors*  h, int sensor_id, float a, float b, float c )
502{
503    Sensor* s = &h->sensors[sensor_id];
504
505    s->u.value.a = a;
506    s->u.value.b = b;
507    s->u.value.c = c;
508}
509
510/* Saves available sensors to allow checking availability when loaded.
511 */
512static void
513_hwSensors_save( QEMUFile*  f, QemudService*  sv, void*  opaque)
514{
515    HwSensors* h = opaque;
516
517    // number of sensors
518    qemu_put_be32(f, MAX_SENSORS);
519    AndroidSensor i;
520    for (i = 0 ; i < MAX_SENSORS; i++) {
521        Sensor* s = &h->sensors[i];
522        qemu_put_be32(f, s->enabled);
523
524        /* this switch ensures that a warning is raised when a new sensor is
525         * added and is not added here as well.
526         */
527        switch (i) {
528        case ANDROID_SENSOR_ACCELERATION:
529            qemu_put_float(f, s->u.acceleration.x);
530            qemu_put_float(f, s->u.acceleration.y);
531            qemu_put_float(f, s->u.acceleration.z);
532            break;
533        case ANDROID_SENSOR_MAGNETIC_FIELD:
534            qemu_put_float(f, s->u.magnetic.x);
535            qemu_put_float(f, s->u.magnetic.y);
536            qemu_put_float(f, s->u.magnetic.z);
537            break;
538        case ANDROID_SENSOR_ORIENTATION:
539            qemu_put_float(f, s->u.orientation.azimuth);
540            qemu_put_float(f, s->u.orientation.pitch);
541            qemu_put_float(f, s->u.orientation.roll);
542            break;
543        case ANDROID_SENSOR_TEMPERATURE:
544            qemu_put_float(f, s->u.temperature.celsius);
545            break;
546        case ANDROID_SENSOR_PROXIMITY:
547            qemu_put_float(f, s->u.proximity.value);
548            break;
549        case MAX_SENSORS:
550            break;
551        }
552    }
553}
554
555
556static int
557_hwSensors_load( QEMUFile*  f, QemudService*  s, void*  opaque)
558{
559    HwSensors* h = opaque;
560
561    /* check number of sensors */
562    int32_t num_sensors = qemu_get_be32(f);
563    if (num_sensors > MAX_SENSORS) {
564        D("%s: cannot load: snapshot requires %d sensors, %d available\n",
565          __FUNCTION__, num_sensors, MAX_SENSORS);
566        return -EIO;
567    }
568
569    /* load sensor state */
570    AndroidSensor i;
571    for (i = 0 ; i < num_sensors; i++) {
572        Sensor* s = &h->sensors[i];
573        s->enabled = qemu_get_be32(f);
574
575        /* this switch ensures that a warning is raised when a new sensor is
576         * added and is not added here as well.
577         */
578        switch (i) {
579        case ANDROID_SENSOR_ACCELERATION:
580            s->u.acceleration.x = qemu_get_float(f);
581            s->u.acceleration.y = qemu_get_float(f);
582            s->u.acceleration.z = qemu_get_float(f);
583            break;
584        case ANDROID_SENSOR_MAGNETIC_FIELD:
585            s->u.magnetic.x = qemu_get_float(f);
586            s->u.magnetic.y = qemu_get_float(f);
587            s->u.magnetic.z = qemu_get_float(f);
588            break;
589        case ANDROID_SENSOR_ORIENTATION:
590            s->u.orientation.azimuth = qemu_get_float(f);
591            s->u.orientation.pitch   = qemu_get_float(f);
592            s->u.orientation.roll    = qemu_get_float(f);
593            break;
594        case ANDROID_SENSOR_TEMPERATURE:
595            s->u.temperature.celsius = qemu_get_float(f);
596            break;
597        case ANDROID_SENSOR_PROXIMITY:
598            s->u.proximity.value = qemu_get_float(f);
599            break;
600        case MAX_SENSORS:
601            break;
602        }
603    }
604
605    /* The following is necessary when we resume a snaphost
606     * created by an older version of the emulator that provided
607     * less hardware sensors.
608     */
609    for ( ; i < MAX_SENSORS; i++ ) {
610        h->sensors[i].enabled = 0;
611    }
612
613    return 0;
614}
615
616
617/* change the emulated proximity */
618static void
619_hwSensors_setProximity( HwSensors*  h, float value )
620{
621    Sensor*  s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
622    s->u.proximity.value = value;
623}
624
625/* change the coarse orientation (landscape/portrait) of the emulated device */
626static void
627_hwSensors_setCoarseOrientation( HwSensors*  h, AndroidCoarseOrientation  orient )
628{
629    /* The Android framework computes the orientation by looking at
630     * the accelerometer sensor (*not* the orientation sensor !)
631     *
632     * That's because the gravity is a constant 9.81 vector that
633     * can be determined quite easily.
634     *
635     * Also, for some reason, the framework code considers that the phone should
636     * be inclined by 30 degrees along the phone's X axis to be considered
637     * in its ideal "vertical" position
638     *
639     * If the phone is completely vertical, rotating it will not do anything !
640     */
641    const double  g      = 9.81;
642    const double  angle  = 20.0;
643    const double  cos_angle = cos(angle/M_PI);
644    const double  sin_angle = sin(angle/M_PI);
645
646    switch (orient) {
647    case ANDROID_COARSE_PORTRAIT:
648        _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, 0., g*cos_angle, g*sin_angle );
649        break;
650
651    case ANDROID_COARSE_LANDSCAPE:
652        _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, g*cos_angle, 0., g*sin_angle );
653        break;
654    default:
655        ;
656    }
657}
658
659
660/* initialize the sensors state */
661static void
662_hwSensors_init( HwSensors*  h )
663{
664    /* Try to see if there is a device attached that can be used for
665     * sensor emulation. */
666    h->sensors_port = sensors_port_create(h);
667    if (h->sensors_port == NULL) {
668        V("Realistic sensor emulation is not available, since the remote controller is not accessible:\n %s",
669          strerror(errno));
670    }
671
672    h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
673                                        _hwSensors_save, _hwSensors_load);
674
675    if (android_hw->hw_accelerometer) {
676        h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
677    }
678
679    if (android_hw->hw_sensors_proximity) {
680        h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
681    }
682
683    if (android_hw->hw_sensors_magnetic_field) {
684        h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD].enabled = 1;
685    }
686
687    if (android_hw->hw_sensors_orientation) {
688        h->sensors[ANDROID_SENSOR_ORIENTATION].enabled = 1;
689    }
690
691    if (android_hw->hw_sensors_temperature) {
692        h->sensors[ANDROID_SENSOR_TEMPERATURE].enabled = 1;
693    }
694
695    if (h->sensors_port != NULL) {
696        /* Init sensors on the attached device. */
697        sensors_port_init_sensors(h->sensors_port);
698    }
699
700    /* XXX: TODO: Add other tests when we add the corresponding
701        * properties to hardware-properties.ini et al. */
702
703    _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
704    _hwSensors_setProximity(h, 1);
705}
706
707static HwSensors    _sensorsState[1];
708
709void
710android_hw_sensors_init( void )
711{
712    HwSensors*  hw = _sensorsState;
713
714    if (hw->service == NULL) {
715        _hwSensors_init(hw);
716        D("%s: sensors qemud service initialized", __FUNCTION__);
717    }
718}
719
720/* change the coarse orientation value */
721extern void
722android_sensors_set_coarse_orientation( AndroidCoarseOrientation  orient )
723{
724    android_hw_sensors_init();
725    _hwSensors_setCoarseOrientation(_sensorsState, orient);
726}
727
728/* Get sensor name from sensor id */
729extern const char*
730android_sensors_get_name_from_id( int sensor_id )
731{
732    if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
733        return NULL;
734
735    return _sensorNameFromId(sensor_id);
736}
737
738/* Get sensor id from sensor name */
739extern int
740android_sensors_get_id_from_name( char* sensorname )
741{
742    HwSensors* hw = _sensorsState;
743
744    if (sensorname == NULL)
745        return SENSOR_STATUS_UNKNOWN;
746
747    int id = _sensorIdFromName(sensorname);
748
749    if (id < 0 || id >= MAX_SENSORS)
750        return SENSOR_STATUS_UNKNOWN;
751
752    if (hw->service != NULL) {
753        if (! hw->sensors[id].enabled)
754            return SENSOR_STATUS_DISABLED;
755    } else
756        return SENSOR_STATUS_NO_SERVICE;
757
758    return id;
759}
760
761/* Interface of reading the data for all sensors */
762extern int
763android_sensors_get( int sensor_id, float* a, float* b, float* c )
764{
765    HwSensors* hw = _sensorsState;
766
767    *a = 0;
768    *b = 0;
769    *c = 0;
770
771    if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
772        return SENSOR_STATUS_UNKNOWN;
773
774    Sensor* sensor = &hw->sensors[sensor_id];
775    if (hw->service != NULL) {
776        if (! sensor->enabled)
777            return SENSOR_STATUS_DISABLED;
778    } else
779        return SENSOR_STATUS_NO_SERVICE;
780
781    *a = sensor->u.value.a;
782    *b = sensor->u.value.b;
783    *c = sensor->u.value.c;
784
785    return SENSOR_STATUS_OK;
786}
787
788/* Interface of setting the data for all sensors */
789extern int
790android_sensors_set( int sensor_id, float a, float b, float c )
791{
792    HwSensors* hw = _sensorsState;
793
794    if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
795        return SENSOR_STATUS_UNKNOWN;
796
797    if (hw->service != NULL) {
798        if (! hw->sensors[sensor_id].enabled)
799            return SENSOR_STATUS_DISABLED;
800    } else
801        return SENSOR_STATUS_NO_SERVICE;
802
803    _hwSensors_setSensorValue(hw, sensor_id, a, b, c);
804
805    return SENSOR_STATUS_OK;
806}
807
808/* Get Sensor from sensor id */
809extern uint8_t
810android_sensors_get_sensor_status( int sensor_id )
811{
812    HwSensors* hw = _sensorsState;
813
814    if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
815        return SENSOR_STATUS_UNKNOWN;
816
817    return hw->sensors[sensor_id].enabled;
818}
819