Home | History | Annotate | Download | only in gps
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /* this implements a GPS hardware library for the Android emulator.
     18  * the following code should be built as a shared library that will be
     19  * placed into /system/lib/hw/gps.goldfish.so
     20  *
     21  * it will be loaded by the code in hardware/libhardware/hardware.c
     22  * which is itself called from android_location_GpsLocationProvider.cpp
     23  */
     24 
     25 
     26 #include <errno.h>
     27 #include <pthread.h>
     28 #include <fcntl.h>
     29 #include <sys/epoll.h>
     30 #include <math.h>
     31 #include <time.h>
     32 
     33 #define  LOG_TAG  "gps_qemu"
     34 #include <cutils/log.h>
     35 #include <cutils/sockets.h>
     36 #include <hardware/gps.h>
     37 #include "qemu_pipe.h"
     38 
     39 /* the name of the qemu-controlled pipe */
     40 #define  QEMU_CHANNEL_NAME  "qemud:gps"
     41 
     42 #define  GPS_DEBUG  0
     43 
     44 #if GPS_DEBUG
     45 #  define  D(...)   ALOGD(__VA_ARGS__)
     46 #else
     47 #  define  D(...)   ((void)0)
     48 #endif
     49 
     50 /*****************************************************************/
     51 /*****************************************************************/
     52 /*****                                                       *****/
     53 /*****       N M E A   T O K E N I Z E R                     *****/
     54 /*****                                                       *****/
     55 /*****************************************************************/
     56 /*****************************************************************/
     57 
     58 typedef struct {
     59     const char*  p;
     60     const char*  end;
     61 } Token;
     62 
     63 #define  MAX_NMEA_TOKENS  16
     64 
     65 typedef struct {
     66     int     count;
     67     Token   tokens[ MAX_NMEA_TOKENS ];
     68 } NmeaTokenizer;
     69 
     70 static int
     71 nmea_tokenizer_init( NmeaTokenizer*  t, const char*  p, const char*  end )
     72 {
     73     int    count = 0;
     74     char*  q;
     75 
     76     // the initial '$' is optional
     77     if (p < end && p[0] == '$')
     78         p += 1;
     79 
     80     // remove trailing newline
     81     if (end > p && end[-1] == '\n') {
     82         end -= 1;
     83         if (end > p && end[-1] == '\r')
     84             end -= 1;
     85     }
     86 
     87     // get rid of checksum at the end of the sentecne
     88     if (end >= p+3 && end[-3] == '*') {
     89         end -= 3;
     90     }
     91 
     92     while (p < end) {
     93         const char*  q = p;
     94 
     95         q = memchr(p, ',', end-p);
     96         if (q == NULL)
     97             q = end;
     98 
     99         if (count < MAX_NMEA_TOKENS) {
    100             t->tokens[count].p   = p;
    101             t->tokens[count].end = q;
    102             count += 1;
    103         }
    104         if (q < end)
    105             q += 1;
    106 
    107         p = q;
    108     }
    109 
    110     t->count = count;
    111     return count;
    112 }
    113 
    114 static Token
    115 nmea_tokenizer_get( NmeaTokenizer*  t, int  index )
    116 {
    117     Token  tok;
    118     static const char*  dummy = "";
    119 
    120     if (index < 0 || index >= t->count) {
    121         tok.p = tok.end = dummy;
    122     } else
    123         tok = t->tokens[index];
    124 
    125     return tok;
    126 }
    127 
    128 
    129 static int
    130 str2int( const char*  p, const char*  end )
    131 {
    132     int   result = 0;
    133     int   len    = end - p;
    134 
    135     for ( ; len > 0; len--, p++ )
    136     {
    137         int  c;
    138 
    139         if (p >= end)
    140             goto Fail;
    141 
    142         c = *p - '0';
    143         if ((unsigned)c >= 10)
    144             goto Fail;
    145 
    146         result = result*10 + c;
    147     }
    148     return  result;
    149 
    150 Fail:
    151     return -1;
    152 }
    153 
    154 static double
    155 str2float( const char*  p, const char*  end )
    156 {
    157     int   result = 0;
    158     int   len    = end - p;
    159     char  temp[16];
    160 
    161     if (len >= (int)sizeof(temp))
    162         return 0.;
    163 
    164     memcpy( temp, p, len );
    165     temp[len] = 0;
    166     return strtod( temp, NULL );
    167 }
    168 
    169 /*****************************************************************/
    170 /*****************************************************************/
    171 /*****                                                       *****/
    172 /*****       N M E A   P A R S E R                           *****/
    173 /*****                                                       *****/
    174 /*****************************************************************/
    175 /*****************************************************************/
    176 
    177 #define  NMEA_MAX_SIZE  83
    178 
    179 typedef struct {
    180     int     pos;
    181     int     overflow;
    182     int     utc_year;
    183     int     utc_mon;
    184     int     utc_day;
    185     int     utc_diff;
    186     GpsLocation  fix;
    187     gps_location_callback  callback;
    188     char    in[ NMEA_MAX_SIZE+1 ];
    189 } NmeaReader;
    190 
    191 
    192 static void
    193 nmea_reader_update_utc_diff( NmeaReader*  r )
    194 {
    195     time_t         now = time(NULL);
    196     struct tm      tm_local;
    197     struct tm      tm_utc;
    198     long           time_local, time_utc;
    199 
    200     gmtime_r( &now, &tm_utc );
    201     localtime_r( &now, &tm_local );
    202 
    203     time_local = tm_local.tm_sec +
    204                  60*(tm_local.tm_min +
    205                  60*(tm_local.tm_hour +
    206                  24*(tm_local.tm_yday +
    207                  365*tm_local.tm_year)));
    208 
    209     time_utc = tm_utc.tm_sec +
    210                60*(tm_utc.tm_min +
    211                60*(tm_utc.tm_hour +
    212                24*(tm_utc.tm_yday +
    213                365*tm_utc.tm_year)));
    214 
    215     r->utc_diff = time_utc - time_local;
    216 }
    217 
    218 
    219 static void
    220 nmea_reader_init( NmeaReader*  r )
    221 {
    222     memset( r, 0, sizeof(*r) );
    223 
    224     r->pos      = 0;
    225     r->overflow = 0;
    226     r->utc_year = -1;
    227     r->utc_mon  = -1;
    228     r->utc_day  = -1;
    229     r->callback = NULL;
    230     r->fix.size = sizeof(r->fix);
    231 
    232     nmea_reader_update_utc_diff( r );
    233 }
    234 
    235 
    236 static void
    237 nmea_reader_set_callback( NmeaReader*  r, gps_location_callback  cb )
    238 {
    239     r->callback = cb;
    240     if (cb != NULL && r->fix.flags != 0) {
    241         D("%s: sending latest fix to new callback", __FUNCTION__);
    242         r->callback( &r->fix );
    243         r->fix.flags = 0;
    244     }
    245 }
    246 
    247 
    248 static int
    249 nmea_reader_update_time( NmeaReader*  r, Token  tok )
    250 {
    251     int        hour, minute;
    252     double     seconds;
    253     struct tm  tm;
    254     time_t     fix_time;
    255 
    256     if (tok.p + 6 > tok.end)
    257         return -1;
    258 
    259     if (r->utc_year < 0) {
    260         // no date yet, get current one
    261         time_t  now = time(NULL);
    262         gmtime_r( &now, &tm );
    263         r->utc_year = tm.tm_year + 1900;
    264         r->utc_mon  = tm.tm_mon + 1;
    265         r->utc_day  = tm.tm_mday;
    266     }
    267 
    268     hour    = str2int(tok.p,   tok.p+2);
    269     minute  = str2int(tok.p+2, tok.p+4);
    270     seconds = str2float(tok.p+4, tok.end);
    271 
    272     tm.tm_hour  = hour;
    273     tm.tm_min   = minute;
    274     tm.tm_sec   = (int) seconds;
    275     tm.tm_year  = r->utc_year - 1900;
    276     tm.tm_mon   = r->utc_mon - 1;
    277     tm.tm_mday  = r->utc_day;
    278     tm.tm_isdst = -1;
    279 
    280     // This is a little confusing, let's use an example:
    281     // Suppose now it's 1970-1-1 01:00 GMT, local time is 1970-1-1 00:00 GMT-1
    282     // Then the utc_diff is 3600.
    283     // The time string from GPS is 01:00:00, mktime assumes it's a local
    284     // time. So we are doing mktime for 1970-1-1 01:00 GMT-1. The result of
    285     // mktime is 7200 (1970-1-1 02:00 GMT) actually. To get the correct
    286     // timestamp, we have to subtract utc_diff here.
    287     fix_time = mktime( &tm ) - r->utc_diff;
    288     r->fix.timestamp = (long long)fix_time * 1000;
    289     return 0;
    290 }
    291 
    292 static int
    293 nmea_reader_update_date( NmeaReader*  r, Token  date, Token  time )
    294 {
    295     Token  tok = date;
    296     int    day, mon, year;
    297 
    298     if (tok.p + 6 != tok.end) {
    299         D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
    300         return -1;
    301     }
    302     day  = str2int(tok.p, tok.p+2);
    303     mon  = str2int(tok.p+2, tok.p+4);
    304     year = str2int(tok.p+4, tok.p+6) + 2000;
    305 
    306     if ((day|mon|year) < 0) {
    307         D("date not properly formatted: '%.*s'", tok.end-tok.p, tok.p);
    308         return -1;
    309     }
    310 
    311     r->utc_year  = year;
    312     r->utc_mon   = mon;
    313     r->utc_day   = day;
    314 
    315     return nmea_reader_update_time( r, time );
    316 }
    317 
    318 
    319 static double
    320 convert_from_hhmm( Token  tok )
    321 {
    322     double  val     = str2float(tok.p, tok.end);
    323     int     degrees = (int)(floor(val) / 100);
    324     double  minutes = val - degrees*100.;
    325     double  dcoord  = degrees + minutes / 60.0;
    326     return dcoord;
    327 }
    328 
    329 
    330 static int
    331 nmea_reader_update_latlong( NmeaReader*  r,
    332                             Token        latitude,
    333                             char         latitudeHemi,
    334                             Token        longitude,
    335                             char         longitudeHemi )
    336 {
    337     double   lat, lon;
    338     Token    tok;
    339 
    340     tok = latitude;
    341     if (tok.p + 6 > tok.end) {
    342         D("latitude is too short: '%.*s'", tok.end-tok.p, tok.p);
    343         return -1;
    344     }
    345     lat = convert_from_hhmm(tok);
    346     if (latitudeHemi == 'S')
    347         lat = -lat;
    348 
    349     tok = longitude;
    350     if (tok.p + 6 > tok.end) {
    351         D("longitude is too short: '%.*s'", tok.end-tok.p, tok.p);
    352         return -1;
    353     }
    354     lon = convert_from_hhmm(tok);
    355     if (longitudeHemi == 'W')
    356         lon = -lon;
    357 
    358     r->fix.flags    |= GPS_LOCATION_HAS_LAT_LONG;
    359     r->fix.latitude  = lat;
    360     r->fix.longitude = lon;
    361     return 0;
    362 }
    363 
    364 
    365 static int
    366 nmea_reader_update_altitude( NmeaReader* r,
    367                              Token altitude,
    368                              Token __unused units )
    369 {
    370     double  alt;
    371     Token   tok = altitude;
    372 
    373     if (tok.p >= tok.end)
    374         return -1;
    375 
    376     r->fix.flags   |= GPS_LOCATION_HAS_ALTITUDE;
    377     r->fix.altitude = str2float(tok.p, tok.end);
    378     return 0;
    379 }
    380 
    381 
    382 static int
    383 nmea_reader_update_bearing( NmeaReader*  r,
    384                             Token        bearing )
    385 {
    386     double  alt;
    387     Token   tok = bearing;
    388 
    389     if (tok.p >= tok.end)
    390         return -1;
    391 
    392     r->fix.flags   |= GPS_LOCATION_HAS_BEARING;
    393     r->fix.bearing  = str2float(tok.p, tok.end);
    394     return 0;
    395 }
    396 
    397 
    398 static int
    399 nmea_reader_update_speed( NmeaReader*  r,
    400                           Token        speed )
    401 {
    402     double  alt;
    403     Token   tok = speed;
    404 
    405     if (tok.p >= tok.end)
    406         return -1;
    407 
    408     r->fix.flags   |= GPS_LOCATION_HAS_SPEED;
    409     r->fix.speed    = str2float(tok.p, tok.end);
    410     return 0;
    411 }
    412 
    413 static int
    414 nmea_reader_update_accuracy( NmeaReader*  r )
    415 {
    416     // Always return 20m accuracy.
    417     // Possibly parse it from the NMEA sentence in the future.
    418     r->fix.flags    |= GPS_LOCATION_HAS_ACCURACY;
    419     r->fix.accuracy = 20;
    420     return 0;
    421 }
    422 
    423 
    424 static void
    425 nmea_reader_parse( NmeaReader*  r )
    426 {
    427    /* we received a complete sentence, now parse it to generate
    428     * a new GPS fix...
    429     */
    430     NmeaTokenizer  tzer[1];
    431     Token          tok;
    432 
    433     D("Received: '%.*s'", r->pos, r->in);
    434     if (r->pos < 9) {
    435         D("Too short. discarded.");
    436         return;
    437     }
    438 
    439     nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
    440 #if GPS_DEBUG
    441     {
    442         int  n;
    443         D("Found %d tokens", tzer->count);
    444         for (n = 0; n < tzer->count; n++) {
    445             Token  tok = nmea_tokenizer_get(tzer,n);
    446             D("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
    447         }
    448     }
    449 #endif
    450 
    451     tok = nmea_tokenizer_get(tzer, 0);
    452     if (tok.p + 5 > tok.end) {
    453         D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
    454         return;
    455     }
    456 
    457     // ignore first two characters.
    458     tok.p += 2;
    459     if ( !memcmp(tok.p, "GGA", 3) ) {
    460         // GPS fix
    461         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    462         Token  tok_latitude      = nmea_tokenizer_get(tzer,2);
    463         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,3);
    464         Token  tok_longitude     = nmea_tokenizer_get(tzer,4);
    465         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
    466         Token  tok_altitude      = nmea_tokenizer_get(tzer,9);
    467         Token  tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
    468 
    469         nmea_reader_update_time(r, tok_time);
    470         nmea_reader_update_latlong(r, tok_latitude,
    471                                       tok_latitudeHemi.p[0],
    472                                       tok_longitude,
    473                                       tok_longitudeHemi.p[0]);
    474         nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
    475 
    476     } else if ( !memcmp(tok.p, "GSA", 3) ) {
    477         // do something ?
    478     } else if ( !memcmp(tok.p, "RMC", 3) ) {
    479         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    480         Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);
    481         Token  tok_latitude      = nmea_tokenizer_get(tzer,3);
    482         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,4);
    483         Token  tok_longitude     = nmea_tokenizer_get(tzer,5);
    484         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
    485         Token  tok_speed         = nmea_tokenizer_get(tzer,7);
    486         Token  tok_bearing       = nmea_tokenizer_get(tzer,8);
    487         Token  tok_date          = nmea_tokenizer_get(tzer,9);
    488 
    489         D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
    490         if (tok_fixStatus.p[0] == 'A')
    491         {
    492             nmea_reader_update_date( r, tok_date, tok_time );
    493 
    494             nmea_reader_update_latlong( r, tok_latitude,
    495                                            tok_latitudeHemi.p[0],
    496                                            tok_longitude,
    497                                            tok_longitudeHemi.p[0] );
    498 
    499             nmea_reader_update_bearing( r, tok_bearing );
    500             nmea_reader_update_speed  ( r, tok_speed );
    501         }
    502     } else {
    503         tok.p -= 2;
    504         D("unknown sentence '%.*s", tok.end-tok.p, tok.p);
    505     }
    506 
    507     // Always update accuracy
    508     nmea_reader_update_accuracy( r );
    509 
    510     if (r->fix.flags != 0) {
    511 #if GPS_DEBUG
    512         char   temp[256];
    513         char*  p   = temp;
    514         char*  end = p + sizeof(temp);
    515         struct tm   utc;
    516 
    517         p += snprintf( p, end-p, "sending fix" );
    518         if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
    519             p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
    520         }
    521         if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
    522             p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
    523         }
    524         if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
    525             p += snprintf(p, end-p, " speed=%g", r->fix.speed);
    526         }
    527         if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
    528             p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
    529         }
    530         if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
    531             p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
    532         }
    533         gmtime_r( (time_t*) &r->fix.timestamp, &utc );
    534         p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
    535         D(temp);
    536 #endif
    537         if (r->callback) {
    538             r->callback( &r->fix );
    539             r->fix.flags = 0;
    540         }
    541         else {
    542             D("no callback, keeping data until needed !");
    543         }
    544     }
    545 }
    546 
    547 
    548 static void
    549 nmea_reader_addc( NmeaReader*  r, int  c )
    550 {
    551     if (r->overflow) {
    552         r->overflow = (c != '\n');
    553         return;
    554     }
    555 
    556     if (r->pos >= (int) sizeof(r->in)-1 ) {
    557         r->overflow = 1;
    558         r->pos      = 0;
    559         return;
    560     }
    561 
    562     r->in[r->pos] = (char)c;
    563     r->pos       += 1;
    564 
    565     if (c == '\n') {
    566         nmea_reader_parse( r );
    567         r->pos = 0;
    568     }
    569 }
    570 
    571 
    572 /*****************************************************************/
    573 /*****************************************************************/
    574 /*****                                                       *****/
    575 /*****       C O N N E C T I O N   S T A T E                 *****/
    576 /*****                                                       *****/
    577 /*****************************************************************/
    578 /*****************************************************************/
    579 
    580 /* commands sent to the gps thread */
    581 enum {
    582     CMD_QUIT  = 0,
    583     CMD_START = 1,
    584     CMD_STOP  = 2
    585 };
    586 
    587 
    588 /* this is the state of our connection to the qemu_gpsd daemon */
    589 typedef struct {
    590     int                     init;
    591     int                     fd;
    592     GpsCallbacks            callbacks;
    593     pthread_t               thread;
    594     int                     control[2];
    595 } GpsState;
    596 
    597 static GpsState  _gps_state[1];
    598 
    599 
    600 static void
    601 gps_state_done( GpsState*  s )
    602 {
    603     // tell the thread to quit, and wait for it
    604     char   cmd = CMD_QUIT;
    605     void*  dummy;
    606     write( s->control[0], &cmd, 1 );
    607     pthread_join(s->thread, &dummy);
    608 
    609     // close the control socket pair
    610     close( s->control[0] ); s->control[0] = -1;
    611     close( s->control[1] ); s->control[1] = -1;
    612 
    613     // close connection to the QEMU GPS daemon
    614     close( s->fd ); s->fd = -1;
    615     s->init = 0;
    616 }
    617 
    618 
    619 static void
    620 gps_state_start( GpsState*  s )
    621 {
    622     char  cmd = CMD_START;
    623     int   ret;
    624 
    625     do { ret=write( s->control[0], &cmd, 1 ); }
    626     while (ret < 0 && errno == EINTR);
    627 
    628     if (ret != 1)
    629         D("%s: could not send CMD_START command: ret=%d: %s",
    630           __FUNCTION__, ret, strerror(errno));
    631 }
    632 
    633 
    634 static void
    635 gps_state_stop( GpsState*  s )
    636 {
    637     char  cmd = CMD_STOP;
    638     int   ret;
    639 
    640     do { ret=write( s->control[0], &cmd, 1 ); }
    641     while (ret < 0 && errno == EINTR);
    642 
    643     if (ret != 1)
    644         D("%s: could not send CMD_STOP command: ret=%d: %s",
    645           __FUNCTION__, ret, strerror(errno));
    646 }
    647 
    648 
    649 static int
    650 epoll_register( int  epoll_fd, int  fd )
    651 {
    652     struct epoll_event  ev;
    653     int                 ret, flags;
    654 
    655     /* important: make the fd non-blocking */
    656     flags = fcntl(fd, F_GETFL);
    657     fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    658 
    659     ev.events  = EPOLLIN;
    660     ev.data.fd = fd;
    661     do {
    662         ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
    663     } while (ret < 0 && errno == EINTR);
    664     return ret;
    665 }
    666 
    667 
    668 static int
    669 epoll_deregister( int  epoll_fd, int  fd )
    670 {
    671     int  ret;
    672     do {
    673         ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
    674     } while (ret < 0 && errno == EINTR);
    675     return ret;
    676 }
    677 
    678 /* this is the main thread, it waits for commands from gps_state_start/stop and,
    679  * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences
    680  * that must be parsed to be converted into GPS fixes sent to the framework
    681  */
    682 static void
    683 gps_state_thread( void*  arg )
    684 {
    685     GpsState*   state = (GpsState*) arg;
    686     NmeaReader  reader[1];
    687     int         epoll_fd   = epoll_create(2);
    688     int         started    = 0;
    689     int         gps_fd     = state->fd;
    690     int         control_fd = state->control[1];
    691 
    692     nmea_reader_init( reader );
    693 
    694     // register control file descriptors for polling
    695     epoll_register( epoll_fd, control_fd );
    696     epoll_register( epoll_fd, gps_fd );
    697 
    698     D("gps thread running");
    699 
    700     // now loop
    701     for (;;) {
    702         struct epoll_event   events[2];
    703         int                  ne, nevents;
    704 
    705         nevents = epoll_wait( epoll_fd, events, 2, -1 );
    706         if (nevents < 0) {
    707             if (errno != EINTR)
    708                 ALOGE("epoll_wait() unexpected error: %s", strerror(errno));
    709             continue;
    710         }
    711         D("gps thread received %d events", nevents);
    712         for (ne = 0; ne < nevents; ne++) {
    713             if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
    714                 ALOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
    715                 return;
    716             }
    717             if ((events[ne].events & EPOLLIN) != 0) {
    718                 int  fd = events[ne].data.fd;
    719 
    720                 if (fd == control_fd)
    721                 {
    722                     char  cmd = 255;
    723                     int   ret;
    724                     D("gps control fd event");
    725                     do {
    726                         ret = read( fd, &cmd, 1 );
    727                     } while (ret < 0 && errno == EINTR);
    728 
    729                     if (cmd == CMD_QUIT) {
    730                         D("gps thread quitting on demand");
    731                         return;
    732                     }
    733                     else if (cmd == CMD_START) {
    734                         if (!started) {
    735                             D("gps thread starting  location_cb=%p", state->callbacks.location_cb);
    736                             started = 1;
    737                             nmea_reader_set_callback( reader, state->callbacks.location_cb );
    738                         }
    739                     }
    740                     else if (cmd == CMD_STOP) {
    741                         if (started) {
    742                             D("gps thread stopping");
    743                             started = 0;
    744                             nmea_reader_set_callback( reader, NULL );
    745                         }
    746                     }
    747                 }
    748                 else if (fd == gps_fd)
    749                 {
    750                     char  buff[32];
    751                     D("gps fd event");
    752                     for (;;) {
    753                         int  nn, ret;
    754 
    755                         ret = read( fd, buff, sizeof(buff) );
    756                         if (ret < 0) {
    757                             if (errno == EINTR)
    758                                 continue;
    759                             if (errno != EWOULDBLOCK)
    760                                 ALOGE("error while reading from gps daemon socket: %s:", strerror(errno));
    761                             break;
    762                         }
    763                         D("received %d bytes: %.*s", ret, ret, buff);
    764                         for (nn = 0; nn < ret; nn++)
    765                             nmea_reader_addc( reader, buff[nn] );
    766                     }
    767                     D("gps fd event end");
    768                 }
    769                 else
    770                 {
    771                     ALOGE("epoll_wait() returned unkown fd %d ?", fd);
    772                 }
    773             }
    774         }
    775     }
    776 }
    777 
    778 
    779 static void
    780 gps_state_init( GpsState*  state, GpsCallbacks* callbacks )
    781 {
    782     state->init       = 1;
    783     state->control[0] = -1;
    784     state->control[1] = -1;
    785     state->fd         = -1;
    786 
    787     state->fd = qemu_pipe_open(QEMU_CHANNEL_NAME);
    788 
    789     if (state->fd < 0) {
    790         D("no gps emulation detected");
    791         return;
    792     }
    793 
    794     D("gps emulation will read from '%s' qemu pipe", QEMU_CHANNEL_NAME );
    795 
    796     if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
    797         ALOGE("could not create thread control socket pair: %s", strerror(errno));
    798         goto Fail;
    799     }
    800 
    801     state->thread = callbacks->create_thread_cb( "gps_state_thread", gps_state_thread, state );
    802 
    803     if ( !state->thread ) {
    804         ALOGE("could not create gps thread: %s", strerror(errno));
    805         goto Fail;
    806     }
    807 
    808     state->callbacks = *callbacks;
    809 
    810     D("gps state initialized");
    811     return;
    812 
    813 Fail:
    814     gps_state_done( state );
    815 }
    816 
    817 
    818 /*****************************************************************/
    819 /*****************************************************************/
    820 /*****                                                       *****/
    821 /*****       I N T E R F A C E                               *****/
    822 /*****                                                       *****/
    823 /*****************************************************************/
    824 /*****************************************************************/
    825 
    826 
    827 static int
    828 qemu_gps_init(GpsCallbacks* callbacks)
    829 {
    830     GpsState*  s = _gps_state;
    831 
    832     if (!s->init)
    833         gps_state_init(s, callbacks);
    834 
    835     if (s->fd < 0)
    836         return -1;
    837 
    838     return 0;
    839 }
    840 
    841 static void
    842 qemu_gps_cleanup(void)
    843 {
    844     GpsState*  s = _gps_state;
    845 
    846     if (s->init)
    847         gps_state_done(s);
    848 }
    849 
    850 
    851 static int
    852 qemu_gps_start()
    853 {
    854     GpsState*  s = _gps_state;
    855 
    856     if (!s->init) {
    857         D("%s: called with uninitialized state !!", __FUNCTION__);
    858         return -1;
    859     }
    860 
    861     D("%s: called", __FUNCTION__);
    862     gps_state_start(s);
    863     return 0;
    864 }
    865 
    866 
    867 static int
    868 qemu_gps_stop()
    869 {
    870     GpsState*  s = _gps_state;
    871 
    872     if (!s->init) {
    873         D("%s: called with uninitialized state !!", __FUNCTION__);
    874         return -1;
    875     }
    876 
    877     D("%s: called", __FUNCTION__);
    878     gps_state_stop(s);
    879     return 0;
    880 }
    881 
    882 
    883 static int
    884 qemu_gps_inject_time(GpsUtcTime __unused time,
    885                      int64_t __unused timeReference,
    886                      int __unused uncertainty)
    887 {
    888     return 0;
    889 }
    890 
    891 static int
    892 qemu_gps_inject_location(double __unused latitude,
    893                          double __unused longitude,
    894                          float __unused accuracy)
    895 {
    896     return 0;
    897 }
    898 
    899 static void
    900 qemu_gps_delete_aiding_data(GpsAidingData __unused flags)
    901 {
    902 }
    903 
    904 static int qemu_gps_set_position_mode(GpsPositionMode __unused mode,
    905                                       GpsPositionRecurrence __unused recurrence,
    906                                       uint32_t __unused min_interval,
    907                                       uint32_t __unused preferred_accuracy,
    908                                       uint32_t __unused preferred_time)
    909 {
    910     // FIXME - support fix_frequency
    911     return 0;
    912 }
    913 
    914 static const void*
    915 qemu_gps_get_extension(const char* __unused name)
    916 {
    917     // no extensions supported
    918     return NULL;
    919 }
    920 
    921 static const GpsInterface  qemuGpsInterface = {
    922     sizeof(GpsInterface),
    923     qemu_gps_init,
    924     qemu_gps_start,
    925     qemu_gps_stop,
    926     qemu_gps_cleanup,
    927     qemu_gps_inject_time,
    928     qemu_gps_inject_location,
    929     qemu_gps_delete_aiding_data,
    930     qemu_gps_set_position_mode,
    931     qemu_gps_get_extension,
    932 };
    933 
    934 const GpsInterface* gps__get_gps_interface(struct gps_device_t* __unused dev)
    935 {
    936     return &qemuGpsInterface;
    937 }
    938 
    939 static int open_gps(const struct hw_module_t* module,
    940                     char const* __unused name,
    941                     struct hw_device_t** device)
    942 {
    943     struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
    944     memset(dev, 0, sizeof(*dev));
    945 
    946     dev->common.tag = HARDWARE_DEVICE_TAG;
    947     dev->common.version = 0;
    948     dev->common.module = (struct hw_module_t*)module;
    949 //    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    950     dev->get_gps_interface = gps__get_gps_interface;
    951 
    952     *device = (struct hw_device_t*)dev;
    953     return 0;
    954 }
    955 
    956 
    957 static struct hw_module_methods_t gps_module_methods = {
    958     .open = open_gps
    959 };
    960 
    961 struct hw_module_t HAL_MODULE_INFO_SYM = {
    962     .tag = HARDWARE_MODULE_TAG,
    963     .version_major = 1,
    964     .version_minor = 0,
    965     .id = GPS_HARDWARE_MODULE_ID,
    966     .name = "Goldfish GPS Module",
    967     .author = "The Android Open Source Project",
    968     .methods = &gps_module_methods,
    969 };
    970