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(...)   LOGD(__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 
    409 static void
    410 nmea_reader_parse( NmeaReader*  r )
    411 {
    412    /* we received a complete sentence, now parse it to generate
    413     * a new GPS fix...
    414     */
    415     NmeaTokenizer  tzer[1];
    416     Token          tok;
    417 
    418     D("Received: '%.*s'", r->pos, r->in);
    419     if (r->pos < 9) {
    420         D("Too short. discarded.");
    421         return;
    422     }
    423 
    424     nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
    425 #if GPS_DEBUG
    426     {
    427         int  n;
    428         D("Found %d tokens", tzer->count);
    429         for (n = 0; n < tzer->count; n++) {
    430             Token  tok = nmea_tokenizer_get(tzer,n);
    431             D("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
    432         }
    433     }
    434 #endif
    435 
    436     tok = nmea_tokenizer_get(tzer, 0);
    437     if (tok.p + 5 > tok.end) {
    438         D("sentence id '%.*s' too short, ignored.", tok.end-tok.p, tok.p);
    439         return;
    440     }
    441 
    442     // ignore first two characters.
    443     tok.p += 2;
    444     if ( !memcmp(tok.p, "GGA", 3) ) {
    445         // GPS fix
    446         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    447         Token  tok_latitude      = nmea_tokenizer_get(tzer,2);
    448         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,3);
    449         Token  tok_longitude     = nmea_tokenizer_get(tzer,4);
    450         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
    451         Token  tok_altitude      = nmea_tokenizer_get(tzer,9);
    452         Token  tok_altitudeUnits = nmea_tokenizer_get(tzer,10);
    453 
    454         nmea_reader_update_time(r, tok_time);
    455         nmea_reader_update_latlong(r, tok_latitude,
    456                                       tok_latitudeHemi.p[0],
    457                                       tok_longitude,
    458                                       tok_longitudeHemi.p[0]);
    459         nmea_reader_update_altitude(r, tok_altitude, tok_altitudeUnits);
    460 
    461     } else if ( !memcmp(tok.p, "GSA", 3) ) {
    462         // do something ?
    463     } else if ( !memcmp(tok.p, "RMC", 3) ) {
    464         Token  tok_time          = nmea_tokenizer_get(tzer,1);
    465         Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);
    466         Token  tok_latitude      = nmea_tokenizer_get(tzer,3);
    467         Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,4);
    468         Token  tok_longitude     = nmea_tokenizer_get(tzer,5);
    469         Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
    470         Token  tok_speed         = nmea_tokenizer_get(tzer,7);
    471         Token  tok_bearing       = nmea_tokenizer_get(tzer,8);
    472         Token  tok_date          = nmea_tokenizer_get(tzer,9);
    473 
    474         D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
    475         if (tok_fixStatus.p[0] == 'A')
    476         {
    477             nmea_reader_update_date( r, tok_date, tok_time );
    478 
    479             nmea_reader_update_latlong( r, tok_latitude,
    480                                            tok_latitudeHemi.p[0],
    481                                            tok_longitude,
    482                                            tok_longitudeHemi.p[0] );
    483 
    484             nmea_reader_update_bearing( r, tok_bearing );
    485             nmea_reader_update_speed  ( r, tok_speed );
    486         }
    487     } else {
    488         tok.p -= 2;
    489         D("unknown sentence '%.*s", tok.end-tok.p, tok.p);
    490     }
    491     if (r->fix.flags != 0) {
    492 #if GPS_DEBUG
    493         char   temp[256];
    494         char*  p   = temp;
    495         char*  end = p + sizeof(temp);
    496         struct tm   utc;
    497 
    498         p += snprintf( p, end-p, "sending fix" );
    499         if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
    500             p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude, r->fix.longitude);
    501         }
    502         if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
    503             p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
    504         }
    505         if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
    506             p += snprintf(p, end-p, " speed=%g", r->fix.speed);
    507         }
    508         if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
    509             p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
    510         }
    511         if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
    512             p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
    513         }
    514         gmtime_r( (time_t*) &r->fix.timestamp, &utc );
    515         p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
    516         D(temp);
    517 #endif
    518         if (r->callback) {
    519             r->callback( &r->fix );
    520             r->fix.flags = 0;
    521         }
    522         else {
    523             D("no callback, keeping data until needed !");
    524         }
    525     }
    526 }
    527 
    528 
    529 static void
    530 nmea_reader_addc( NmeaReader*  r, int  c )
    531 {
    532     if (r->overflow) {
    533         r->overflow = (c != '\n');
    534         return;
    535     }
    536 
    537     if (r->pos >= (int) sizeof(r->in)-1 ) {
    538         r->overflow = 1;
    539         r->pos      = 0;
    540         return;
    541     }
    542 
    543     r->in[r->pos] = (char)c;
    544     r->pos       += 1;
    545 
    546     if (c == '\n') {
    547         nmea_reader_parse( r );
    548         r->pos = 0;
    549     }
    550 }
    551 
    552 
    553 /*****************************************************************/
    554 /*****************************************************************/
    555 /*****                                                       *****/
    556 /*****       C O N N E C T I O N   S T A T E                 *****/
    557 /*****                                                       *****/
    558 /*****************************************************************/
    559 /*****************************************************************/
    560 
    561 /* commands sent to the gps thread */
    562 enum {
    563     CMD_QUIT  = 0,
    564     CMD_START = 1,
    565     CMD_STOP  = 2
    566 };
    567 
    568 
    569 /* this is the state of our connection to the qemu_gpsd daemon */
    570 typedef struct {
    571     int                     init;
    572     int                     fd;
    573     GpsCallbacks            callbacks;
    574     pthread_t               thread;
    575     int                     control[2];
    576 } GpsState;
    577 
    578 static GpsState  _gps_state[1];
    579 
    580 
    581 static void
    582 gps_state_done( GpsState*  s )
    583 {
    584     // tell the thread to quit, and wait for it
    585     char   cmd = CMD_QUIT;
    586     void*  dummy;
    587     write( s->control[0], &cmd, 1 );
    588     pthread_join(s->thread, &dummy);
    589 
    590     // close the control socket pair
    591     close( s->control[0] ); s->control[0] = -1;
    592     close( s->control[1] ); s->control[1] = -1;
    593 
    594     // close connection to the QEMU GPS daemon
    595     close( s->fd ); s->fd = -1;
    596     s->init = 0;
    597 }
    598 
    599 
    600 static void
    601 gps_state_start( GpsState*  s )
    602 {
    603     char  cmd = CMD_START;
    604     int   ret;
    605 
    606     do { ret=write( s->control[0], &cmd, 1 ); }
    607     while (ret < 0 && errno == EINTR);
    608 
    609     if (ret != 1)
    610         D("%s: could not send CMD_START command: ret=%d: %s",
    611           __FUNCTION__, ret, strerror(errno));
    612 }
    613 
    614 
    615 static void
    616 gps_state_stop( GpsState*  s )
    617 {
    618     char  cmd = CMD_STOP;
    619     int   ret;
    620 
    621     do { ret=write( s->control[0], &cmd, 1 ); }
    622     while (ret < 0 && errno == EINTR);
    623 
    624     if (ret != 1)
    625         D("%s: could not send CMD_STOP command: ret=%d: %s",
    626           __FUNCTION__, ret, strerror(errno));
    627 }
    628 
    629 
    630 static int
    631 epoll_register( int  epoll_fd, int  fd )
    632 {
    633     struct epoll_event  ev;
    634     int                 ret, flags;
    635 
    636     /* important: make the fd non-blocking */
    637     flags = fcntl(fd, F_GETFL);
    638     fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    639 
    640     ev.events  = EPOLLIN;
    641     ev.data.fd = fd;
    642     do {
    643         ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
    644     } while (ret < 0 && errno == EINTR);
    645     return ret;
    646 }
    647 
    648 
    649 static int
    650 epoll_deregister( int  epoll_fd, int  fd )
    651 {
    652     int  ret;
    653     do {
    654         ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
    655     } while (ret < 0 && errno == EINTR);
    656     return ret;
    657 }
    658 
    659 /* this is the main thread, it waits for commands from gps_state_start/stop and,
    660  * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences
    661  * that must be parsed to be converted into GPS fixes sent to the framework
    662  */
    663 static void*
    664 gps_state_thread( void*  arg )
    665 {
    666     GpsState*   state = (GpsState*) arg;
    667     NmeaReader  reader[1];
    668     int         epoll_fd   = epoll_create(2);
    669     int         started    = 0;
    670     int         gps_fd     = state->fd;
    671     int         control_fd = state->control[1];
    672 
    673     nmea_reader_init( reader );
    674 
    675     // register control file descriptors for polling
    676     epoll_register( epoll_fd, control_fd );
    677     epoll_register( epoll_fd, gps_fd );
    678 
    679     D("gps thread running");
    680 
    681     // now loop
    682     for (;;) {
    683         struct epoll_event   events[2];
    684         int                  ne, nevents;
    685 
    686         nevents = epoll_wait( epoll_fd, events, 2, -1 );
    687         if (nevents < 0) {
    688             if (errno != EINTR)
    689                 LOGE("epoll_wait() unexpected error: %s", strerror(errno));
    690             continue;
    691         }
    692         D("gps thread received %d events", nevents);
    693         for (ne = 0; ne < nevents; ne++) {
    694             if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
    695                 LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
    696                 goto Exit;
    697             }
    698             if ((events[ne].events & EPOLLIN) != 0) {
    699                 int  fd = events[ne].data.fd;
    700 
    701                 if (fd == control_fd)
    702                 {
    703                     char  cmd = 255;
    704                     int   ret;
    705                     D("gps control fd event");
    706                     do {
    707                         ret = read( fd, &cmd, 1 );
    708                     } while (ret < 0 && errno == EINTR);
    709 
    710                     if (cmd == CMD_QUIT) {
    711                         D("gps thread quitting on demand");
    712                         goto Exit;
    713                     }
    714                     else if (cmd == CMD_START) {
    715                         if (!started) {
    716                             D("gps thread starting  location_cb=%p", state->callbacks.location_cb);
    717                             started = 1;
    718                             nmea_reader_set_callback( reader, state->callbacks.location_cb );
    719                         }
    720                     }
    721                     else if (cmd == CMD_STOP) {
    722                         if (started) {
    723                             D("gps thread stopping");
    724                             started = 0;
    725                             nmea_reader_set_callback( reader, NULL );
    726                         }
    727                     }
    728                 }
    729                 else if (fd == gps_fd)
    730                 {
    731                     char  buff[32];
    732                     D("gps fd event");
    733                     for (;;) {
    734                         int  nn, ret;
    735 
    736                         ret = read( fd, buff, sizeof(buff) );
    737                         if (ret < 0) {
    738                             if (errno == EINTR)
    739                                 continue;
    740                             if (errno != EWOULDBLOCK)
    741                                 LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
    742                             break;
    743                         }
    744                         D("received %d bytes: %.*s", ret, ret, buff);
    745                         for (nn = 0; nn < ret; nn++)
    746                             nmea_reader_addc( reader, buff[nn] );
    747                     }
    748                     D("gps fd event end");
    749                 }
    750                 else
    751                 {
    752                     LOGE("epoll_wait() returned unkown fd %d ?", fd);
    753                 }
    754             }
    755         }
    756     }
    757 Exit:
    758     return NULL;
    759 }
    760 
    761 
    762 static void
    763 gps_state_init( GpsState*  state )
    764 {
    765     state->init       = 1;
    766     state->control[0] = -1;
    767     state->control[1] = -1;
    768     state->fd         = -1;
    769 
    770     state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);
    771 
    772     if (state->fd < 0) {
    773         D("no gps emulation detected");
    774         return;
    775     }
    776 
    777     D("gps emulation will read from '%s' qemud channel", QEMU_CHANNEL_NAME );
    778 
    779     if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {
    780         LOGE("could not create thread control socket pair: %s", strerror(errno));
    781         goto Fail;
    782     }
    783 
    784     if ( pthread_create( &state->thread, NULL, gps_state_thread, state ) != 0 ) {
    785         LOGE("could not create gps thread: %s", strerror(errno));
    786         goto Fail;
    787     }
    788 
    789     D("gps state initialized");
    790     return;
    791 
    792 Fail:
    793     gps_state_done( state );
    794 }
    795 
    796 
    797 /*****************************************************************/
    798 /*****************************************************************/
    799 /*****                                                       *****/
    800 /*****       I N T E R F A C E                               *****/
    801 /*****                                                       *****/
    802 /*****************************************************************/
    803 /*****************************************************************/
    804 
    805 
    806 static int
    807 qemu_gps_init(GpsCallbacks* callbacks)
    808 {
    809     GpsState*  s = _gps_state;
    810 
    811     if (!s->init)
    812         gps_state_init(s);
    813 
    814     if (s->fd < 0)
    815         return -1;
    816 
    817     s->callbacks = *callbacks;
    818 
    819     return 0;
    820 }
    821 
    822 static void
    823 qemu_gps_cleanup(void)
    824 {
    825     GpsState*  s = _gps_state;
    826 
    827     if (s->init)
    828         gps_state_done(s);
    829 }
    830 
    831 
    832 static int
    833 qemu_gps_start()
    834 {
    835     GpsState*  s = _gps_state;
    836 
    837     if (!s->init) {
    838         D("%s: called with uninitialized state !!", __FUNCTION__);
    839         return -1;
    840     }
    841 
    842     D("%s: called", __FUNCTION__);
    843     gps_state_start(s);
    844     return 0;
    845 }
    846 
    847 
    848 static int
    849 qemu_gps_stop()
    850 {
    851     GpsState*  s = _gps_state;
    852 
    853     if (!s->init) {
    854         D("%s: called with uninitialized state !!", __FUNCTION__);
    855         return -1;
    856     }
    857 
    858     D("%s: called", __FUNCTION__);
    859     gps_state_stop(s);
    860     return 0;
    861 }
    862 
    863 
    864 static int
    865 qemu_gps_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty)
    866 {
    867     return 0;
    868 }
    869 
    870 static int
    871 qemu_gps_inject_location(double latitude, double longitude, float accuracy)
    872 {
    873     return 0;
    874 }
    875 
    876 static void
    877 qemu_gps_delete_aiding_data(GpsAidingData flags)
    878 {
    879 }
    880 
    881 static int qemu_gps_set_position_mode(GpsPositionMode mode, int fix_frequency)
    882 {
    883     // FIXME - support fix_frequency
    884     return 0;
    885 }
    886 
    887 static const void*
    888 qemu_gps_get_extension(const char* name)
    889 {
    890     // no extensions supported
    891     return NULL;
    892 }
    893 
    894 static const GpsInterface  qemuGpsInterface = {
    895     sizeof(GpsInterface),
    896     qemu_gps_init,
    897     qemu_gps_start,
    898     qemu_gps_stop,
    899     qemu_gps_cleanup,
    900     qemu_gps_inject_time,
    901     qemu_gps_inject_location,
    902     qemu_gps_delete_aiding_data,
    903     qemu_gps_set_position_mode,
    904     qemu_gps_get_extension,
    905 };
    906 
    907 const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
    908 {
    909     return &qemuGpsInterface;
    910 }
    911 
    912 static int open_gps(const struct hw_module_t* module, char const* name,
    913         struct hw_device_t** device)
    914 {
    915     struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
    916     memset(dev, 0, sizeof(*dev));
    917 
    918     dev->common.tag = HARDWARE_DEVICE_TAG;
    919     dev->common.version = 0;
    920     dev->common.module = (struct hw_module_t*)module;
    921 //    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    922     dev->get_gps_interface = gps__get_gps_interface;
    923 
    924     *device = (struct hw_device_t*)dev;
    925     return 0;
    926 }
    927 
    928 
    929 static struct hw_module_methods_t gps_module_methods = {
    930     .open = open_gps
    931 };
    932 
    933 const struct hw_module_t HAL_MODULE_INFO_SYM = {
    934     .tag = HARDWARE_MODULE_TAG,
    935     .version_major = 1,
    936     .version_minor = 0,
    937     .id = GPS_HARDWARE_MODULE_ID,
    938     .name = "Goldfish GPS Module",
    939     .author = "The Android Open Source Project",
    940     .methods = &gps_module_methods,
    941 };
    942