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