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