diff options
Diffstat (limited to 'android')
-rw-r--r-- | android/hw-sensors.c | 391 |
1 files changed, 238 insertions, 153 deletions
diff --git a/android/hw-sensors.c b/android/hw-sensors.c index 37d4af7..1fa12dc 100644 --- a/android/hw-sensors.c +++ b/android/hw-sensors.c @@ -13,6 +13,7 @@ #include "android/hw-sensors.h" #include "android/utils/debug.h" #include "android/utils/misc.h" +#include "android/utils/system.h" #include "android/hw-qemud.h" #include "android/globals.h" #include "qemu-char.h" @@ -139,189 +140,172 @@ typedef struct { #define HEADER_SIZE 4 #define BUFFER_SIZE 512 +typedef struct HwSensorClient HwSensorClient; + typedef struct { - QemudService* service; - int32_t delay_ms; - uint32_t enabledMask; - QEMUTimer* timer; - Sensor sensors[MAX_SENSORS]; + QemudService* service; + Sensor sensors[MAX_SENSORS]; + HwSensorClient* clients; } HwSensors; -/* forward */ - -static void hw_sensors_receive( HwSensors* h, - uint8_t* query, - int querylen ); - -static void hw_sensors_timer_tick(void* opaque); - -/* Qemud service management */ +struct HwSensorClient { + HwSensorClient* next; + HwSensors* sensors; + QemudClient* client; + QEMUTimer* timer; + uint32_t enabledMask; + int32_t delay_ms; +}; static void -_hw_sensors_qemud_client_recv( void* opaque, uint8_t* msg, int msglen, - QemudClient* client ) +_hwSensorClient_free( HwSensorClient* cl ) { - hw_sensors_receive(opaque, msg, msglen); -} + /* remove from sensors's list */ + if (cl->sensors) { + HwSensorClient** pnode = &cl->sensors->clients; + for (;;) { + HwSensorClient* node = *pnode; + if (node == NULL) + break; + if (node == cl) { + *pnode = cl->next; + break; + } + pnode = &node->next; + } + cl->next = NULL; + cl->sensors = NULL; + } -static QemudClient* -_hw_sensors_service_connect( void* opaque, QemudService* service, int channel ) -{ - HwSensors* sensors = opaque; - QemudClient* client = qemud_client_new(service, channel, - sensors, - _hw_sensors_qemud_client_recv, - NULL); - qemud_client_set_framing(client, 1); - return client; + /* close QEMUD client, if any */ + if (cl->client) { + qemud_client_close(cl->client); + cl->client = NULL; + } + /* remove timer, if any */ + if (cl->timer) { + qemu_del_timer(cl->timer); + qemu_free_timer(cl->timer); + cl->timer = NULL; + } + AFREE(cl); } -/* change the value of the emulated acceleration vector */ -static void -hw_sensors_set_acceleration( HwSensors* h, float x, float y, float z ) -{ - Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION]; - s->u.acceleration.x = x; - s->u.acceleration.y = y; - s->u.acceleration.z = z; -} +/* forward */ +static void _hwSensorClient_tick(void* opaque); -#if 0 /* not used yet */ -/* change the value of the emulated magnetic vector */ -static void -hw_sensors_set_magnetic_field( HwSensors* h, float x, float y, float z ) -{ - Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; - s->u.magnetic.x = x; - s->u.magnetic.y = y; - s->u.magnetic.z = z; -} -/* change the values of the emulated orientation */ -static void -hw_sensors_set_orientation( HwSensors* h, float azimuth, float pitch, float roll ) +static HwSensorClient* +_hwSensorClient_new( HwSensors* sensors ) { - Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; - s->u.orientation.azimuth = azimuth; - s->u.orientation.pitch = pitch; - s->u.orientation.roll = roll; -} + HwSensorClient* cl; -/* change the emulated temperature */ -static void -hw_sensors_set_temperature( HwSensors* h, float celsius ) -{ - Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; - s->u.temperature.celsius = celsius; + ANEW0(cl); + + cl->sensors = sensors; + cl->enabledMask = 0; + cl->delay_ms = 1000; + cl->timer = qemu_new_timer(vm_clock, _hwSensorClient_tick, cl); + + cl->next = sensors->clients; + sensors->clients = cl; + + return cl; } -#endif -/* change the coarse orientation (landscape/portrait) of the emulated device */ +/* forward */ + +static void _hwSensorClient_receive( HwSensorClient* cl, + uint8_t* query, + int querylen ); + +/* Qemud service management */ + static void -hw_sensors_set_coarse_orientation( HwSensors* h, AndroidCoarseOrientation orient ) +_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen, + QemudClient* client ) { - /* The Android framework computes the orientation by looking at - * the accelerometer sensor (*not* the orientation sensor !) - * - * That's because the gravity is a constant 9.81 vector that - * can be determined quite easily. - * - * Also, for some reason, the framework code considers that the phone should - * be inclined by 30 degrees along the phone's X axis to be considered - * in its ideal "vertical" position - * - * If the phone is completely vertical, rotating it will not do anything ! - */ - const double g = 9.81; - const double cos_30 = 0.866025403784; - const double sin_30 = 0.5; + HwSensorClient* cl = opaque; - switch (orient) { - case ANDROID_COARSE_PORTRAIT: - hw_sensors_set_acceleration( h, 0., g*cos_30, g*sin_30 ); - break; - - case ANDROID_COARSE_LANDSCAPE: - hw_sensors_set_acceleration( h, g*cos_30, 0., g*sin_30 ); - break; - default: - ; - } + _hwSensorClient_receive(cl, msg, msglen); } - -/* initialize the sensors state */ static void -hw_sensors_init( HwSensors* h ) +_hwSensorClient_close( void* opaque ) { - h->service = qemud_service_register("sensors", 1, h, - _hw_sensors_service_connect ); - h->enabledMask = 0; - h->delay_ms = 1000; - h->timer = qemu_new_timer(vm_clock, hw_sensors_timer_tick, h); + HwSensorClient* cl = opaque; - hw_sensors_set_coarse_orientation(h, ANDROID_COARSE_PORTRAIT); + /* the client is already closed here */ + cl->client = NULL; + _hwSensorClient_free(cl); } /* send a one-line message to the HAL module through a qemud channel */ static void -hw_sensors_send( HwSensors* hw, const uint8_t* msg, int msglen ) +_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen ) { D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen)); - qemud_service_broadcast(hw->service, msg, msglen); + qemud_client_send(cl->client, msg, msglen); +} + +static int +_hwSensorClient_enabled( HwSensorClient* cl, int sensorId ) +{ + return (cl->enabledMask & (1 << sensorId)) != 0; } /* this function is called periodically to send sensor reports * to the HAL module, and re-arm the timer if necessary */ static void -hw_sensors_timer_tick( void* opaque ) +_hwSensorClient_tick( void* opaque ) { - HwSensors* h = opaque; - int64_t delay = h->delay_ms; - int64_t now_ns; - uint32_t mask = h->enabledMask; - Sensor* sensor; - char buffer[128]; - - sensor = &h->sensors[ANDROID_SENSOR_ACCELERATION]; - if (sensor->enabled) { + HwSensorClient* cl = opaque; + HwSensors* hw = cl->sensors; + int64_t delay = cl->delay_ms; + int64_t now_ns; + uint32_t mask = cl->enabledMask; + Sensor* sensor; + char buffer[128]; + + if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) { + sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION]; snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g", sensor->u.acceleration.x, sensor->u.acceleration.y, sensor->u.acceleration.z); - hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer)); + _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } - sensor = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; - if (sensor->enabled) { + if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) { + sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g", sensor->u.magnetic.x, sensor->u.magnetic.y, sensor->u.magnetic.z); - hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer)); + _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } - sensor = &h->sensors[ANDROID_SENSOR_ORIENTATION]; - if (sensor->enabled) { + if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) { + sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION]; snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g", sensor->u.orientation.azimuth, sensor->u.orientation.pitch, sensor->u.orientation.roll); - hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer)); + _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } - sensor = &h->sensors[ANDROID_SENSOR_TEMPERATURE]; - if (sensor->enabled) { + if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) { + sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE]; snprintf(buffer, sizeof buffer, "temperature:%g", sensor->u.temperature.celsius); - hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer)); + _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); } now_ns = qemu_get_clock(vm_clock); snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000); - hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer)); + _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); /* rearm timer, use a minimum delay of 20 ms, just to * be safe. @@ -333,13 +317,15 @@ hw_sensors_timer_tick( void* opaque ) delay = 20; delay *= 1000000LL; /* convert to nanoseconds */ - qemu_mod_timer(h->timer, now_ns + delay); + qemu_mod_timer(cl->timer, now_ns + delay); } /* handle incoming messages from the HAL module */ static void -hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) +_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen ) { + HwSensors* hw = cl->sensors; + D("%s: '%.*s'", __FUNCTION__, msglen, msg); /* "list-sensors" is used to get an integer bit map of @@ -349,15 +335,15 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) { char buff[12]; int mask = 0; + int nn; - if (android_hw->hw_accelerometer) - mask |= (1 << ANDROID_SENSOR_ACCELERATION); - - /* XXX: TODO: Add other tests when we add the corresponding - * properties to hardware-properties.ini et al. */ + for (nn = 0; nn < MAX_SENSORS; nn++) { + if (hw->sensors[nn].enabled) + mask |= (1 << nn); + } snprintf(buff, sizeof buff, "%d", mask); - hw_sensors_send(hw, (const uint8_t*)buff, strlen(buff)); + _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff)); return; } @@ -365,7 +351,7 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) * the channel. It is used to exit a blocking read. */ if (msglen == 4 && !memcmp(msg, "wake", 4)) { - hw_sensors_send(hw, (const uint8_t*)"wake", 4); + _hwSensorClient_send(cl, (const uint8_t*)"wake", 4); return; } @@ -373,9 +359,9 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) * between sensor events */ if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) { - hw->delay_ms = atoi((const char*)msg+10); - if (hw->enabledMask != 0) - hw_sensors_timer_tick(hw); + cl->delay_ms = atoi((const char*)msg+10); + if (cl->enabledMask != 0) + _hwSensorClient_tick(cl); return; } @@ -385,7 +371,7 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) */ if (msglen > 4 && !memcmp(msg, "set:", 4)) { char* q; - int id, enabled, oldEnabledMask = hw->enabledMask; + int id, enabled, oldEnabledMask = cl->enabledMask; msg += 4; q = strchr((char*)msg, ':'); if (q == NULL) { /* should not happen */ @@ -395,32 +381,27 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) *q++ = 0; id = _sensorIdFromName((const char*)msg); - if (id < 0) { + if (id < 0 || id >= MAX_SENSORS) { D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg); return; } + if (!hw->sensors[id].enabled) { + D("%s: trying to set disabled %s sensor", __FUNCTION__, msg); + return; + } enabled = (q[0] == '1'); - hw->sensors[id].enabled = (char) enabled; if (enabled) - hw->enabledMask |= (1 << id); + cl->enabledMask |= (1 << id); else - hw->enabledMask &= ~(1 << id); - - D("%s: %s %s sensor", __FUNCTION__, - hw->sensors[id].enabled ? "enabling" : "disabling", msg); + cl->enabledMask &= ~(1 << id); - if (oldEnabledMask == 0 && enabled) { - /* we enabled our first sensor, start event reporting */ - D("%s: starting event reporting (mask=%04x)", __FUNCTION__, - hw->enabledMask); - } - else if (hw->enabledMask == 0 && !enabled) { - /* we disabled our last sensor, stop event reporting */ - D("%s: stopping event reporting", __FUNCTION__); + if (cl->enabledMask != oldEnabledMask) { + D("%s: %s %s sensor", __FUNCTION__, + (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg); } - hw_sensors_timer_tick(hw); + _hwSensorClient_tick(cl); return; } @@ -428,6 +409,110 @@ hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen ) } +static QemudClient* +_hwSensors_connect( void* opaque, QemudService* service, int channel ) +{ + HwSensors* sensors = opaque; + HwSensorClient* cl = _hwSensorClient_new(sensors); + QemudClient* client = qemud_client_new(service, channel, cl, + _hwSensorClient_recv, + _hwSensorClient_close); + qemud_client_set_framing(client, 1); + cl->client = client; + + return client; +} + +/* change the value of the emulated acceleration vector */ +static void +_hwSensors_setAcceleration( HwSensors* h, float x, float y, float z ) +{ + Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION]; + s->u.acceleration.x = x; + s->u.acceleration.y = y; + s->u.acceleration.z = z; +} + +#if 0 /* not used yet */ +/* change the value of the emulated magnetic vector */ +static void +_hwSensors_setMagneticField( HwSensors* h, float x, float y, float z ) +{ + Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; + s->u.magnetic.x = x; + s->u.magnetic.y = y; + s->u.magnetic.z = z; +} + +/* change the values of the emulated orientation */ +static void +_hwSensors_setOrientation( HwSensors* h, float azimuth, float pitch, float roll ) +{ + Sensor* s = &h->sensors[ANDROID_SENSOR_ORIENTATION]; + s->u.orientation.azimuth = azimuth; + s->u.orientation.pitch = pitch; + s->u.orientation.roll = roll; +} + +/* change the emulated temperature */ +static void +_hwSensors_setTemperature( HwSensors* h, float celsius ) +{ + Sensor* s = &h->sensors[ANDROID_SENSOR_TEMPERATURE]; + s->u.temperature.celsius = celsius; +} +#endif + +/* change the coarse orientation (landscape/portrait) of the emulated device */ +static void +_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient ) +{ + /* The Android framework computes the orientation by looking at + * the accelerometer sensor (*not* the orientation sensor !) + * + * That's because the gravity is a constant 9.81 vector that + * can be determined quite easily. + * + * Also, for some reason, the framework code considers that the phone should + * be inclined by 30 degrees along the phone's X axis to be considered + * in its ideal "vertical" position + * + * If the phone is completely vertical, rotating it will not do anything ! + */ + const double g = 9.81; + const double cos_30 = 0.866025403784; + const double sin_30 = 0.5; + + switch (orient) { + case ANDROID_COARSE_PORTRAIT: + _hwSensors_setAcceleration( h, 0., g*cos_30, g*sin_30 ); + break; + + case ANDROID_COARSE_LANDSCAPE: + _hwSensors_setAcceleration( h, g*cos_30, 0., g*sin_30 ); + break; + default: + ; + } +} + + +/* initialize the sensors state */ +static void +_hwSensors_init( HwSensors* h ) +{ + h->service = qemud_service_register("sensors", 0, h, + _hwSensors_connect ); + + if (android_hw->hw_accelerometer) + h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1; + + /* XXX: TODO: Add other tests when we add the corresponding + * properties to hardware-properties.ini et al. */ + + _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT); +} + static HwSensors _sensorsState[1]; void @@ -436,7 +521,7 @@ android_hw_sensors_init( void ) HwSensors* hw = _sensorsState; if (hw->service == NULL) { - hw_sensors_init(hw); + _hwSensors_init(hw); D("%s: sensors qemud service initialized", __FUNCTION__); } } @@ -446,6 +531,6 @@ extern void android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient ) { android_hw_sensors_init(); - hw_sensors_set_coarse_orientation(_sensorsState, orient); + _hwSensors_setCoarseOrientation(_sensorsState, orient); } |