diff options
author | David 'Digit' Turner <digit@android.com> | 2011-04-07 10:16:15 +0200 |
---|---|---|
committer | David 'Digit' Turner <digit@android.com> | 2011-04-07 10:16:15 +0200 |
commit | 183675b74e5a58211e5d9a90a9ca86546ed3e245 (patch) | |
tree | 9f8204145a800972905450f06fe57c7a177c3b3c /emulator | |
parent | 6288bf53f8f21fb0c4cef51cbb3d5135b879f820 (diff) | |
download | sdk-183675b74e5a58211e5d9a90a9ca86546ed3e245.zip sdk-183675b74e5a58211e5d9a90a9ca86546ed3e245.tar.gz sdk-183675b74e5a58211e5d9a90a9ca86546ed3e245.tar.bz2 |
Remove obsolete emulator modules
The corresponding modules have all been moved to development/tools/emulator/system/
already. Note that we use a global variable Make trick to prevent the same module
from being built twice, so removing these files doesn't break the builds.
Another patch should remove the global variable Make trick from
development/tools/emulator/system after this patch.
Change-Id: I547d2a0173ddf58c1870784920ce795f6a0d7bcf
Diffstat (limited to 'emulator')
-rw-r--r-- | emulator/gps/Android.mk | 39 | ||||
-rw-r--r-- | emulator/gps/gps_qemu.c | 941 | ||||
-rw-r--r-- | emulator/qemud/Android.mk | 25 | ||||
-rw-r--r-- | emulator/qemud/qemud.c | 1719 | ||||
-rw-r--r-- | emulator/sensors/Android.mk | 38 | ||||
-rw-r--r-- | emulator/sensors/sensors_qemu.c | 637 | ||||
-rw-r--r-- | emulator/tools/Android.mk | 44 | ||||
-rw-r--r-- | emulator/tools/qemu-props.c | 116 |
8 files changed, 0 insertions, 3559 deletions
diff --git a/emulator/gps/Android.mk b/emulator/gps/Android.mk deleted file mode 100644 index 41bdc64..0000000 --- a/emulator/gps/Android.mk +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2010 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# We're moving the emulator-specific platform libs to -# development.git/tools/emulator/. The following test is to ensure -# smooth builds even if the tree contains both versions. -# -ifndef BUILD_EMULATOR_GPS_MODULE -BUILD_EMULATOR_GPS_MODULE := true - -LOCAL_PATH := $(call my-dir) - -ifneq ($(TARGET_PRODUCT),sim) -# HAL module implemenation, not prelinked and stored in -# hw/<GPS_HARDWARE_MODULE_ID>.<ro.hardware>.so -include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_CFLAGS += -DQEMU_HARDWARE -LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware -LOCAL_SRC_FILES := gps_qemu.c -LOCAL_MODULE := gps.goldfish -LOCAL_MODULE_TAGS := debug -include $(BUILD_SHARED_LIBRARY) -endif - -endif # BUILD_EMULATOR_GPS_MODULE diff --git a/emulator/gps/gps_qemu.c b/emulator/gps/gps_qemu.c deleted file mode 100644 index a4699d3..0000000 --- a/emulator/gps/gps_qemu.c +++ /dev/null @@ -1,941 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* this implements a GPS hardware library for the Android emulator. - * the following code should be built as a shared library that will be - * placed into /system/lib/hw/gps.goldfish.so - * - * it will be loaded by the code in hardware/libhardware/hardware.c - * which is itself called from android_location_GpsLocationProvider.cpp - */ - - -#include <errno.h> -#include <pthread.h> -#include <fcntl.h> -#include <sys/epoll.h> -#include <math.h> -#include <time.h> - -#define LOG_TAG "gps_qemu" -#include <cutils/log.h> -#include <cutils/sockets.h> -#include <hardware/gps.h> -#include <hardware/qemud.h> - -/* the name of the qemud-controlled socket */ -#define QEMU_CHANNEL_NAME "gps" - -#define GPS_DEBUG 0 - -#if GPS_DEBUG -# define D(...) LOGD(__VA_ARGS__) -#else -# define D(...) ((void)0) -#endif - -/*****************************************************************/ -/*****************************************************************/ -/***** *****/ -/***** N M E A T O K E N I Z E R *****/ -/***** *****/ -/*****************************************************************/ -/*****************************************************************/ - -typedef struct { - const char* p; - const char* end; -} Token; - -#define MAX_NMEA_TOKENS 16 - -typedef struct { - int count; - Token tokens[ MAX_NMEA_TOKENS ]; -} NmeaTokenizer; - -static int -nmea_tokenizer_init( NmeaTokenizer* t, const char* p, const char* end ) -{ - int count = 0; - char* q; - - // the initial '$' is optional - if (p < end && p[0] == '$') - p += 1; - - // remove trailing newline - if (end > p && end[-1] == '\n') { - end -= 1; - if (end > p && end[-1] == '\r') - end -= 1; - } - - // get rid of checksum at the end of the sentecne - if (end >= p+3 && end[-3] == '*') { - end -= 3; - } - - while (p < end) { - const char* q = p; - - q = memchr(p, ',', end-p); - if (q == NULL) - q = end; - - if (q > p) { - if (count < MAX_NMEA_TOKENS) { - t->tokens[count].p = p; - t->tokens[count].end = q; - count += 1; - } - } - if (q < end) - q += 1; - - p = q; - } - - t->count = count; - return count; -} - -static Token -nmea_tokenizer_get( NmeaTokenizer* t, int index ) -{ - Token tok; - static const char* dummy = ""; - - if (index < 0 || index >= t->count) { - tok.p = tok.end = dummy; - } else - tok = t->tokens[index]; - - return tok; -} - - -static int -str2int( const char* p, const char* end ) -{ - int result = 0; - int len = end - p; - - for ( ; len > 0; len--, p++ ) - { - int c; - - if (p >= end) - goto Fail; - - c = *p - '0'; - if ((unsigned)c >= 10) - goto Fail; - - result = result*10 + c; - } - return result; - -Fail: - return -1; -} - -static double -str2float( const char* p, const char* end ) -{ - int result = 0; - int len = end - p; - char temp[16]; - - if (len >= (int)sizeof(temp)) - return 0.; - - memcpy( temp, p, len ); - temp[len] = 0; - return strtod( temp, NULL ); -} - -/*****************************************************************/ -/*****************************************************************/ -/***** *****/ -/***** N M E A P A R S E R *****/ -/***** *****/ -/*****************************************************************/ -/*****************************************************************/ - -#define NMEA_MAX_SIZE 83 - -typedef struct { - int pos; - int overflow; - int utc_year; - int utc_mon; - int utc_day; - int utc_diff; - GpsLocation fix; - gps_location_callback callback; - char in[ NMEA_MAX_SIZE+1 ]; -} NmeaReader; - - -static void -nmea_reader_update_utc_diff( NmeaReader* r ) -{ - time_t now = time(NULL); - struct tm tm_local; - struct tm tm_utc; - long time_local, time_utc; - - gmtime_r( &now, &tm_utc ); - localtime_r( &now, &tm_local ); - - time_local = tm_local.tm_sec + - 60*(tm_local.tm_min + - 60*(tm_local.tm_hour + - 24*(tm_local.tm_yday + - 365*tm_local.tm_year))); - - time_utc = tm_utc.tm_sec + - 60*(tm_utc.tm_min + - 60*(tm_utc.tm_hour + - 24*(tm_utc.tm_yday + - 365*tm_utc.tm_year))); - - r->utc_diff = time_utc - time_local; -} - - -static void -nmea_reader_init( NmeaReader* r ) -{ - memset( r, 0, sizeof(*r) ); - - r->pos = 0; - r->overflow = 0; - r->utc_year = -1; - r->utc_mon = -1; - r->utc_day = -1; - r->callback = NULL; - r->fix.size = sizeof(r->fix); - - nmea_reader_update_utc_diff( r ); -} - - -static void -nmea_reader_set_callback( NmeaReader* r, gps_location_callback cb ) -{ - r->callback = cb; - if (cb != NULL && r->fix.flags != 0) { - D("%s: sending latest fix to new callback", __FUNCTION__); - r->callback( &r->fix ); - r->fix.flags = 0; - } -} - - -static int -nmea_reader_update_time( NmeaReader* r, Token tok ) -{ - int hour, minute; - double seconds; - struct tm tm; - time_t fix_time; - - if (tok.p + 6 > tok.end) - return -1; - - if (r->utc_year < 0) { - // no date yet, get current one - time_t now = time(NULL); - gmtime_r( &now, &tm ); - r->utc_year = tm.tm_year + 1900; - r->utc_mon = tm.tm_mon + 1; - r->utc_day = tm.tm_mday; - } - - hour = str2int(tok.p, tok.p+2); - minute = str2int(tok.p+2, tok.p+4); - seconds = str2float(tok.p+4, tok.end); - - tm.tm_hour = hour; - tm.tm_min = minute; - tm.tm_sec = (int) seconds; - tm.tm_year = r->utc_year - 1900; - tm.tm_mon = r->utc_mon - 1; - tm.tm_mday = r->utc_day; - tm.tm_isdst = -1; - - fix_time = mktime( &tm ) + r->utc_diff; - r->fix.timestamp = (long long)fix_time * 1000; - return 0; -} - -static int -nmea_reader_update_date( NmeaReader* r, Token date, Token time ) -{ - Token tok = date; - int day, mon, year; - - if (tok.p + 6 != tok.end) { - D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p); - return -1; - } - day = str2int(tok.p, tok.p+2); - mon = str2int(tok.p+2, tok.p+4); - year = str2int(tok.p+4, tok.p+6) + 2000; - - if ((day|mon|year) < 0) { - D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p); - return -1; - } - - r->utc_year = year; - r->utc_mon = mon; - r->utc_day = day; - - return nmea_reader_update_time( r, time ); -} - - -static double -convert_from_hhmm( Token tok ) -{ - double val = str2float(tok.p, tok.end); - int degrees = (int)(floor(val) / 100); - double minutes = val - degrees*100.; - double dcoord = degrees + minutes / 60.0; - return dcoord; -} - - -static int -nmea_reader_update_latlong( NmeaReader* r, - Token latitude, - char latitudeHemi, - Token longitude, - char longitudeHemi ) -{ - double lat, lon; - Token tok; - - tok = latitude; - if (tok.p + 6 > tok.end) { - D("latitude is too short: '%.*s'", tok.end-tok.p, tok.p); - return -1; - } - lat = convert_from_hhmm(tok); - if (latitudeHemi == 'S') - lat = -lat; - - tok = longitude; - if (tok.p + 6 > tok.end) { - D("longitude is too short: '%.*s'", tok.end-tok.p, tok.p); - return -1; - } - lon = convert_from_hhmm(tok); - if (longitudeHemi == 'W') - lon = -lon; - - r->fix.flags |= GPS_LOCATION_HAS_LAT_LONG; - r->fix.latitude = lat; - r->fix.longitude = lon; - return 0; -} - - -static int -nmea_reader_update_altitude( NmeaReader* r, - Token altitude, - Token units ) -{ - double alt; - Token tok = altitude; - - if (tok.p >= tok.end) - return -1; - - r->fix.flags |= GPS_LOCATION_HAS_ALTITUDE; - r->fix.altitude = str2float(tok.p, tok.end); - return 0; -} - - -static int -nmea_reader_update_bearing( NmeaReader* r, - Token bearing ) -{ - double alt; - Token tok = bearing; - - if (tok.p >= tok.end) - return -1; - - r->fix.flags |= GPS_LOCATION_HAS_BEARING; - r->fix.bearing = str2float(tok.p, tok.end); - return 0; -} - - -static int -nmea_reader_update_speed( NmeaReader* r, - Token speed ) -{ - double alt; - Token tok = speed; - - if (tok.p >= tok.end) - return -1; - - r->fix.flags |= GPS_LOCATION_HAS_SPEED; - r->fix.speed = str2float(tok.p, tok.end); - return 0; -} - - -static void -nmea_reader_parse( NmeaReader* r ) -{ - /* we received a complete sentence, now parse it to generate - * a new GPS fix... - */ - NmeaTokenizer tzer[1]; - Token tok; - - D("Received: '%.*s'", r->pos, r->in); - if (r->pos < 9) { - D("Too short. discarded."); - return; - } - - nmea_tokenizer_init(tzer, r->in, r->in + r->pos); -#if GPS_DEBUG - { - int n; - D("Found %d tokens", tzer->count); - for (n = 0; n < tzer->count; n++) { - Token tok = nmea_tokenizer_get(tzer,n); - D("%2d: '%.*s'", n, tok.end-tok.p, tok.p); - } - } -#endif - - tok = nmea_tokenizer_get(tzer, 0); - if (tok.p + 5 > tok.end) { - D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p); - return; - } - - // ignore first two characters. - tok.p += 2; - if ( !memcmp(tok.p, "GGA", 3) ) { - // GPS fix - Token tok_time = nmea_tokenizer_get(tzer,1); - Token tok_latitude = nmea_tokenizer_get(tzer,2); - Token tok_latitudeHemi = nmea_tokenizer_get(tzer,3); - Token tok_longitude = nmea_tokenizer_get(tzer,4); - Token tok_longitudeHemi = nmea_tokenizer_get(tzer,5); - Token tok_altitude = nmea_tokenizer_get(tzer,9); - Token tok_altitudeUnits = nmea_tokenizer_get(tzer,10); - - nmea_reader_update_time(r, tok_time); - nmea_reader_update_latlong(r, tok_latitude, - tok_latitudeHemi.p[0], - tok_longitude, - tok_longitudeHemi.p[0]); - nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits); - - } else if ( !memcmp(tok.p, "GSA", 3) ) { - // do something ? - } else if ( !memcmp(tok.p, "RMC", 3) ) { - Token tok_time = nmea_tokenizer_get(tzer,1); - Token tok_fixStatus = nmea_tokenizer_get(tzer,2); - Token tok_latitude = nmea_tokenizer_get(tzer,3); - Token tok_latitudeHemi = nmea_tokenizer_get(tzer,4); - Token tok_longitude = nmea_tokenizer_get(tzer,5); - Token tok_longitudeHemi = nmea_tokenizer_get(tzer,6); - Token tok_speed = nmea_tokenizer_get(tzer,7); - Token tok_bearing = nmea_tokenizer_get(tzer,8); - Token tok_date = nmea_tokenizer_get(tzer,9); - - D("in RMC, fixStatus=%c", tok_fixStatus.p[0]); - if (tok_fixStatus.p[0] == 'A') - { - nmea_reader_update_date( r, tok_date, tok_time ); - - nmea_reader_update_latlong( r, tok_latitude, - tok_latitudeHemi.p[0], - tok_longitude, - tok_longitudeHemi.p[0] ); - - nmea_reader_update_bearing( r, tok_bearing ); - nmea_reader_update_speed ( r, tok_speed ); - } - } else { - tok.p -= 2; - D("unknown sentence '%.*s", tok.end-tok.p, tok.p); - } - if (r->fix.flags != 0) { -#if GPS_DEBUG - char temp[256]; - char* p = temp; - char* end = p + sizeof(temp); - struct tm utc; - - p += snprintf( p, end-p, "sending fix" ); - if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) { - p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude); - } - if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) { - p += snprintf(p, end-p, " altitude=%g", r->fix.altitude); - } - if (r->fix.flags & GPS_LOCATION_HAS_SPEED) { - p += snprintf(p, end-p, " speed=%g", r->fix.speed); - } - if (r->fix.flags & GPS_LOCATION_HAS_BEARING) { - p += snprintf(p, end-p, " bearing=%g", r->fix.bearing); - } - if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) { - p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy); - } - gmtime_r( (time_t*) &r->fix.timestamp, &utc ); - p += snprintf(p, end-p, " time=%s", asctime( &utc ) ); - D(temp); -#endif - if (r->callback) { - r->callback( &r->fix ); - r->fix.flags = 0; - } - else { - D("no callback, keeping data until needed !"); - } - } -} - - -static void -nmea_reader_addc( NmeaReader* r, int c ) -{ - if (r->overflow) { - r->overflow = (c != '\n'); - return; - } - - if (r->pos >= (int) sizeof(r->in)-1 ) { - r->overflow = 1; - r->pos = 0; - return; - } - - r->in[r->pos] = (char)c; - r->pos += 1; - - if (c == '\n') { - nmea_reader_parse( r ); - r->pos = 0; - } -} - - -/*****************************************************************/ -/*****************************************************************/ -/***** *****/ -/***** C O N N E C T I O N S T A T E *****/ -/***** *****/ -/*****************************************************************/ -/*****************************************************************/ - -/* commands sent to the gps thread */ -enum { - CMD_QUIT = 0, - CMD_START = 1, - CMD_STOP = 2 -}; - - -/* this is the state of our connection to the qemu_gpsd daemon */ -typedef struct { - int init; - int fd; - GpsCallbacks callbacks; - pthread_t thread; - int control[2]; -} GpsState; - -static GpsState _gps_state[1]; - - -static void -gps_state_done( GpsState* s ) -{ - // tell the thread to quit, and wait for it - char cmd = CMD_QUIT; - void* dummy; - write( s->control[0], &cmd, 1 ); - pthread_join(s->thread, &dummy); - - // close the control socket pair - close( s->control[0] ); s->control[0] = -1; - close( s->control[1] ); s->control[1] = -1; - - // close connection to the QEMU GPS daemon - close( s->fd ); s->fd = -1; - s->init = 0; -} - - -static void -gps_state_start( GpsState* s ) -{ - char cmd = CMD_START; - int ret; - - do { ret=write( s->control[0], &cmd, 1 ); } - while (ret < 0 && errno == EINTR); - - if (ret != 1) - D("%s: could not send CMD_START command: ret=%d: %s", - __FUNCTION__, ret, strerror(errno)); -} - - -static void -gps_state_stop( GpsState* s ) -{ - char cmd = CMD_STOP; - int ret; - - do { ret=write( s->control[0], &cmd, 1 ); } - while (ret < 0 && errno == EINTR); - - if (ret != 1) - D("%s: could not send CMD_STOP command: ret=%d: %s", - __FUNCTION__, ret, strerror(errno)); -} - - -static int -epoll_register( int epoll_fd, int fd ) -{ - struct epoll_event ev; - int ret, flags; - - /* important: make the fd non-blocking */ - flags = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - ev.events = EPOLLIN; - ev.data.fd = fd; - do { - ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev ); - } while (ret < 0 && errno == EINTR); - return ret; -} - - -static int -epoll_deregister( int epoll_fd, int fd ) -{ - int ret; - do { - ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL ); - } while (ret < 0 && errno == EINTR); - return ret; -} - -/* this is the main thread, it waits for commands from gps_state_start/stop and, - * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences - * that must be parsed to be converted into GPS fixes sent to the framework - */ -static void -gps_state_thread( void* arg ) -{ - GpsState* state = (GpsState*) arg; - NmeaReader reader[1]; - int epoll_fd = epoll_create(2); - int started = 0; - int gps_fd = state->fd; - int control_fd = state->control[1]; - - nmea_reader_init( reader ); - - // register control file descriptors for polling - epoll_register( epoll_fd, control_fd ); - epoll_register( epoll_fd, gps_fd ); - - D("gps thread running"); - - // now loop - for (;;) { - struct epoll_event events[2]; - int ne, nevents; - - nevents = epoll_wait( epoll_fd, events, 2, -1 ); - if (nevents < 0) { - if (errno != EINTR) - LOGE("epoll_wait() unexpected error: %s", strerror(errno)); - continue; - } - D("gps thread received %d events", nevents); - for (ne = 0; ne < nevents; ne++) { - if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) { - LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?"); - return; - } - if ((events[ne].events & EPOLLIN) != 0) { - int fd = events[ne].data.fd; - - if (fd == control_fd) - { - char cmd = 255; - int ret; - D("gps control fd event"); - do { - ret = read( fd, &cmd, 1 ); - } while (ret < 0 && errno == EINTR); - - if (cmd == CMD_QUIT) { - D("gps thread quitting on demand"); - return; - } - else if (cmd == CMD_START) { - if (!started) { - D("gps thread starting location_cb=%p", state->callbacks.location_cb); - started = 1; - nmea_reader_set_callback( reader, state->callbacks.location_cb ); - } - } - else if (cmd == CMD_STOP) { - if (started) { - D("gps thread stopping"); - started = 0; - nmea_reader_set_callback( reader, NULL ); - } - } - } - else if (fd == gps_fd) - { - char buff[32]; - D("gps fd event"); - for (;;) { - int nn, ret; - - ret = read( fd, buff, sizeof(buff) ); - if (ret < 0) { - if (errno == EINTR) - continue; - if (errno != EWOULDBLOCK) - LOGE("error while reading from gps daemon socket: %s:", strerror(errno)); - break; - } - D("received %d bytes: %.*s", ret, ret, buff); - for (nn = 0; nn < ret; nn++) - nmea_reader_addc( reader, buff[nn] ); - } - D("gps fd event end"); - } - else - { - LOGE("epoll_wait() returned unkown fd %d ?", fd); - } - } - } - } -} - - -static void -gps_state_init( GpsState* state, GpsCallbacks* callbacks ) -{ - state->init = 1; - state->control[0] = -1; - state->control[1] = -1; - state->fd = -1; - - state->fd = qemud_channel_open(QEMU_CHANNEL_NAME); - - if (state->fd < 0) { - D("no gps emulation detected"); - return; - } - - D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME ); - - if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) { - LOGE("could not create thread control socket pair: %s", strerror(errno)); - goto Fail; - } - - state->thread = callbacks->create_thread_cb( "gps_state_thread", gps_state_thread, state ); - - if ( !state->thread ) { - LOGE("could not create gps thread: %s", strerror(errno)); - goto Fail; - } - - state->callbacks = *callbacks; - - D("gps state initialized"); - return; - -Fail: - gps_state_done( state ); -} - - -/*****************************************************************/ -/*****************************************************************/ -/***** *****/ -/***** I N T E R F A C E *****/ -/***** *****/ -/*****************************************************************/ -/*****************************************************************/ - - -static int -qemu_gps_init(GpsCallbacks* callbacks) -{ - GpsState* s = _gps_state; - - if (!s->init) - gps_state_init(s, callbacks); - - if (s->fd < 0) - return -1; - - return 0; -} - -static void -qemu_gps_cleanup(void) -{ - GpsState* s = _gps_state; - - if (s->init) - gps_state_done(s); -} - - -static int -qemu_gps_start() -{ - GpsState* s = _gps_state; - - if (!s->init) { - D("%s: called with uninitialized state !!", __FUNCTION__); - return -1; - } - - D("%s: called", __FUNCTION__); - gps_state_start(s); - return 0; -} - - -static int -qemu_gps_stop() -{ - GpsState* s = _gps_state; - - if (!s->init) { - D("%s: called with uninitialized state !!", __FUNCTION__); - return -1; - } - - D("%s: called", __FUNCTION__); - gps_state_stop(s); - return 0; -} - - -static int -qemu_gps_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty) -{ - return 0; -} - -static int -qemu_gps_inject_location(double latitude, double longitude, float accuracy) -{ - return 0; -} - -static void -qemu_gps_delete_aiding_data(GpsAidingData flags) -{ -} - -static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency) -{ - // FIXME - support fix_frequency - return 0; -} - -static const void* -qemu_gps_get_extension(const char* name) -{ - // no extensions supported - return NULL; -} - -static const GpsInterface qemuGpsInterface = { - sizeof(GpsInterface), - qemu_gps_init, - qemu_gps_start, - qemu_gps_stop, - qemu_gps_cleanup, - qemu_gps_inject_time, - qemu_gps_inject_location, - qemu_gps_delete_aiding_data, - qemu_gps_set_position_mode, - qemu_gps_get_extension, -}; - -const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev) -{ - return &qemuGpsInterface; -} - -static int open_gps(const struct hw_module_t* module, char const* name, - struct hw_device_t** device) -{ - struct gps_device_t *dev = malloc(sizeof(struct gps_device_t)); - memset(dev, 0, sizeof(*dev)); - - dev->common.tag = HARDWARE_DEVICE_TAG; - dev->common.version = 0; - dev->common.module = (struct hw_module_t*)module; -// dev->common.close = (int (*)(struct hw_device_t*))close_lights; - dev->get_gps_interface = gps__get_gps_interface; - - *device = (struct hw_device_t*)dev; - return 0; -} - - -static struct hw_module_methods_t gps_module_methods = { - .open = open_gps -}; - -const struct hw_module_t HAL_MODULE_INFO_SYM = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = GPS_HARDWARE_MODULE_ID, - .name = "Goldfish GPS Module", - .author = "The Android Open Source Project", - .methods = &gps_module_methods, -}; diff --git a/emulator/qemud/Android.mk b/emulator/qemud/Android.mk deleted file mode 100644 index 5666a74..0000000 --- a/emulator/qemud/Android.mk +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2008 The Android Open Source Project - -# We're moving the emulator-specific platform libs to -# development.git/tools/emulator/. The following test is to ensure -# smooth builds even if the tree contains both versions. -# -ifndef BUILD_EMULATOR_QEMUD -BUILD_EMULATOR_QEMUD := true - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_SRC_FILES:= \ - qemud.c - - -LOCAL_SHARED_LIBRARIES := \ - libcutils \ - -LOCAL_MODULE:= qemud -LOCAL_MODULE_TAGS := debug - -include $(BUILD_EXECUTABLE) - -endif # BUILD_EMULATOR_QEMUD
\ No newline at end of file diff --git a/emulator/qemud/qemud.c b/emulator/qemud/qemud.c deleted file mode 100644 index e1c7b54..0000000 --- a/emulator/qemud/qemud.c +++ /dev/null @@ -1,1719 +0,0 @@ -#include <stdint.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> -#include <termios.h> -#include <cutils/sockets.h> - -/* - * the qemud daemon program is only used within Android as a bridge - * between the emulator program and the emulated system. it really works as - * a simple stream multiplexer that works as follows: - * - * - qemud is started by init following instructions in - * /system/etc/init.goldfish.rc (i.e. it is never started on real devices) - * - * - qemud communicates with the emulator program through a single serial - * port, whose name is passed through a kernel boot parameter - * (e.g. android.qemud=ttyS1) - * - * - qemud binds one unix local stream socket (/dev/socket/qemud, created - * by init through /system/etc/init.goldfish.rc). - * - * - * emulator <==serial==> qemud <---> /dev/socket/qemud <-+--> client1 - * | - * +--> client2 - * - * - the special channel index 0 is used by the emulator and qemud only. - * other channel numbers correspond to clients. More specifically, - * connection are created like this: - * - * * the client connects to /dev/socket/qemud - * - * * the client sends the service name through the socket, as - * <service-name> - * - * * qemud creates a "Client" object internally, assigns it an - * internal unique channel number > 0, then sends a connection - * initiation request to the emulator (i.e. through channel 0): - * - * connect:<id>:<name> - * - * where <name> is the service name, and <id> is a 2-hexchar - * number corresponding to the channel number. - * - * * in case of success, the emulator responds through channel 0 - * with: - * - * ok:connect:<id> - * - * after this, all messages between the client and the emulator - * are passed in pass-through mode. - * - * * if the emulator refuses the service connection, it will - * send the following through channel 0: - * - * ko:connect:<id>:reason-for-failure - * - * * If the client closes the connection, qemud sends the following - * to the emulator: - * - * disconnect:<id> - * - * The same message is the opposite direction if the emulator - * chooses to close the connection. - * - * * any command sent through channel 0 to the emulator that is - * not properly recognized will be answered by: - * - * ko:unknown command - * - * - * Internally, the daemon maintains a "Client" object for each client - * connection (i.e. accepting socket connection). - */ - -/* name of the single control socket used by the daemon */ -#define CONTROL_SOCKET_NAME "qemud" - -#define DEBUG 1 -#define T_ACTIVE 0 /* set to 1 to dump traffic */ - -#if DEBUG -# define LOG_TAG "qemud" -# include <cutils/log.h> -# define D(...) LOGD(__VA_ARGS__) -#else -# define D(...) ((void)0) -# define T(...) ((void)0) -#endif - -#if T_ACTIVE -# define T(...) D(__VA_ARGS__) -#else -# define T(...) ((void)0) -#endif - -/** UTILITIES - **/ - -static void -fatal( const char* fmt, ... ) -{ - va_list args; - va_start(args, fmt); - fprintf(stderr, "PANIC: "); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n" ); - va_end(args); - exit(1); -} - -static void* -xalloc( size_t sz ) -{ - void* p; - - if (sz == 0) - return NULL; - - p = malloc(sz); - if (p == NULL) - fatal( "not enough memory" ); - - return p; -} - -#define xnew(p) (p) = xalloc(sizeof(*(p))) - -static void* -xalloc0( size_t sz ) -{ - void* p = xalloc(sz); - memset( p, 0, sz ); - return p; -} - -#define xnew0(p) (p) = xalloc0(sizeof(*(p))) - -#define xfree(p) (free((p)), (p) = NULL) - -static void* -xrealloc( void* block, size_t size ) -{ - void* p = realloc( block, size ); - - if (p == NULL && size > 0) - fatal( "not enough memory" ); - - return p; -} - -#define xrenew(p,count) (p) = xrealloc((p),sizeof(*(p))*(count)) - -static int -hex2int( const uint8_t* data, int len ) -{ - int result = 0; - while (len > 0) { - int c = *data++; - unsigned d; - - result <<= 4; - do { - d = (unsigned)(c - '0'); - if (d < 10) - break; - - d = (unsigned)(c - 'a'); - if (d < 6) { - d += 10; - break; - } - - d = (unsigned)(c - 'A'); - if (d < 6) { - d += 10; - break; - } - - return -1; - } - while (0); - - result |= d; - len -= 1; - } - return result; -} - - -static void -int2hex( int value, uint8_t* to, int width ) -{ - int nn = 0; - static const char hexchars[16] = "0123456789abcdef"; - - for ( --width; width >= 0; width--, nn++ ) { - to[nn] = hexchars[(value >> (width*4)) & 15]; - } -} - -static int -fd_read(int fd, void* to, int len) -{ - int ret; - - do { - ret = read(fd, to, len); - } while (ret < 0 && errno == EINTR); - - return ret; -} - -static int -fd_write(int fd, const void* from, int len) -{ - int ret; - - do { - ret = write(fd, from, len); - } while (ret < 0 && errno == EINTR); - - return ret; -} - -static void -fd_setnonblock(int fd) -{ - int ret, flags; - - do { - flags = fcntl(fd, F_GETFD); - } while (flags < 0 && errno == EINTR); - - if (flags < 0) { - fatal( "%s: could not get flags for fd %d: %s", - __FUNCTION__, fd, strerror(errno) ); - } - - do { - ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK); - } while (ret < 0 && errno == EINTR); - - if (ret < 0) { - fatal( "%s: could not set fd %d to non-blocking: %s", - __FUNCTION__, fd, strerror(errno) ); - } -} - - -static int -fd_accept(int fd) -{ - struct sockaddr from; - socklen_t fromlen = sizeof(from); - int ret; - - do { - ret = accept(fd, &from, &fromlen); - } while (ret < 0 && errno == EINTR); - - return ret; -} - -/** FD EVENT LOOP - **/ - -/* A Looper object is used to monitor activity on one or more - * file descriptors (e.g sockets). - * - * - call looper_add() to register a function that will be - * called when events happen on the file descriptor. - * - * - call looper_enable() or looper_disable() to enable/disable - * the set of monitored events for a given file descriptor. - * - * - call looper_del() to unregister a file descriptor. - * this does *not* close the file descriptor. - * - * Note that you can only provide a single function to handle - * all events related to a given file descriptor. - - * You can call looper_enable/_disable/_del within a function - * callback. - */ - -/* the current implementation uses Linux's epoll facility - * the event mask we use are simply combinations of EPOLLIN - * EPOLLOUT, EPOLLHUP and EPOLLERR - */ -#include <sys/epoll.h> - -#define MAX_CHANNELS 16 -#define MAX_EVENTS (MAX_CHANNELS+1) /* each channel + the serial fd */ - -/* the event handler function type, 'user' is a user-specific - * opaque pointer passed to looper_add(). - */ -typedef void (*EventFunc)( void* user, int events ); - -/* bit flags for the LoopHook structure. - * - * HOOK_PENDING means that an event happened on the - * corresponding file descriptor. - * - * HOOK_CLOSING is used to delay-close monitored - * file descriptors. - */ -enum { - HOOK_PENDING = (1 << 0), - HOOK_CLOSING = (1 << 1), -}; - -/* A LoopHook structure is used to monitor a given - * file descriptor and record its event handler. - */ -typedef struct { - int fd; - int wanted; /* events we are monitoring */ - int events; /* events that occured */ - int state; /* see HOOK_XXX constants */ - void* ev_user; /* user-provided handler parameter */ - EventFunc ev_func; /* event handler callback */ -} LoopHook; - -/* Looper is the main object modeling a looper object - */ -typedef struct { - int epoll_fd; - int num_fds; - int max_fds; - struct epoll_event* events; - LoopHook* hooks; -} Looper; - -/* initialize a looper object */ -static void -looper_init( Looper* l ) -{ - l->epoll_fd = epoll_create(4); - l->num_fds = 0; - l->max_fds = 0; - l->events = NULL; - l->hooks = NULL; -} - -/* finalize a looper object */ -static void -looper_done( Looper* l ) -{ - xfree(l->events); - xfree(l->hooks); - l->max_fds = 0; - l->num_fds = 0; - - close(l->epoll_fd); - l->epoll_fd = -1; -} - -/* return the LoopHook corresponding to a given - * monitored file descriptor, or NULL if not found - */ -static LoopHook* -looper_find( Looper* l, int fd ) -{ - LoopHook* hook = l->hooks; - LoopHook* end = hook + l->num_fds; - - for ( ; hook < end; hook++ ) { - if (hook->fd == fd) - return hook; - } - return NULL; -} - -/* grow the arrays in the looper object */ -static void -looper_grow( Looper* l ) -{ - int old_max = l->max_fds; - int new_max = old_max + (old_max >> 1) + 4; - int n; - - xrenew( l->events, new_max ); - xrenew( l->hooks, new_max ); - l->max_fds = new_max; - - /* now change the handles to all events */ - for (n = 0; n < l->num_fds; n++) { - struct epoll_event ev; - LoopHook* hook = l->hooks + n; - - ev.events = hook->wanted; - ev.data.ptr = hook; - epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, hook->fd, &ev ); - } -} - -/* register a file descriptor and its event handler. - * no event mask will be enabled - */ -static void -looper_add( Looper* l, int fd, EventFunc func, void* user ) -{ - struct epoll_event ev; - LoopHook* hook; - - if (l->num_fds >= l->max_fds) - looper_grow(l); - - hook = l->hooks + l->num_fds; - - hook->fd = fd; - hook->ev_user = user; - hook->ev_func = func; - hook->state = 0; - hook->wanted = 0; - hook->events = 0; - - fd_setnonblock(fd); - - ev.events = 0; - ev.data.ptr = hook; - epoll_ctl( l->epoll_fd, EPOLL_CTL_ADD, fd, &ev ); - - l->num_fds += 1; -} - -/* unregister a file descriptor and its event handler - */ -static void -looper_del( Looper* l, int fd ) -{ - LoopHook* hook = looper_find( l, fd ); - - if (!hook) { - D( "%s: invalid fd: %d", __FUNCTION__, fd ); - return; - } - /* don't remove the hook yet */ - hook->state |= HOOK_CLOSING; - - epoll_ctl( l->epoll_fd, EPOLL_CTL_DEL, fd, NULL ); -} - -/* enable monitoring of certain events for a file - * descriptor. This adds 'events' to the current - * event mask - */ -static void -looper_enable( Looper* l, int fd, int events ) -{ - LoopHook* hook = looper_find( l, fd ); - - if (!hook) { - D("%s: invalid fd: %d", __FUNCTION__, fd ); - return; - } - - if (events & ~hook->wanted) { - struct epoll_event ev; - - hook->wanted |= events; - ev.events = hook->wanted; - ev.data.ptr = hook; - - epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev ); - } -} - -/* disable monitoring of certain events for a file - * descriptor. This ignores events that are not - * currently enabled. - */ -static void -looper_disable( Looper* l, int fd, int events ) -{ - LoopHook* hook = looper_find( l, fd ); - - if (!hook) { - D("%s: invalid fd: %d", __FUNCTION__, fd ); - return; - } - - if (events & hook->wanted) { - struct epoll_event ev; - - hook->wanted &= ~events; - ev.events = hook->wanted; - ev.data.ptr = hook; - - epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, fd, &ev ); - } -} - -/* wait until an event occurs on one of the registered file - * descriptors. Only returns in case of error !! - */ -static void -looper_loop( Looper* l ) -{ - for (;;) { - int n, count; - - do { - count = epoll_wait( l->epoll_fd, l->events, l->num_fds, -1 ); - } while (count < 0 && errno == EINTR); - - if (count < 0) { - D("%s: error: %s", __FUNCTION__, strerror(errno) ); - return; - } - - if (count == 0) { - D("%s: huh ? epoll returned count=0", __FUNCTION__); - continue; - } - - /* mark all pending hooks */ - for (n = 0; n < count; n++) { - LoopHook* hook = l->events[n].data.ptr; - hook->state = HOOK_PENDING; - hook->events = l->events[n].events; - } - - /* execute hook callbacks. this may change the 'hooks' - * and 'events' array, as well as l->num_fds, so be careful */ - for (n = 0; n < l->num_fds; n++) { - LoopHook* hook = l->hooks + n; - if (hook->state & HOOK_PENDING) { - hook->state &= ~HOOK_PENDING; - hook->ev_func( hook->ev_user, hook->events ); - } - } - - /* now remove all the hooks that were closed by - * the callbacks */ - for (n = 0; n < l->num_fds;) { - struct epoll_event ev; - LoopHook* hook = l->hooks + n; - - if (!(hook->state & HOOK_CLOSING)) { - n++; - continue; - } - - hook[0] = l->hooks[l->num_fds-1]; - l->num_fds -= 1; - ev.events = hook->wanted; - ev.data.ptr = hook; - epoll_ctl( l->epoll_fd, EPOLL_CTL_MOD, hook->fd, &ev ); - } - } -} - -#if T_ACTIVE -char* -quote( const void* data, int len ) -{ - const char* p = data; - const char* end = p + len; - int count = 0; - int phase = 0; - static char* buff = NULL; - - for (phase = 0; phase < 2; phase++) { - if (phase != 0) { - xfree(buff); - buff = xalloc(count+1); - } - count = 0; - for (p = data; p < end; p++) { - int c = *p; - - if (c == '\\') { - if (phase != 0) { - buff[count] = buff[count+1] = '\\'; - } - count += 2; - continue; - } - - if (c >= 32 && c < 127) { - if (phase != 0) - buff[count] = c; - count += 1; - continue; - } - - - if (c == '\t') { - if (phase != 0) { - memcpy(buff+count, "<TAB>", 5); - } - count += 5; - continue; - } - if (c == '\n') { - if (phase != 0) { - memcpy(buff+count, "<LN>", 4); - } - count += 4; - continue; - } - if (c == '\r') { - if (phase != 0) { - memcpy(buff+count, "<CR>", 4); - } - count += 4; - continue; - } - - if (phase != 0) { - buff[count+0] = '\\'; - buff[count+1] = 'x'; - buff[count+2] = "0123456789abcdef"[(c >> 4) & 15]; - buff[count+3] = "0123456789abcdef"[ (c) & 15]; - } - count += 4; - } - } - buff[count] = 0; - return buff; -} -#endif /* T_ACTIVE */ - -/** PACKETS - ** - ** We need a way to buffer data before it can be sent to the - ** corresponding file descriptor. We use linked list of Packet - ** objects to do this. - **/ - -typedef struct Packet Packet; - -#define MAX_PAYLOAD 4000 - -struct Packet { - Packet* next; - int len; - int channel; - uint8_t data[ MAX_PAYLOAD ]; -}; - -/* we expect to alloc/free a lot of packets during - * operations so use a single linked list of free packets - * to keep things speedy and simple. - */ -static Packet* _free_packets; - -/* Allocate a packet */ -static Packet* -packet_alloc(void) -{ - Packet* p = _free_packets; - if (p != NULL) { - _free_packets = p->next; - } else { - xnew(p); - } - p->next = NULL; - p->len = 0; - p->channel = -1; - return p; -} - -/* Release a packet. This takes the address of a packet - * pointer that will be set to NULL on exit (avoids - * referencing dangling pointers in case of bugs) - */ -static void -packet_free( Packet* *ppacket ) -{ - Packet* p = *ppacket; - if (p) { - p->next = _free_packets; - _free_packets = p; - *ppacket = NULL; - } -} - -/** PACKET RECEIVER - ** - ** Simple abstraction for something that can receive a packet - ** from a FDHandler (see below) or something else. - ** - ** Send a packet to it with 'receiver_post' - ** - ** Call 'receiver_close' to indicate that the corresponding - ** packet source was closed. - **/ - -typedef void (*PostFunc) ( void* user, Packet* p ); -typedef void (*CloseFunc)( void* user ); - -typedef struct { - PostFunc post; - CloseFunc close; - void* user; -} Receiver; - -/* post a packet to a receiver. Note that this transfers - * ownership of the packet to the receiver. - */ -static __inline__ void -receiver_post( Receiver* r, Packet* p ) -{ - if (r->post) - r->post( r->user, p ); - else - packet_free(&p); -} - -/* tell a receiver the packet source was closed. - * this will also prevent further posting to the - * receiver. - */ -static __inline__ void -receiver_close( Receiver* r ) -{ - if (r->close) { - r->close( r->user ); - r->close = NULL; - } - r->post = NULL; -} - - -/** FD HANDLERS - ** - ** these are smart listeners that send incoming packets to a receiver - ** and can queue one or more outgoing packets and send them when - ** possible to the FD. - ** - ** note that we support clean shutdown of file descriptors, - ** i.e. we try to send all outgoing packets before destroying - ** the FDHandler. - **/ - -typedef struct FDHandler FDHandler; -typedef struct FDHandlerList FDHandlerList; - -struct FDHandler { - int fd; - FDHandlerList* list; - char closing; - Receiver receiver[1]; - - /* queue of outgoing packets */ - int out_pos; - Packet* out_first; - Packet** out_ptail; - - FDHandler* next; - FDHandler** pref; - -}; - -struct FDHandlerList { - /* the looper that manages the fds */ - Looper* looper; - - /* list of active FDHandler objects */ - FDHandler* active; - - /* list of closing FDHandler objects. - * these are waiting to push their - * queued packets to the fd before - * freeing themselves. - */ - FDHandler* closing; - -}; - -/* remove a FDHandler from its current list */ -static void -fdhandler_remove( FDHandler* f ) -{ - f->pref[0] = f->next; - if (f->next) - f->next->pref = f->pref; -} - -/* add a FDHandler to a given list */ -static void -fdhandler_prepend( FDHandler* f, FDHandler** list ) -{ - f->next = list[0]; - f->pref = list; - list[0] = f; - if (f->next) - f->next->pref = &f->next; -} - -/* initialize a FDHandler list */ -static void -fdhandler_list_init( FDHandlerList* list, Looper* looper ) -{ - list->looper = looper; - list->active = NULL; - list->closing = NULL; -} - - -/* close a FDHandler (and free it). Note that this will not - * perform a graceful shutdown, i.e. all packets in the - * outgoing queue will be immediately free. - * - * this *will* notify the receiver that the file descriptor - * was closed. - * - * you should call fdhandler_shutdown() if you want to - * notify the FDHandler that its packet source is closed. - */ -static void -fdhandler_close( FDHandler* f ) -{ - /* notify receiver */ - receiver_close(f->receiver); - - /* remove the handler from its list */ - fdhandler_remove(f); - - /* get rid of outgoing packet queue */ - if (f->out_first != NULL) { - Packet* p; - while ((p = f->out_first) != NULL) { - f->out_first = p->next; - packet_free(&p); - } - } - - /* get rid of file descriptor */ - if (f->fd >= 0) { - looper_del( f->list->looper, f->fd ); - close(f->fd); - f->fd = -1; - } - - f->list = NULL; - xfree(f); -} - -/* Ask the FDHandler to cleanly shutdown the connection, - * i.e. send any pending outgoing packets then auto-free - * itself. - */ -static void -fdhandler_shutdown( FDHandler* f ) -{ - /* prevent later fdhandler_close() to - * call the receiver's close. - */ - f->receiver->close = NULL; - - if (f->out_first != NULL && !f->closing) - { - /* move the handler to the 'closing' list */ - f->closing = 1; - fdhandler_remove(f); - fdhandler_prepend(f, &f->list->closing); - return; - } - - fdhandler_close(f); -} - -/* Enqueue a new packet that the FDHandler will - * send through its file descriptor. - */ -static void -fdhandler_enqueue( FDHandler* f, Packet* p ) -{ - Packet* first = f->out_first; - - p->next = NULL; - f->out_ptail[0] = p; - f->out_ptail = &p->next; - - if (first == NULL) { - f->out_pos = 0; - looper_enable( f->list->looper, f->fd, EPOLLOUT ); - } -} - - -/* FDHandler file descriptor event callback for read/write ops */ -static void -fdhandler_event( FDHandler* f, int events ) -{ - int len; - - /* in certain cases, it's possible to have both EPOLLIN and - * EPOLLHUP at the same time. This indicates that there is incoming - * data to read, but that the connection was nonetheless closed - * by the sender. Be sure to read the data before closing - * the receiver to avoid packet loss. - */ - - if (events & EPOLLIN) { - Packet* p = packet_alloc(); - int len; - - if ((len = fd_read(f->fd, p->data, MAX_PAYLOAD)) < 0) { - D("%s: can't recv: %s", __FUNCTION__, strerror(errno)); - packet_free(&p); - } else if (len > 0) { - p->len = len; - p->channel = -101; /* special debug value, not used */ - receiver_post( f->receiver, p ); - } - } - - if (events & (EPOLLHUP|EPOLLERR)) { - /* disconnection */ - D("%s: disconnect on fd %d", __FUNCTION__, f->fd); - fdhandler_close(f); - return; - } - - if (events & EPOLLOUT && f->out_first) { - Packet* p = f->out_first; - int avail, len; - - avail = p->len - f->out_pos; - if ((len = fd_write(f->fd, p->data + f->out_pos, avail)) < 0) { - D("%s: can't send: %s", __FUNCTION__, strerror(errno)); - } else { - f->out_pos += len; - if (f->out_pos >= p->len) { - f->out_pos = 0; - f->out_first = p->next; - packet_free(&p); - if (f->out_first == NULL) { - f->out_ptail = &f->out_first; - looper_disable( f->list->looper, f->fd, EPOLLOUT ); - } - } - } - } -} - - -/* Create a new FDHandler that monitors read/writes */ -static FDHandler* -fdhandler_new( int fd, - FDHandlerList* list, - Receiver* receiver ) -{ - FDHandler* f = xalloc0(sizeof(*f)); - - f->fd = fd; - f->list = list; - f->receiver[0] = receiver[0]; - f->out_first = NULL; - f->out_ptail = &f->out_first; - f->out_pos = 0; - - fdhandler_prepend(f, &list->active); - - looper_add( list->looper, fd, (EventFunc) fdhandler_event, f ); - looper_enable( list->looper, fd, EPOLLIN ); - - return f; -} - - -/* event callback function to monitor accepts() on server sockets. - * the convention used here is that the receiver will receive a - * dummy packet with the new client socket in p->channel - */ -static void -fdhandler_accept_event( FDHandler* f, int events ) -{ - if (events & EPOLLIN) { - /* this is an accept - send a dummy packet to the receiver */ - Packet* p = packet_alloc(); - - D("%s: accepting on fd %d", __FUNCTION__, f->fd); - p->data[0] = 1; - p->len = 1; - p->channel = fd_accept(f->fd); - if (p->channel < 0) { - D("%s: accept failed ?: %s", __FUNCTION__, strerror(errno)); - packet_free(&p); - return; - } - receiver_post( f->receiver, p ); - } - - if (events & (EPOLLHUP|EPOLLERR)) { - /* disconnecting !! */ - D("%s: closing accept fd %d", __FUNCTION__, f->fd); - fdhandler_close(f); - return; - } -} - - -/* Create a new FDHandler used to monitor new connections on a - * server socket. The receiver must expect the new connection - * fd in the 'channel' field of a dummy packet. - */ -static FDHandler* -fdhandler_new_accept( int fd, - FDHandlerList* list, - Receiver* receiver ) -{ - FDHandler* f = xalloc0(sizeof(*f)); - - f->fd = fd; - f->list = list; - f->receiver[0] = receiver[0]; - - fdhandler_prepend(f, &list->active); - - looper_add( list->looper, fd, (EventFunc) fdhandler_accept_event, f ); - looper_enable( list->looper, fd, EPOLLIN ); - listen( fd, 5 ); - - return f; -} - -/** SERIAL CONNECTION STATE - ** - ** The following is used to handle the framing protocol - ** used on the serial port connection. - **/ - -/* each packet is made of a 6 byte header followed by a payload - * the header looks like: - * - * offset size description - * 0 2 a 2-byte hex string for the channel number - * 4 4 a 4-char hex string for the size of the payload - * 6 n the payload itself - */ -#define HEADER_SIZE 6 -#define CHANNEL_OFFSET 0 -#define LENGTH_OFFSET 2 -#define CHANNEL_SIZE 2 -#define LENGTH_SIZE 4 - -#define CHANNEL_CONTROL 0 - -/* The Serial object receives data from the serial port, - * extracts the payload size and channel index, then sends - * the resulting messages as a packet to a generic receiver. - * - * You can also use serial_send to send a packet through - * the serial port. - */ -typedef struct Serial { - FDHandler* fdhandler; /* used to monitor serial port fd */ - Receiver receiver[1]; /* send payload there */ - int in_len; /* current bytes in input packet */ - int in_datalen; /* payload size, or 0 when reading header */ - int in_channel; /* extracted channel number */ - Packet* in_packet; /* used to read incoming packets */ -} Serial; - - -/* a callback called when the serial port's fd is closed */ -static void -serial_fd_close( Serial* s ) -{ - fatal("unexpected serial port close !!"); -} - -static void -serial_dump( Packet* p, const char* funcname ) -{ - T("%s: %03d bytes: '%s'", - funcname, p->len, quote(p->data, p->len)); -} - -/* a callback called when a packet arrives from the serial port's FDHandler. - * - * This will essentially parse the header, extract the channel number and - * the payload size and store them in 'in_datalen' and 'in_channel'. - * - * After that, the payload is sent to the receiver once completed. - */ -static void -serial_fd_receive( Serial* s, Packet* p ) -{ - int rpos = 0, rcount = p->len; - Packet* inp = s->in_packet; - int inpos = s->in_len; - - serial_dump( p, __FUNCTION__ ); - - while (rpos < rcount) - { - int avail = rcount - rpos; - - /* first, try to read the header */ - if (s->in_datalen == 0) { - int wanted = HEADER_SIZE - inpos; - if (avail > wanted) - avail = wanted; - - memcpy( inp->data + inpos, p->data + rpos, avail ); - inpos += avail; - rpos += avail; - - if (inpos == HEADER_SIZE) { - s->in_datalen = hex2int( inp->data + LENGTH_OFFSET, LENGTH_SIZE ); - s->in_channel = hex2int( inp->data + CHANNEL_OFFSET, CHANNEL_SIZE ); - - if (s->in_datalen <= 0) { - D("ignoring %s packet from serial port", - s->in_datalen ? "empty" : "malformed"); - s->in_datalen = 0; - } - - //D("received %d bytes packet for channel %d", s->in_datalen, s->in_channel); - inpos = 0; - } - } - else /* then, populate the packet itself */ - { - int wanted = s->in_datalen - inpos; - - if (avail > wanted) - avail = wanted; - - memcpy( inp->data + inpos, p->data + rpos, avail ); - inpos += avail; - rpos += avail; - - if (inpos == s->in_datalen) { - if (s->in_channel < 0) { - D("ignoring %d bytes addressed to channel %d", - inpos, s->in_channel); - } else { - inp->len = inpos; - inp->channel = s->in_channel; - receiver_post( s->receiver, inp ); - s->in_packet = inp = packet_alloc(); - } - s->in_datalen = 0; - inpos = 0; - } - } - } - s->in_len = inpos; - packet_free(&p); -} - - -/* send a packet to the serial port. - * this assumes that p->len and p->channel contain the payload's - * size and channel and will add the appropriate header. - */ -static void -serial_send( Serial* s, Packet* p ) -{ - Packet* h = packet_alloc(); - - //D("sending to serial %d bytes from channel %d: '%.*s'", p->len, p->channel, p->len, p->data); - - /* insert a small header before this packet */ - h->len = HEADER_SIZE; - int2hex( p->len, h->data + LENGTH_OFFSET, LENGTH_SIZE ); - int2hex( p->channel, h->data + CHANNEL_OFFSET, CHANNEL_SIZE ); - - serial_dump( h, __FUNCTION__ ); - serial_dump( p, __FUNCTION__ ); - - fdhandler_enqueue( s->fdhandler, h ); - fdhandler_enqueue( s->fdhandler, p ); -} - - -/* initialize serial reader */ -static void -serial_init( Serial* s, - int fd, - FDHandlerList* list, - Receiver* receiver ) -{ - Receiver recv; - - recv.user = s; - recv.post = (PostFunc) serial_fd_receive; - recv.close = (CloseFunc) serial_fd_close; - - s->receiver[0] = receiver[0]; - - s->fdhandler = fdhandler_new( fd, list, &recv ); - s->in_len = 0; - s->in_datalen = 0; - s->in_channel = 0; - s->in_packet = packet_alloc(); -} - - -/** CLIENTS - **/ - -typedef struct Client Client; -typedef struct Multiplexer Multiplexer; - -/* A Client object models a single qemud client socket - * connection in the emulated system. - * - * the client first sends the name of the system service - * it wants to contact (no framing), then waits for a 2 - * byte answer from qemud. - * - * the answer is either "OK" or "KO" to indicate - * success or failure. - * - * In case of success, the client can send messages - * to the service. - * - * In case of failure, it can disconnect or try sending - * the name of another service. - */ -struct Client { - Client* next; - Client** pref; - int channel; - char registered; - FDHandler* fdhandler; - Multiplexer* multiplexer; -}; - -struct Multiplexer { - Client* clients; - int last_channel; - Serial serial[1]; - Looper looper[1]; - FDHandlerList fdhandlers[1]; -}; - - -static int multiplexer_open_channel( Multiplexer* mult, Packet* p ); -static void multiplexer_close_channel( Multiplexer* mult, int channel ); -static void multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p ); - -static void -client_dump( Client* c, Packet* p, const char* funcname ) -{ - T("%s: client %p (%d): %3d bytes: '%s'", - funcname, c, c->fdhandler->fd, - p->len, quote(p->data, p->len)); -} - -/* destroy a client */ -static void -client_free( Client* c ) -{ - /* remove from list */ - c->pref[0] = c->next; - if (c->next) - c->next->pref = c->pref; - - c->channel = -1; - c->registered = 0; - - /* gently ask the FDHandler to shutdown to - * avoid losing queued outgoing packets */ - if (c->fdhandler != NULL) { - fdhandler_shutdown(c->fdhandler); - c->fdhandler = NULL; - } - - xfree(c); -} - - -/* a function called when a client socket receives data */ -static void -client_fd_receive( Client* c, Packet* p ) -{ - client_dump(c, p, __FUNCTION__); - - if (c->registered) { - /* the client is registered, just send the - * data through the serial port - */ - multiplexer_serial_send(c->multiplexer, c->channel, p); - return; - } - - if (c->channel > 0) { - /* the client is waiting registration results. - * this should not happen because the client - * should wait for our 'ok' or 'ko'. - * close the connection. - */ - D("%s: bad client sending data before end of registration", - __FUNCTION__); - BAD_CLIENT: - packet_free(&p); - client_free(c); - return; - } - - /* the client hasn't registered a service yet, - * so this must be the name of a service, call - * the multiplexer to start registration for - * it. - */ - D("%s: attempting registration for service '%.*s'", - __FUNCTION__, p->len, p->data); - c->channel = multiplexer_open_channel(c->multiplexer, p); - if (c->channel < 0) { - D("%s: service name too long", __FUNCTION__); - goto BAD_CLIENT; - } - D("%s: -> received channel id %d", __FUNCTION__, c->channel); - packet_free(&p); -} - - -/* a function called when the client socket is closed. */ -static void -client_fd_close( Client* c ) -{ - T("%s: client %p (%d)", __FUNCTION__, c, c->fdhandler->fd); - - /* no need to shutdown the FDHandler */ - c->fdhandler = NULL; - - /* tell the emulator we're out */ - if (c->channel > 0) - multiplexer_close_channel(c->multiplexer, c->channel); - - /* free the client */ - client_free(c); -} - -/* a function called when the multiplexer received a registration - * response from the emulator for a given client. - */ -static void -client_registration( Client* c, int registered ) -{ - Packet* p = packet_alloc(); - - /* sends registration status to client */ - if (!registered) { - D("%s: registration failed for client %d", __FUNCTION__, c->channel); - memcpy( p->data, "KO", 2 ); - p->len = 2; - } else { - D("%s: registration succeeded for client %d", __FUNCTION__, c->channel); - memcpy( p->data, "OK", 2 ); - p->len = 2; - } - client_dump(c, p, __FUNCTION__); - fdhandler_enqueue(c->fdhandler, p); - - /* now save registration state - */ - c->registered = registered; - if (!registered) { - /* allow the client to try registering another service */ - c->channel = -1; - } -} - -/* send data to a client */ -static void -client_send( Client* c, Packet* p ) -{ - client_dump(c, p, __FUNCTION__); - fdhandler_enqueue(c->fdhandler, p); -} - - -/* Create new client socket handler */ -static Client* -client_new( Multiplexer* mult, - int fd, - FDHandlerList* pfdhandlers, - Client** pclients ) -{ - Client* c; - Receiver recv; - - xnew(c); - - c->multiplexer = mult; - c->next = NULL; - c->pref = &c->next; - c->channel = -1; - c->registered = 0; - - recv.user = c; - recv.post = (PostFunc) client_fd_receive; - recv.close = (CloseFunc) client_fd_close; - - c->fdhandler = fdhandler_new( fd, pfdhandlers, &recv ); - - /* add to client list */ - c->next = *pclients; - c->pref = pclients; - *pclients = c; - if (c->next) - c->next->pref = &c->next; - - return c; -} - -/** GLOBAL MULTIPLEXER - **/ - -/* find a client by its channel */ -static Client* -multiplexer_find_client( Multiplexer* mult, int channel ) -{ - Client* c = mult->clients; - - for ( ; c != NULL; c = c->next ) { - if (c->channel == channel) - return c; - } - return NULL; -} - -/* handle control messages coming from the serial port - * on CONTROL_CHANNEL. - */ -static void -multiplexer_handle_control( Multiplexer* mult, Packet* p ) -{ - /* connection registration success */ - if (p->len == 13 && !memcmp(p->data, "ok:connect:", 11)) { - int channel = hex2int(p->data+11, 2); - Client* client = multiplexer_find_client(mult, channel); - - /* note that 'client' can be NULL if the corresponding - * socket was closed before the emulator response arrived. - */ - if (client != NULL) { - client_registration(client, 1); - } else { - D("%s: NULL client: '%.*s'", __FUNCTION__, p->len, p->data+11); - } - goto EXIT; - } - - /* connection registration failure */ - if (p->len == 13 && !memcmp(p->data, "ko:connect:",11)) { - int channel = hex2int(p->data+11, 2); - Client* client = multiplexer_find_client(mult, channel); - - if (client != NULL) - client_registration(client, 0); - - goto EXIT; - } - - /* emulator-induced client disconnection */ - if (p->len == 13 && !memcmp(p->data, "disconnect:",11)) { - int channel = hex2int(p->data+11, 2); - Client* client = multiplexer_find_client(mult, channel); - - if (client != NULL) - client_free(client); - - goto EXIT; - } - - /* A message that begins with "X00" is a probe sent by - * the emulator used to detect which version of qemud it runs - * against (in order to detect 1.0/1.1 system images. Just - * silently ignore it there instead of printing an error - * message. - */ - if (p->len >= 3 && !memcmp(p->data,"X00",3)) { - goto EXIT; - } - - D("%s: unknown control message (%d bytes): '%.*s'", - __FUNCTION__, p->len, p->len, p->data); - -EXIT: - packet_free(&p); -} - -/* a function called when an incoming packet comes from the serial port */ -static void -multiplexer_serial_receive( Multiplexer* mult, Packet* p ) -{ - Client* client; - - T("%s: channel=%d '%.*s'", __FUNCTION__, p->channel, p->len, p->data); - - if (p->channel == CHANNEL_CONTROL) { - multiplexer_handle_control(mult, p); - return; - } - - client = multiplexer_find_client(mult, p->channel); - if (client != NULL) { - client_send(client, p); - return; - } - - D("%s: discarding packet for unknown channel %d", __FUNCTION__, p->channel); - packet_free(&p); -} - -/* a function called when the serial reader closes */ -static void -multiplexer_serial_close( Multiplexer* mult ) -{ - fatal("unexpected close of serial reader"); -} - -/* a function called to send a packet to the serial port */ -static void -multiplexer_serial_send( Multiplexer* mult, int channel, Packet* p ) -{ - p->channel = channel; - serial_send( mult->serial, p ); -} - - - -/* a function used by a client to allocate a new channel id and - * ask the emulator to open it. 'service' must be a packet containing - * the name of the service in its payload. - * - * returns -1 if the service name is too long. - * - * notice that client_registration() will be called later when - * the answer arrives. - */ -static int -multiplexer_open_channel( Multiplexer* mult, Packet* service ) -{ - Packet* p = packet_alloc(); - int len, channel; - - /* find a free channel number, assume we don't have many - * clients here. */ - { - Client* c; - TRY_AGAIN: - channel = (++mult->last_channel) & 0xff; - - for (c = mult->clients; c != NULL; c = c->next) - if (c->channel == channel) - goto TRY_AGAIN; - } - - len = snprintf((char*)p->data, sizeof p->data, "connect:%.*s:%02x", service->len, service->data, channel); - if (len >= (int)sizeof(p->data)) { - D("%s: weird, service name too long (%d > %d)", __FUNCTION__, len, sizeof(p->data)); - packet_free(&p); - return -1; - } - p->channel = CHANNEL_CONTROL; - p->len = len; - - serial_send(mult->serial, p); - return channel; -} - -/* used to tell the emulator a channel was closed by a client */ -static void -multiplexer_close_channel( Multiplexer* mult, int channel ) -{ - Packet* p = packet_alloc(); - int len = snprintf((char*)p->data, sizeof(p->data), "disconnect:%02x", channel); - - if (len > (int)sizeof(p->data)) { - /* should not happen */ - return; - } - - p->channel = CHANNEL_CONTROL; - p->len = len; - - serial_send(mult->serial, p); -} - -/* this function is used when a new connection happens on the control - * socket. - */ -static void -multiplexer_control_accept( Multiplexer* m, Packet* p ) -{ - /* the file descriptor for the new socket connection is - * in p->channel. See fdhandler_accept_event() */ - int fd = p->channel; - Client* client = client_new( m, fd, m->fdhandlers, &m->clients ); - - D("created client %p listening on fd %d", client, fd); - - /* free dummy packet */ - packet_free(&p); -} - -static void -multiplexer_control_close( Multiplexer* m ) -{ - fatal("unexpected multiplexer control close"); -} - -static void -multiplexer_init( Multiplexer* m, const char* serial_dev ) -{ - int fd, control_fd; - Receiver recv; - - /* initialize looper and fdhandlers list */ - looper_init( m->looper ); - fdhandler_list_init( m->fdhandlers, m->looper ); - - /* open the serial port */ - do { - fd = open(serial_dev, O_RDWR); - } while (fd < 0 && errno == EINTR); - - if (fd < 0) { - fatal( "%s: could not open '%s': %s", __FUNCTION__, serial_dev, - strerror(errno) ); - } - // disable echo on serial lines - if ( !memcmp( serial_dev, "/dev/ttyS", 9 ) ) { - struct termios ios; - tcgetattr( fd, &ios ); - ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ - tcsetattr( fd, TCSANOW, &ios ); - } - - /* initialize the serial reader/writer */ - recv.user = m; - recv.post = (PostFunc) multiplexer_serial_receive; - recv.close = (CloseFunc) multiplexer_serial_close; - - serial_init( m->serial, fd, m->fdhandlers, &recv ); - - /* open the qemud control socket */ - recv.user = m; - recv.post = (PostFunc) multiplexer_control_accept; - recv.close = (CloseFunc) multiplexer_control_close; - - fd = android_get_control_socket(CONTROL_SOCKET_NAME); - if (fd < 0) { - fatal("couldn't get fd for control socket '%s'", CONTROL_SOCKET_NAME); - } - - fdhandler_new_accept( fd, m->fdhandlers, &recv ); - - /* initialize clients list */ - m->clients = NULL; -} - -/** MAIN LOOP - **/ - -static Multiplexer _multiplexer[1]; - -int main( void ) -{ - Multiplexer* m = _multiplexer; - - /* extract the name of our serial device from the kernel - * boot options that are stored in /proc/cmdline - */ -#define KERNEL_OPTION "android.qemud=" - - { - char buff[1024]; - int fd, len; - char* p; - char* q; - - fd = open( "/proc/cmdline", O_RDONLY ); - if (fd < 0) { - D("%s: can't open /proc/cmdline !!: %s", __FUNCTION__, - strerror(errno)); - exit(1); - } - - len = fd_read( fd, buff, sizeof(buff)-1 ); - close(fd); - if (len < 0) { - D("%s: can't read /proc/cmdline: %s", __FUNCTION__, - strerror(errno)); - exit(1); - } - buff[len] = 0; - - p = strstr( buff, KERNEL_OPTION ); - if (p == NULL) { - D("%s: can't find '%s' in /proc/cmdline", - __FUNCTION__, KERNEL_OPTION ); - exit(1); - } - - p += sizeof(KERNEL_OPTION)-1; /* skip option */ - q = p; - while ( *q && *q != ' ' && *q != '\t' ) - q += 1; - - snprintf( buff, sizeof(buff), "/dev/%.*s", q-p, p ); - - multiplexer_init( m, buff ); - } - - D( "entering main loop"); - looper_loop( m->looper ); - D( "unexpected termination !!" ); - return 0; -} diff --git a/emulator/sensors/Android.mk b/emulator/sensors/Android.mk deleted file mode 100644 index 9b0e83d..0000000 --- a/emulator/sensors/Android.mk +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2009 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -# We're moving the emulator-specific platform libs to -# development.git/tools/emulator/. The following test is to ensure -# smooth builds even if the tree contains both versions. -# -ifndef BUILD_EMULATOR_SENSORS_MODULE -BUILD_EMULATOR_SENSORS_MODULE := true - -LOCAL_PATH := $(call my-dir) - -ifneq ($(TARGET_PRODUCT),sim) -# HAL module implemenation, not prelinked and stored in -# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.hardware>.so -include $(CLEAR_VARS) -LOCAL_PRELINK_MODULE := false -LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libcutils -LOCAL_SRC_FILES := sensors_qemu.c -LOCAL_MODULE := sensors.goldfish -LOCAL_MODULE_TAGS := debug -include $(BUILD_SHARED_LIBRARY) -endif - -endif # BUILD_EMULATOR_SENSORS_MODULE diff --git a/emulator/sensors/sensors_qemu.c b/emulator/sensors/sensors_qemu.c deleted file mode 100644 index 9a776c7..0000000 --- a/emulator/sensors/sensors_qemu.c +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* this implements a sensors hardware library for the Android emulator. - * the following code should be built as a shared library that will be - * placed into /system/lib/hw/sensors.goldfish.so - * - * it will be loaded by the code in hardware/libhardware/hardware.c - * which is itself called from com_android_server_SensorService.cpp - */ - - -/* we connect with the emulator through the "sensors" qemud service - */ -#define SENSORS_SERVICE_NAME "sensors" - -#define LOG_TAG "QemuSensors" - -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <string.h> -#include <cutils/log.h> -#include <cutils/native_handle.h> -#include <cutils/sockets.h> -#include <hardware/sensors.h> - -#if 0 -#define D(...) LOGD(__VA_ARGS__) -#else -#define D(...) ((void)0) -#endif - -#define E(...) LOGE(__VA_ARGS__) - -#include <hardware/qemud.h> - -/** SENSOR IDS AND NAMES - **/ - -#define MAX_NUM_SENSORS 5 - -#define SUPPORTED_SENSORS ((1<<MAX_NUM_SENSORS)-1) - -#define ID_BASE SENSORS_HANDLE_BASE -#define ID_ACCELERATION (ID_BASE+0) -#define ID_MAGNETIC_FIELD (ID_BASE+1) -#define ID_ORIENTATION (ID_BASE+2) -#define ID_TEMPERATURE (ID_BASE+3) -#define ID_PROXIMITY (ID_BASE+4) - -#define SENSORS_ACCELERATION (1 << ID_ACCELERATION) -#define SENSORS_MAGNETIC_FIELD (1 << ID_MAGNETIC_FIELD) -#define SENSORS_ORIENTATION (1 << ID_ORIENTATION) -#define SENSORS_TEMPERATURE (1 << ID_TEMPERATURE) -#define SENSORS_PROXIMITY (1 << ID_PROXIMITY) - -#define ID_CHECK(x) ((unsigned)((x)-ID_BASE) < MAX_NUM_SENSORS) - -#define SENSORS_LIST \ - SENSOR_(ACCELERATION,"acceleration") \ - SENSOR_(MAGNETIC_FIELD,"magnetic-field") \ - SENSOR_(ORIENTATION,"orientation") \ - SENSOR_(TEMPERATURE,"temperature") \ - SENSOR_(PROXIMITY,"proximity") \ - -static const struct { - const char* name; - int id; } _sensorIds[MAX_NUM_SENSORS] = -{ -#define SENSOR_(x,y) { y, ID_##x }, - SENSORS_LIST -#undef SENSOR_ -}; - -static const char* -_sensorIdToName( int id ) -{ - int nn; - for (nn = 0; nn < MAX_NUM_SENSORS; nn++) - if (id == _sensorIds[nn].id) - return _sensorIds[nn].name; - return "<UNKNOWN>"; -} - -static int -_sensorIdFromName( const char* name ) -{ - int nn; - - if (name == NULL) - return -1; - - for (nn = 0; nn < MAX_NUM_SENSORS; nn++) - if (!strcmp(name, _sensorIds[nn].name)) - return _sensorIds[nn].id; - - return -1; -} - -/** SENSORS POLL DEVICE - ** - ** This one is used to read sensor data from the hardware. - ** We implement this by simply reading the data from the - ** emulator through the QEMUD channel. - **/ - -typedef struct SensorPoll { - struct sensors_poll_device_t device; - sensors_event_t sensors[MAX_NUM_SENSORS]; - int events_fd; - uint32_t pendingSensors; - int64_t timeStart; - int64_t timeOffset; - int fd; - uint32_t active_sensors; -} SensorPoll; - -/* this must return a file descriptor that will be used to read - * the sensors data (it is passed to data__data_open() below - */ -static native_handle_t* -control__open_data_source(struct sensors_poll_device_t *dev) -{ - SensorPoll* ctl = (void*)dev; - native_handle_t* handle; - - if (ctl->fd < 0) { - ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME); - } - D("%s: fd=%d", __FUNCTION__, ctl->fd); - handle = native_handle_create(1, 0); - handle->data[0] = dup(ctl->fd); - return handle; -} - -static int -control__activate(struct sensors_poll_device_t *dev, - int handle, - int enabled) -{ - SensorPoll* ctl = (void*)dev; - uint32_t mask, sensors, active, new_sensors, changed; - char command[128]; - int ret; - - D("%s: handle=%s (%d) fd=%d enabled=%d", __FUNCTION__, - _sensorIdToName(handle), handle, ctl->fd, enabled); - - if (!ID_CHECK(handle)) { - E("%s: bad handle ID", __FUNCTION__); - return -1; - } - - mask = (1<<handle); - sensors = enabled ? mask : 0; - - active = ctl->active_sensors; - new_sensors = (active & ~mask) | (sensors & mask); - changed = active ^ new_sensors; - - if (!changed) - return 0; - - snprintf(command, sizeof command, "set:%s:%d", - _sensorIdToName(handle), enabled != 0); - - if (ctl->fd < 0) { - ctl->fd = qemud_channel_open(SENSORS_SERVICE_NAME); - } - - ret = qemud_channel_send(ctl->fd, command, -1); - if (ret < 0) { - E("%s: when sending command errno=%d: %s", __FUNCTION__, errno, strerror(errno)); - return -1; - } - ctl->active_sensors = new_sensors; - - return 0; -} - -static int -control__set_delay(struct sensors_poll_device_t *dev, int32_t ms) -{ - SensorPoll* ctl = (void*)dev; - char command[128]; - - D("%s: dev=%p delay-ms=%d", __FUNCTION__, dev, ms); - - snprintf(command, sizeof command, "set-delay:%d", ms); - - return qemud_channel_send(ctl->fd, command, -1); -} - -static int -control__close(struct hw_device_t *dev) -{ - SensorPoll* ctl = (void*)dev; - close(ctl->fd); - free(ctl); - return 0; -} - -/* return the current time in nanoseconds */ -static int64_t -data__now_ns(void) -{ - struct timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - - return (int64_t)ts.tv_sec * 1000000000 + ts.tv_nsec; -} - -static int -data__data_open(struct sensors_poll_device_t *dev, native_handle_t* handle) -{ - SensorPoll* data = (void*)dev; - int i; - D("%s: dev=%p fd=%d", __FUNCTION__, dev, handle->data[0]); - memset(&data->sensors, 0, sizeof(data->sensors)); - - for (i=0 ; i<MAX_NUM_SENSORS ; i++) { - data->sensors[i].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH; - } - data->pendingSensors = 0; - data->timeStart = 0; - data->timeOffset = 0; - - data->events_fd = dup(handle->data[0]); - D("%s: dev=%p fd=%d (was %d)", __FUNCTION__, dev, data->events_fd, handle->data[0]); - native_handle_close(handle); - native_handle_delete(handle); - return 0; -} - -static int -data__data_close(struct sensors_poll_device_t *dev) -{ - SensorPoll* data = (void*)dev; - D("%s: dev=%p", __FUNCTION__, dev); - if (data->events_fd >= 0) { - close(data->events_fd); - data->events_fd = -1; - } - return 0; -} - -static int -pick_sensor(SensorPoll* data, - sensors_event_t* values) -{ - uint32_t mask = SUPPORTED_SENSORS; - while (mask) { - uint32_t i = 31 - __builtin_clz(mask); - mask &= ~(1<<i); - if (data->pendingSensors & (1<<i)) { - data->pendingSensors &= ~(1<<i); - *values = data->sensors[i]; - values->sensor = i; - values->version = sizeof(*values); - - D("%s: %d [%f, %f, %f]", __FUNCTION__, - i, - values->data[0], - values->data[1], - values->data[2]); - return i; - } - } - LOGE("No sensor to return!!! pendingSensors=%08x", data->pendingSensors); - // we may end-up in a busy loop, slow things down, just in case. - usleep(100000); - return -EINVAL; -} - -static int -data__poll(struct sensors_poll_device_t *dev, sensors_event_t* values) -{ - SensorPoll* data = (void*)dev; - int fd = data->events_fd; - - D("%s: data=%p", __FUNCTION__, dev); - - // there are pending sensors, returns them now... - if (data->pendingSensors) { - return pick_sensor(data, values); - } - - // wait until we get a complete event for an enabled sensor - uint32_t new_sensors = 0; - - while (1) { - /* read the next event */ - char buff[256]; - int len = qemud_channel_recv(data->events_fd, buff, sizeof buff-1); - float params[3]; - int64_t event_time; - - if (len < 0) { - E("%s: len=%d, errno=%d: %s", __FUNCTION__, len, errno, strerror(errno)); - return -errno; - } - - buff[len] = 0; - - /* "wake" is sent from the emulator to exit this loop. */ - if (!strcmp((const char*)data, "wake")) { - return 0x7FFFFFFF; - } - - /* "acceleration:<x>:<y>:<z>" corresponds to an acceleration event */ - if (sscanf(buff, "acceleration:%g:%g:%g", params+0, params+1, params+2) == 3) { - new_sensors |= SENSORS_ACCELERATION; - data->sensors[ID_ACCELERATION].acceleration.x = params[0]; - data->sensors[ID_ACCELERATION].acceleration.y = params[1]; - data->sensors[ID_ACCELERATION].acceleration.z = params[2]; - continue; - } - - /* "orientation:<azimuth>:<pitch>:<roll>" is sent when orientation changes */ - if (sscanf(buff, "orientation:%g:%g:%g", params+0, params+1, params+2) == 3) { - new_sensors |= SENSORS_ORIENTATION; - data->sensors[ID_ORIENTATION].orientation.azimuth = params[0]; - data->sensors[ID_ORIENTATION].orientation.pitch = params[1]; - data->sensors[ID_ORIENTATION].orientation.roll = params[2]; - continue; - } - - /* "magnetic:<x>:<y>:<z>" is sent for the params of the magnetic field */ - if (sscanf(buff, "magnetic:%g:%g:%g", params+0, params+1, params+2) == 3) { - new_sensors |= SENSORS_MAGNETIC_FIELD; - data->sensors[ID_MAGNETIC_FIELD].magnetic.x = params[0]; - data->sensors[ID_MAGNETIC_FIELD].magnetic.y = params[1]; - data->sensors[ID_MAGNETIC_FIELD].magnetic.z = params[2]; - continue; - } - - /* "temperature:<celsius>" */ - if (sscanf(buff, "temperature:%g", params+0) == 2) { - new_sensors |= SENSORS_TEMPERATURE; - data->sensors[ID_TEMPERATURE].temperature = params[0]; - continue; - } - - /* "proximity:<value>" */ - if (sscanf(buff, "proximity:%g", params+0) == 1) { - new_sensors |= SENSORS_PROXIMITY; - data->sensors[ID_PROXIMITY].distance = params[0]; - continue; - } - - /* "sync:<time>" is sent after a series of sensor events. - * where 'time' is expressed in micro-seconds and corresponds - * to the VM time when the real poll occured. - */ - if (sscanf(buff, "sync:%lld", &event_time) == 1) { - if (new_sensors) { - data->pendingSensors = new_sensors; - int64_t t = event_time * 1000LL; /* convert to nano-seconds */ - - /* use the time at the first sync: as the base for later - * time values */ - if (data->timeStart == 0) { - data->timeStart = data__now_ns(); - data->timeOffset = data->timeStart - t; - } - t += data->timeOffset; - - while (new_sensors) { - uint32_t i = 31 - __builtin_clz(new_sensors); - new_sensors &= ~(1<<i); - data->sensors[i].timestamp = t; - } - return pick_sensor(data, values); - } else { - D("huh ? sync without any sensor data ?"); - } - continue; - } - D("huh ? unsupported command"); - } - return -1; -} - -static int -data__close(struct hw_device_t *dev) -{ - SensorPoll* data = (SensorPoll*)dev; - if (data) { - if (data->events_fd >= 0) { - //LOGD("(device close) about to close fd=%d", data->events_fd); - close(data->events_fd); - } - free(data); - } - return 0; -} - -/** SENSORS POLL DEVICE FUNCTIONS **/ - -static int poll__close(struct hw_device_t* dev) -{ - SensorPoll* ctl = (void*)dev; - close(ctl->fd); - if (ctl->fd >= 0) { - close(ctl->fd); - } - if (ctl->events_fd >= 0) { - close(ctl->events_fd); - } - free(ctl); - return 0; -} - -static int poll__poll(struct sensors_poll_device_t *dev, - sensors_event_t* data, int count) -{ - SensorPoll* datadev = (void*)dev; - int ret; - int i; - D("%s: dev=%p data=%p count=%d ", __FUNCTION__, dev, data, count); - - for (i = 0; i < count; i++) { - ret = data__poll(dev, data); - data++; - if (ret > MAX_NUM_SENSORS || ret < 0) { - return i; - } - if (!datadev->pendingSensors) { - return i + 1; - } - } - return count; -} - -static int poll__activate(struct sensors_poll_device_t *dev, - int handle, int enabled) -{ - int ret; - native_handle_t* hdl; - SensorPoll* ctl = (void*)dev; - D("%s: dev=%p handle=%x enable=%d ", __FUNCTION__, dev, handle, enabled); - if (ctl->fd < 0) { - D("%s: OPEN CTRL and DATA ", __FUNCTION__); - hdl = control__open_data_source(dev); - ret = data__data_open(dev,hdl); - } - ret = control__activate(dev, handle, enabled); - return ret; -} - -static int poll__setDelay(struct sensors_poll_device_t *dev, - int handle, int64_t ns) -{ - // TODO - return 0; -} - -/** MODULE REGISTRATION SUPPORT - ** - ** This is required so that hardware/libhardware/hardware.c - ** will dlopen() this library appropriately. - **/ - -/* - * the following is the list of all supported sensors. - * this table is used to build sSensorList declared below - * according to which hardware sensors are reported as - * available from the emulator (see get_sensors_list below) - * - * note: numerical values for maxRange/resolution/power were - * taken from the reference AK8976A implementation - */ -static const struct sensor_t sSensorListInit[] = { - { .name = "Goldfish 3-axis Accelerometer", - .vendor = "The Android Open Source Project", - .version = 1, - .handle = ID_ACCELERATION, - .type = SENSOR_TYPE_ACCELEROMETER, - .maxRange = 2.8f, - .resolution = 1.0f/4032.0f, - .power = 3.0f, - .reserved = {} - }, - - { .name = "Goldfish 3-axis Magnetic field sensor", - .vendor = "The Android Open Source Project", - .version = 1, - .handle = ID_MAGNETIC_FIELD, - .type = SENSOR_TYPE_MAGNETIC_FIELD, - .maxRange = 2000.0f, - .resolution = 1.0f, - .power = 6.7f, - .reserved = {} - }, - - { .name = "Goldfish Orientation sensor", - .vendor = "The Android Open Source Project", - .version = 1, - .handle = ID_ORIENTATION, - .type = SENSOR_TYPE_ORIENTATION, - .maxRange = 360.0f, - .resolution = 1.0f, - .power = 9.7f, - .reserved = {} - }, - - { .name = "Goldfish Temperature sensor", - .vendor = "The Android Open Source Project", - .version = 1, - .handle = ID_TEMPERATURE, - .type = SENSOR_TYPE_TEMPERATURE, - .maxRange = 80.0f, - .resolution = 1.0f, - .power = 0.0f, - .reserved = {} - }, - - { .name = "Goldfish Proximity sensor", - .vendor = "The Android Open Source Project", - .version = 1, - .handle = ID_PROXIMITY, - .type = SENSOR_TYPE_PROXIMITY, - .maxRange = 1.0f, - .resolution = 1.0f, - .power = 20.0f, - .reserved = {} - }, -}; - -static struct sensor_t sSensorList[MAX_NUM_SENSORS]; - -static int sensors__get_sensors_list(struct sensors_module_t* module, - struct sensor_t const** list) -{ - int fd = qemud_channel_open(SENSORS_SERVICE_NAME); - char buffer[12]; - int mask, nn, count; - - int ret; - if (fd < 0) { - E("%s: no qemud connection", __FUNCTION__); - return 0; - } - ret = qemud_channel_send(fd, "list-sensors", -1); - if (ret < 0) { - E("%s: could not query sensor list: %s", __FUNCTION__, - strerror(errno)); - close(fd); - return 0; - } - ret = qemud_channel_recv(fd, buffer, sizeof buffer-1); - if (ret < 0) { - E("%s: could not receive sensor list: %s", __FUNCTION__, - strerror(errno)); - close(fd); - return 0; - } - buffer[ret] = 0; - close(fd); - - /* the result is a integer used as a mask for available sensors */ - mask = atoi(buffer); - count = 0; - for (nn = 0; nn < MAX_NUM_SENSORS; nn++) { - if (((1 << nn) & mask) == 0) - continue; - - sSensorList[count++] = sSensorListInit[nn]; - } - D("%s: returned %d sensors (mask=%d)", __FUNCTION__, count, mask); - *list = sSensorList; - return count; -} - - -static int -open_sensors(const struct hw_module_t* module, - const char* name, - struct hw_device_t* *device) -{ - int status = -EINVAL; - - D("%s: name=%s", __FUNCTION__, name); - - if (!strcmp(name, SENSORS_HARDWARE_POLL)) { - SensorPoll *dev = malloc(sizeof(*dev)); - - memset(dev, 0, sizeof(*dev)); - - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; - dev->device.common.module = (struct hw_module_t*) module; - dev->device.common.close = poll__close; - dev->device.poll = poll__poll; - dev->device.activate = poll__activate; - dev->device.setDelay = poll__setDelay; - dev->events_fd = -1; - dev->fd = -1; - - *device = &dev->device.common; - status = 0; - } - return status; -} - - -static struct hw_module_methods_t sensors_module_methods = { - .open = open_sensors -}; - -const struct sensors_module_t HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 1, - .version_minor = 0, - .id = SENSORS_HARDWARE_MODULE_ID, - .name = "Goldfish SENSORS Module", - .author = "The Android Open Source Project", - .methods = &sensors_module_methods, - }, - .get_sensors_list = sensors__get_sensors_list -}; diff --git a/emulator/tools/Android.mk b/emulator/tools/Android.mk deleted file mode 100644 index 1bdbf68..0000000 --- a/emulator/tools/Android.mk +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2009 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# this file is used to build emulator-specific program tools -# that should only run in the emulator. -# - -# We're moving the emulator-specific platform libs to -# development.git/tools/emulator/. The following test is to ensure -# smooth builds even if the tree contains both versions. -# -ifndef BUILD_EMULATOR_QEMU_PROPS -BUILD_EMULATOR_QEMU_PROPS := true - -LOCAL_PATH := $(call my-dir) - -ifneq ($(TARGET_PRODUCT),sim) - -# The 'qemu-props' program is run from /system/etc/init.goldfish.rc -# to setup various system properties sent by the emulator program. -# -include $(CLEAR_VARS) -LOCAL_MODULE := qemu-props -LOCAL_SRC_FILES := qemu-props.c -LOCAL_SHARED_LIBRARIES := libcutils -# we don't want this in 'user' builds which don't have -# emulator-specific binaries. -LOCAL_MODULE_TAGS := debug -include $(BUILD_EXECUTABLE) - -endif # TARGET_PRODUCT != sim - -endif # BUILD_EMULATOR_QEMU_PROPS diff --git a/emulator/tools/qemu-props.c b/emulator/tools/qemu-props.c deleted file mode 100644 index 3f086a1..0000000 --- a/emulator/tools/qemu-props.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* this program is used to read a set of system properties and their values - * from the emulator program and set them in the currently-running emulated - * system. It does so by connecting to the 'boot-properties' qemud service. - * - * This program should be run as root and called from - * /system/etc/init.goldfish.rc exclusively. - */ - -#define LOG_TAG "qemu-props" - -#define DEBUG 1 - -#if DEBUG -# include <cutils/log.h> -# define DD(...) LOGI(__VA_ARGS__) -#else -# define DD(...) ((void)0) -#endif - -#include <cutils/properties.h> -#include <unistd.h> -#include <hardware/qemud.h> - -/* Name of the qemud service we want to connect to. - */ -#define QEMUD_SERVICE "boot-properties" - -#define MAX_TRIES 5 - -int main(void) -{ - int qemud_fd, count = 0; - - /* try to connect to the qemud service */ - { - int tries = MAX_TRIES; - - while (1) { - qemud_fd = qemud_channel_open( "boot-properties" ); - if (qemud_fd >= 0) - break; - - if (--tries <= 0) { - DD("Could not connect after too many tries. Aborting"); - return 1; - } - - DD("waiting 1s to wait for qemud."); - sleep(1); - } - } - - DD("connected to '%s' qemud service.", QEMUD_SERVICE); - - /* send the 'list' command to the service */ - if (qemud_channel_send(qemud_fd, "list", -1) < 0) { - DD("could not send command to '%s' service", QEMUD_SERVICE); - return 1; - } - - /* read each system property as a single line from the service, - * until exhaustion. - */ - for (;;) - { -#define BUFF_SIZE (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2) - DD("receiving.."); - char* q; - char temp[BUFF_SIZE]; - int len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1); - - /* lone NUL-byte signals end of properties */ - if (len < 0 || len > BUFF_SIZE-1 || temp[0] == '\0') - break; - - temp[len] = '\0'; /* zero-terminate string */ - - DD("received: %.*s", len, temp); - - /* separate propery name from value */ - q = strchr(temp, '='); - if (q == NULL) { - DD("invalid format, ignored."); - continue; - } - *q++ = '\0'; - - if (property_set(temp, q) < 0) { - DD("could not set property '%s' to '%s'", temp, q); - } else { - count += 1; - } - } - - - /* finally, close the channel and exit */ - close(qemud_fd); - DD("exiting (%d properties set).", count); - return 0; -} |