Hi,i am puzzled by gps porting on andoroid2.3(gingerbread),i build
libgps.so,but can not get right result,the following are the
source,pls take a look at them,and show me what's wrong with these
codes,thank you in advance.

###BoardAndroid.mk
BOARD_HAVE_LIANSP_GPS :=true     ## gps HAL implement
BOARD_GPS_LIBRARIES="libgps.so"  ##gps lib name


### gps HAL implement(including 2 files below)
--- Android.mk
--- gps-liansp.c

Android.mk
====
#Get from liansp

ifeq ($(strip $(BOARD_HAVE_LIANSP_GPS)),true)
LOCAL_PATH := $(call my-dir)

# HAL module implemenation, not prelinked and stored in
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
include $(CLEAR_VARS)
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware

LOCAL_SRC_FILES := gps-liansp.c

LOCAL_MODULE := libgps
LOCAL_MODULE_TAGS := eng debug
LOCAL_CFLAGS := -DLOG_TAG=\"gps.liansp\"

include $(BUILD_SHARED_LIBRARY)
endif

gps-liansp.c
===
//get this file from liansp,as said this can be use on android 2.3
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* this implements a GPS hardware library for the Android emulator.
 * the following code should be built as a shared library that will be
 * placed into /system/lib/hw/gps.goldfish.so
 *
 * it will be loaded by the code in hardware/libhardware/hardware.c
 * which is itself called from
android_location_GpsLocationProvider.cpp
 */


#include <errno.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <math.h>
#include <time.h>
#include <termios.h>

//#define  LOG_TAG  "gps_qemu"
#include <cutils/log.h>
#include <cutils/sockets.h>
#include <cutils/properties.h>
#include <hardware/gps.h>
//#include <hardware/qemud.h>

/* the name of the qemud-controlled socket */
//#define  QEMU_CHANNEL_NAME  "gps"

#define GPS_DATA_IF "s3c2410_serial3"
#define GPS_POWER_IF "/sys/devices/virtual/pm_gpio/gps/enable"


#define  GPS_DEBUG  1

#if GPS_DEBUG
#  define  D(...)   LOGD(__VA_ARGS__)
#else
#  define  D(...)   ((void)0)
#endif

#define GPS_STATUS_CB(_cb, _s)    \
  if ((_cb).status_cb) {          \
    GpsStatus gps_status;         \
    gps_status.status = (_s);     \
    (_cb).status_cb(&gps_status); \
    D("gps status callback: 0x%x", _s); \
  }
/*****************************************************************/
/*****************************************************************/
/*****                                                       *****/
/*****       N M E A   T O K E N I Z E R                     *****/
/*****                                                       *****/
/*****************************************************************/
/*****************************************************************/

typedef struct {
    const char*  p;
    const char*  end;
} Token;

#define  MAX_NMEA_TOKENS  16

typedef struct {
    int     count;
    Token   tokens[ MAX_NMEA_TOKENS ];
} NmeaTokenizer;

static int
nmea_tokenizer_init( NmeaTokenizer*  t, const char*  p, const char*
end )
{
    D("%s\n", __FUNCTION__);
    int    count = 0;
    char*  q;

    // the initial '$' is optional
    if (p < end && p[0] == '$')
        p += 1;

    // remove trailing newline
    if (end > p && end[-1] == '\n') {
        end -= 1;
        if (end > p && end[-1] == '\r')
            end -= 1;
    }

    // get rid of checksum at the end of the sentecne
    if (end >= p+3 && end[-3] == '*') {
        end -= 3;
    }

    while (p < end) {
        const char*  q = p;

        q = memchr(p, ',', end-p);
        if (q == NULL)
            q = end;

//        if (q > p) {
            if (count < MAX_NMEA_TOKENS) {
                t->tokens[count].p   = p;
                t->tokens[count].end = q;
                count += 1;
            }
//        }
        if (q < end)
            q += 1;

        p = q;
    }

    t->count = count;
    return count;
}

static Token
nmea_tokenizer_get( NmeaTokenizer*  t, int  index )
{
    D("%s\n", __FUNCTION__);
    Token  tok;
    static const char*  dummy = "";

    if (index < 0 || index >= t->count) {
        tok.p = tok.end = dummy;
    } else
        tok = t->tokens[index];

    return tok;
}


static int
str2int( const char*  p, const char*  end )
{
    int   result = 0;
    int   len    = end - p;

    for ( ; len > 0; len--, p++ )
    {
        int  c;

        if (p >= end)
            goto Fail;

        c = *p - '0';
        if ((unsigned)c >= 10)
            goto Fail;

        result = result*10 + c;
    }
    return  result;

Fail:
    return -1;
}

static double
str2float( const char*  p, const char*  end )
{
    int   result = 0;
    int   len    = end - p;
    char  temp[16];

    if (len >= (int)sizeof(temp))
        return 0.;

    memcpy( temp, p, len );
    temp[len] = 0;
    return strtod( temp, NULL );
}

/*****************************************************************/
/*****************************************************************/
/*****                                                       *****/
/*****       N M E A   P A R S E R                           *****/
/*****                                                       *****/
/*****************************************************************/
/*****************************************************************/

#define  NMEA_MAX_SIZE  83

typedef struct {
    int     pos;
    int     overflow;
    int     utc_year;
    int     utc_mon;
    int     utc_day;
    int     utc_diff;

    GpsLocation  fix;
    gps_location_callback  callback;
    GpsSvStatus  sv_status;
    gps_sv_status_callback sv_callback;

    char    in[ NMEA_MAX_SIZE+1 ];
} NmeaReader;


static void
nmea_reader_update_utc_diff( NmeaReader*  r )
{
    D("%s\n", __FUNCTION__);
    time_t         now = time(NULL);
    struct tm      tm_local;
    struct tm      tm_utc;
    long           time_local, time_utc;

    gmtime_r( &now, &tm_utc );
    localtime_r( &now, &tm_local );

    time_local = tm_local.tm_sec +
                 60*(tm_local.tm_min +
                 60*(tm_local.tm_hour +
                 24*(tm_local.tm_yday +
                 365*tm_local.tm_year)));

    time_utc = tm_utc.tm_sec +
               60*(tm_utc.tm_min +
               60*(tm_utc.tm_hour +
               24*(tm_utc.tm_yday +
               365*tm_utc.tm_year)));

    r->utc_diff = time_utc - time_local;
}


static void
nmea_reader_init( NmeaReader*  r )
{
    D("%s\n", __FUNCTION__);
    memset( r, 0, sizeof(*r) );

    r->pos      = 0;
    r->overflow = 0;
    r->utc_year = -1;
    r->utc_mon  = -1;
    r->utc_day  = -1;
    r->callback = NULL;
    r->fix.size = sizeof(r->fix);
    r->sv_status.size = sizeof(r->sv_status);

    nmea_reader_update_utc_diff( r );
}


static void
nmea_reader_set_callback( NmeaReader*  r, gps_location_callback  cb,
                gps_sv_status_callback sv_cb )
{
    D("%s\n", __FUNCTION__);
    r->callback = cb;
    r->sv_callback = sv_cb;
    if (cb != NULL && r->fix.flags != 0) {
        D("%s: sending latest fix to new callback", __FUNCTION__);
        r->callback( &r->fix );
        r->fix.flags = 0;
    }
}


static int
nmea_reader_update_time( NmeaReader*  r, Token  tok )
{
    D("%s\n", __FUNCTION__);
    int        hour, minute;
    double     seconds;
    struct tm  tm;
    time_t     fix_time;

    if (tok.p + 6 > tok.end)
        return -1;

    if (r->utc_year < 0) {
        // no date yet, get current one
        time_t  now = time(NULL);
        gmtime_r( &now, &tm );
        r->utc_year = tm.tm_year + 1900;
        r->utc_mon  = tm.tm_mon + 1;
        r->utc_day  = tm.tm_mday;
    }

    hour    = str2int(tok.p,   tok.p+2);
    minute  = str2int(tok.p+2, tok.p+4);
    seconds = str2float(tok.p+4, tok.end);

    tm.tm_hour  = hour;
    tm.tm_min   = minute;
    tm.tm_sec   = (int) seconds;
    tm.tm_year  = r->utc_year - 1900;
    tm.tm_mon   = r->utc_mon - 1;
    tm.tm_mday  = r->utc_day;
    tm.tm_isdst = -1;

    fix_time = mktime( &tm ) + r->utc_diff;
    r->fix.timestamp = (long long)fix_time * 1000;
    return 0;
}

static int
nmea_reader_update_date( NmeaReader*  r, Token  date, Token  time )
{
    D("%s\n", __FUNCTION__);
    Token  tok = date;
    int    day, mon, year;

    if (tok.p + 6 != tok.end) {
        D("1-date not properly formatted: '%.*s'", tok.end-tok.p,
tok.p);
        return -1;
    }
    day  = str2int(tok.p, tok.p+2);
    mon  = str2int(tok.p+2, tok.p+4);
    year = str2int(tok.p+4, tok.p+6) + 2000;

    if ((day|mon|year) < 0) {
        D("2-date not properly formatted: '%.*s'", tok.end-tok.p,
tok.p);
        return -1;
    }

    r->utc_year  = year;
    r->utc_mon   = mon;
    r->utc_day   = day;

    return nmea_reader_update_time( r, time );
}


static double
convert_from_hhmm( Token  tok )
{
    D("%s\n", __FUNCTION__);
    double  val     = str2float(tok.p, tok.end);
    int     degrees = (int)(floor(val) / 100);
    double  minutes = val - degrees*100.;
    double  dcoord  = degrees + minutes / 60.0;
    return dcoord;
}


static int
nmea_reader_update_latlong( NmeaReader*  r,
                            Token        latitude,
                            char         latitudeHemi,
                            Token        longitude,
                            char         longitudeHemi )
{
    D("%s\n", __FUNCTION__);
    double   lat, lon;
    Token    tok;

    tok = latitude;
    if (tok.p + 6 > tok.end) {
        D("latitude is too short: '%.*s'", tok.end-tok.p, tok.p);
        return -1;
    }
    lat = convert_from_hhmm(tok);
    if (latitudeHemi == 'S')
        lat = -lat;

    tok = longitude;
    if (tok.p + 6 > tok.end) {
        D("longitude is too short: '%.*s'", tok.end-tok.p, tok.p);
        return -1;
    }
    lon = convert_from_hhmm(tok);
    if (longitudeHemi == 'W')
        lon = -lon;

    r->fix.flags    |= GPS_LOCATION_HAS_LAT_LONG;
    r->fix.latitude  = lat;
    r->fix.longitude = lon;
    return 0;
}


static int
nmea_reader_update_altitude( NmeaReader*  r,
                             Token        altitude,
                             Token        units )
{
    D("%s\n", __FUNCTION__);
    double  alt;
    Token   tok = altitude;

    if (tok.p >= tok.end)
        return -1;

    r->fix.flags   |= GPS_LOCATION_HAS_ALTITUDE;
    r->fix.altitude = str2float(tok.p, tok.end);
    return 0;
}


static int
nmea_reader_update_bearing( NmeaReader*  r,
                            Token        bearing )
{
    D("%s\n", __FUNCTION__);
    double  alt;
    Token   tok = bearing;

    if (tok.p >= tok.end)
        return -1;

    r->fix.flags   |= GPS_LOCATION_HAS_BEARING;
    r->fix.bearing  = str2float(tok.p, tok.end);
    return 0;
}


static int
nmea_reader_update_speed( NmeaReader*  r,
                          Token        speed )
{
    D("%s\n", __FUNCTION__);
    double  alt;
    Token   tok = speed;

    if (tok.p >= tok.end)
        return -1;

    r->fix.flags   |= GPS_LOCATION_HAS_SPEED;
    r->fix.speed    = str2float(tok.p, tok.end);
    return 0;
}


static int
nmea_reader_update_accuracy( NmeaReader*  r,
                             Token        accuracy )
{
    D("%s\n", __FUNCTION__);
    double  acc;
    Token   tok = accuracy;

    if (tok.p >= tok.end)
        return -1;

    r->fix.accuracy = str2float(tok.p, tok.end);

    if (r->fix.accuracy == 99.99){
      return 0;
    }

    r->fix.flags   |= GPS_LOCATION_HAS_ACCURACY;
    return 0;
}


static void
nmea_reader_parse( NmeaReader*  r )
{
   /* we received a complete sentence, now parse it to generate
    * a new GPS fix...
    */
    NmeaTokenizer  tzer[1];
    Token          tok;

    D("Received: '%.*s'", r->pos, r->in);
    if (r->pos < 9) {
        D("Too short. discarded.");
        return;
    }

    nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
#if GPS_DEBUG_N
    {
        int  n;
        D("Found %d tokens", tzer->count);
        for (n = 0; n < tzer->count; n++) {
            Token  tok = nmea_tokenizer_get(tzer,n);
            D("%2d: '%.*s'", n, tok.end-tok.p, tok.p);
        }
    }
#endif

    tok = nmea_tokenizer_get(tzer, 0);
    if (tok.p + 5 > tok.end) {
        D("sentence id '%.*s' too short, ignored.", tok.end-tok.p,
tok.p);
        return;
    }

    // ignore first two characters.
    tok.p += 2;
    if ( !memcmp(tok.p, "GGA", 3) ) {
        // GPS fix
        /*
        Token  tok_time          = nmea_tokenizer_get(tzer,1);
        Token  tok_latitude      = nmea_tokenizer_get(tzer,2);
        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,3);
        Token  tok_longitude     = nmea_tokenizer_get(tzer,4);
        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,5);
        */
        Token  tok_altitude      = nmea_tokenizer_get(tzer,9);
        Token  tok_altitudeUnits = nmea_tokenizer_get(tzer,10);

        /*
        nmea_reader_update_time(r, tok_time);
        nmea_reader_update_latlong(r, tok_latitude,
                                      tok_latitudeHemi.p[0],
                                      tok_longitude,
                                      tok_longitudeHemi.p[0]);
        */
        nmea_reader_update_altitude(r, tok_altitude,
tok_altitudeUnits);

    } else if ( !memcmp(tok.p, "RMC", 3) ) {
        Token  tok_time          = nmea_tokenizer_get(tzer,1);
        Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);
        Token  tok_latitude      = nmea_tokenizer_get(tzer,3);
        Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,4);
        Token  tok_longitude     = nmea_tokenizer_get(tzer,5);
        Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,6);
        Token  tok_speed         = nmea_tokenizer_get(tzer,7);
        Token  tok_bearing       = nmea_tokenizer_get(tzer,8);
        Token  tok_date          = nmea_tokenizer_get(tzer,9);

        D("in RMC, fixStatus=%c", tok_fixStatus.p[0]);
        if (tok_fixStatus.p[0] == 'A')
        {
            nmea_reader_update_date( r, tok_date, tok_time );

            nmea_reader_update_latlong( r, tok_latitude,
                                           tok_latitudeHemi.p[0],
                                           tok_longitude,
                                           tok_longitudeHemi.p[0] );

            nmea_reader_update_bearing( r, tok_bearing );
            nmea_reader_update_speed  ( r, tok_speed );
        }

    } else if ( !memcmp(tok.p, "GSA", 3) ) {
        Token  tok_fixStatus   = nmea_tokenizer_get(tzer, 2);
        int i;

        r->sv_status.used_in_fix_mask = 0ul;

        if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') {

          Token  tok_accuracy      = nmea_tokenizer_get(tzer, 15);

          nmea_reader_update_accuracy(r, tok_accuracy);

          for (i = 3; i <= 14; ++i){

            Token  tok_prn  = nmea_tokenizer_get(tzer, i);
            int prn = str2int(tok_prn.p, tok_prn.end);

            if (prn > 0){
              r->sv_status.used_in_fix_mask |= (1ul << (prn - 1));
            }
          }
        }

    } else if (!memcmp(tok.p, "GSV", 3)) {
        Token tok_noSatellites = nmea_tokenizer_get(tzer, 3);
        int noSatellites =
            str2int(tok_noSatellites.p, tok_noSatellites.end);

        if (noSatellites > 0) {

            Token tok_noSentences = nmea_tokenizer_get(tzer, 1);
            Token tok_sentence = nmea_tokenizer_get(tzer, 2);

            int sentence = str2int(tok_sentence.p, tok_sentence.end);
            int totalSentences =
                str2int(tok_noSentences.p, tok_noSentences.end);
            int curr;
            int i;

            if (sentence == 1) {
                r->sv_status.num_svs = 0;
            }

            curr = r->sv_status.num_svs;

            i = 0;

            while ((i < 4) && (r->sv_status.num_svs < noSatellites)) {

                Token tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4);
                Token tok_elevation = nmea_tokenizer_get(tzer, i * 4 +
5);
                Token tok_azimuth = nmea_tokenizer_get(tzer, i * 4 +
6);
                Token tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7);
                int prn;
                double snr;

                prn = str2int(tok_prn.p, tok_prn.end);
                snr = str2float(tok_snr.p, tok_snr.end);

                //if (prn > 0 && snr > 0) {
                if (prn > 0) {
                    r->sv_status.sv_list[curr].prn = prn;
                    r->sv_status.sv_list[curr].elevation =
                        str2float(tok_elevation.p, tok_elevation.end);
                    r->sv_status.sv_list[curr].azimuth =
                        str2float(tok_azimuth.p, tok_azimuth.end);
                    r->sv_status.sv_list[curr].snr = snr;
                    r->sv_status.num_svs += 1;

                    curr += 1;
                }
                i += 1;
            }
            if (sentence == totalSentences) {
                r->sv_callback( &r->sv_status );
            }
        } else {
                        if (r->sv_status.num_svs > 0) {
                                r->sv_status.num_svs = 0;
                                r->sv_status.used_in_fix_mask = 0ul;
                                r->sv_callback( &r->sv_status );
                        }
        }

    } else {
        tok.p -= 2;
        D("unknown sentence '%.*s", tok.end-tok.p, tok.p);
    }

    if (r->fix.flags != 0) {
#if GPS_DEBUG
        char   temp[256];
        char*  p   = temp;
        char*  end = p + sizeof(temp);
        struct tm   utc;

        p += snprintf( p, end-p, "sending fix" );
        if (r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {
            p += snprintf(p, end-p, " lat=%g lon=%g", r->fix.latitude,
r->fix.longitude);
        }
        if (r->fix.flags & GPS_LOCATION_HAS_ALTITUDE) {
            p += snprintf(p, end-p, " altitude=%g", r->fix.altitude);
        }
        if (r->fix.flags & GPS_LOCATION_HAS_SPEED) {
            p += snprintf(p, end-p, " speed=%g", r->fix.speed);
        }
        if (r->fix.flags & GPS_LOCATION_HAS_BEARING) {
            p += snprintf(p, end-p, " bearing=%g", r->fix.bearing);
        }
        if (r->fix.flags & GPS_LOCATION_HAS_ACCURACY) {
            p += snprintf(p,end-p, " accuracy=%g", r->fix.accuracy);
        }
        gmtime_r( (time_t*) &r->fix.timestamp, &utc );
        p += snprintf(p, end-p, " time=%s", asctime( &utc ) );
        D("*** %s", temp);
#endif
        if (r->callback) {
            r->callback( &r->fix );
            r->fix.flags = 0;
        }
        else {
            D("no callback, keeping data until needed !");
        }
    }
}


static void
nmea_reader_addc( NmeaReader*  r, int  c )
{
    D("%s\n", __FUNCTION__);
    if (r->overflow) {
        r->overflow = (c != '\n');
        return;
    }

    if (r->pos >= (int) sizeof(r->in)-1 ) {
        r->overflow = 1;
        r->pos      = 0;
        return;
    }

    r->in[r->pos] = (char)c;
    r->pos       += 1;

    if (c == '\n') {
        ////TESTIT
        /*
                if (!memcmp(r->in, "$GPGGA", 6)) {
                        strcpy(r->in, "$GPGGA,092725.00,4717.11399,N,
00833.91590,E,
1,8,1.01,499.6,M,48.0,M,,0*5B\r\n");
                        r->pos = strlen(r->in);
                } else if (!memcmp(r->in, "$GPRMC", 6)) {
                        strcpy(r->in, "$GPRMC,083559.00,A,4717.11437,N,
00833.91522,E,
0.004,77.52,091202,,,A*57\r\n");
                        r->pos = strlen(r->in);
                } else if (!memcmp(r->in, "$GPGSA", 6)) {
                        strcpy(r->in, "$GPGSA,A,
3,23,29,07,08,09,18,26,28,,,,,1.94,1.18,1.54*0D\r\n");
                        r->pos = strlen(r->in);
                } else if (!memcmp(r->in, "$GPGSV", 6)) {
                        static int index = 0;
                        if (index == 0)
                                strcpy(r->in, "$GPGSV,
3,1,10,23,38,230,44,29,71,156,47,07,29,116,41,08,09,081,36*7F\r\n");
                        else if (index == 1)
                                strcpy(r->in, "$GPGSV,
3,2,10,10,07,189,,05,05,220,,09,34,274,42,18,25,309,44*72\r\n");
                        else if (index == 2)
                                strcpy(r->in, "$GPGSV,
3,3,10,26,82,187,47,28,43,056,46*77\r\n");
                        r->pos = strlen(r->in);
                        index++;
                        index %= 3;
                }
                */
                ////TESTIT

        nmea_reader_parse( r );
        r->pos = 0;
    }
}


/*****************************************************************/
/*****************************************************************/
/*****                                                       *****/
/*****       gps HW interface                                *****/
/*****                                                       *****/
/*****************************************************************/
/*****************************************************************/

static int hw_dev_open(void)
{
    char prop[PROPERTY_VALUE_MAX];
    char device[256];
    int fd;
    D("%s\n", __FUNCTION__);
    // look for a kernel-provided device name

    if (property_get("ro.kernel.android.gps",prop,GPS_DATA_IF) == 0) {
        D("no kernel-provided gps device name");
        return -1;
    }

    if ( snprintf(device, sizeof(device), "/dev/%s", prop) >=
(int)sizeof(device) ) {
        LOGE("gps serial device name too long: '%s'", prop);
        return -1;
    }

    do {
        fd = open( device, O_RDWR );
    } while (fd < 0 && errno == EINTR);

    // disable echo on serial lines
    if ( isatty( fd ) ) {
        struct termios  ios;
        tcgetattr( fd, &ios );
        ios.c_lflag = 0;  /* disable ECHO, ICANON, etc... */
        ios.c_oflag &= (~ONLCR); /* Stop \n -> \r\n translation on
output */
        ios.c_iflag &= (~(ICRNL | INLCR)); /* Stop \r -> \n & \n -> \r
translation on input */
        ios.c_iflag |= (IGNCR | IXOFF);  /* Ignore \r & XON/XOFF on
input */
        tcsetattr( fd, TCSANOW, &ios );
    }

    return fd;
}


static void hw_dev_power(int state)
{
    char   prop[PROPERTY_VALUE_MAX];
    int fd;
    char cmd;
    int ret;
    D("%s\n", __FUNCTION__);
    if (property_get("gps.power_on",prop,GPS_POWER_IF) == 0) {
        LOGE("no gps power interface name");
        return;
    }

    do {
        fd = open( prop, O_RDWR );
    } while (fd < 0 && errno == EINTR);

    if (fd < 0) {
        LOGE("could not open gps power interfcae: %s", prop );
        return;
    }

    if (state) {
      cmd = '1';
    } else {
      cmd = '0';
    }

    do {
        ret = write( fd, &cmd, 1 );
    } while (ret < 0 && errno == EINTR);

    close(fd);

    D("gps power state = %c", cmd);

    return;

}


/*****************************************************************/
/*****************************************************************/
/*****                                                       *****/
/*****       C O N N E C T I O N   S T A T E                 *****/
/*****                                                       *****/
/*****************************************************************/
/*****************************************************************/

/* commands sent to the gps thread */
enum {
    CMD_QUIT  = 0,
    CMD_START = 1,
    CMD_STOP  = 2
};


/* this is the state of our connection to the qemu_gpsd daemon */
typedef struct {
    int                     init;
    int                     fd;
    GpsCallbacks            callbacks;
    pthread_t               thread;
    int                     control[2];
} GpsState;

static GpsState  _gps_state[1];


static void
gps_report_status( GpsState*  s, GpsStatusValue st)
{
    D("%s\n", __FUNCTION__);
        GpsStatus gps_st;

        gps_st.size = sizeof(GpsStatus);
        gps_st.status = st;
        if (s->callbacks.status_cb) {
                s->callbacks.status_cb(&gps_st);
        }
}

static void
gps_state_done( GpsState*  s )
{
    D("%s\n", __FUNCTION__);
    // tell the thread to quit, and wait for it
    char   cmd = CMD_QUIT;
    void*  dummy;
    write( s->control[0], &cmd, 1 );
    pthread_join(s->thread, &dummy);

    // close the control socket pair
    close( s->control[0] ); s->control[0] = -1;
    close( s->control[1] ); s->control[1] = -1;

    // close connection to the QEMU GPS daemon
    close( s->fd ); s->fd = -1;
    s->init = 0;
}


static void
gps_state_start( GpsState*  s )
{
    D("%s\n", __FUNCTION__);
    char  cmd = CMD_START;
    int   ret;

    do { ret=write( s->control[0], &cmd, 1 ); }
    while (ret < 0 && errno == EINTR);

    if (ret != 1)
        D("%s: could not send CMD_START command: ret=%d: %s",
          __FUNCTION__, ret, strerror(errno));
}


static void
gps_state_stop( GpsState*  s )
{
    D("%s\n", __FUNCTION__);
    char  cmd = CMD_STOP;
    int   ret;

    do { ret=write( s->control[0], &cmd, 1 ); }
    while (ret < 0 && errno == EINTR);

    if (ret != 1)
        D("%s: could not send CMD_STOP command: ret=%d: %s",
          __FUNCTION__, ret, strerror(errno));
}


static int
epoll_register( int  epoll_fd, int  fd )
{
    struct epoll_event  ev;
    int                 ret, flags;

    /* important: make the fd non-blocking */
    flags = fcntl(fd, F_GETFL);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    ev.events  = EPOLLIN;
    ev.data.fd = fd;
    do {
        ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
    } while (ret < 0 && errno == EINTR);
    return ret;
}


static int
epoll_deregister( int  epoll_fd, int  fd )
{
    int  ret;
    do {
        ret = epoll_ctl( epoll_fd, EPOLL_CTL_DEL, fd, NULL );
    } while (ret < 0 && errno == EINTR);
    return ret;
}

/* this is the main thread, it waits for commands from
gps_state_start/
stop and,
 * when started, messages from the QEMU GPS daemon. these are simple
NMEA sentences
 * that must be parsed to be converted into GPS fixes sent to the
framework
 */
static void
gps_state_thread( void*  arg )
{
    GpsState*   state = (GpsState*) arg;
    NmeaReader  reader[1];
    int         epoll_fd   = epoll_create(2);
    int         started    = 0;
    int         gps_fd     = state->fd;
    int         control_fd = state->control[1];

    nmea_reader_init( reader );

    // register control file descriptors for polling
    epoll_register( epoll_fd, control_fd );
    epoll_register( epoll_fd, gps_fd );

    D("gps thread running");

    hw_dev_power(1);

    // now loop
    for (;;) {
        struct epoll_event   events[2];
        int                  ne, nevents;

        nevents = epoll_wait( epoll_fd, events, 2, -1 );
        if (nevents < 0) {
            if (errno != EINTR)
                LOGE("epoll_wait() unexpected error: %s",
strerror(errno));
            continue;
        }
//        D("gps thread received %d events", nevents);
        for (ne = 0; ne < nevents; ne++) {
            if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
                LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
                goto Exit;
            }
            if ((events[ne].events & EPOLLIN) != 0) {
                int  fd = events[ne].data.fd;

                if (fd == control_fd)
                {
                    char  cmd = 255;
                    int   ret;
                    D("gps control fd event");
                    do {
                        ret = read( fd, &cmd, 1 );
                    } while (ret < 0 && errno == EINTR);

                    if (cmd == CMD_QUIT) {
                        D("gps thread quitting on demand");
                        goto Exit;
                    }
                    else if (cmd == CMD_START) {
                        if (!started) {
                            D("gps thread starting  location_cb=%p",
state->callbacks.location_cb);
                            started = 1;
                            gps_report_status(state,
GPS_STATUS_ENGINE_ON);
                            nmea_reader_set_callback( reader, state-
>callbacks.location_cb,
                                        state-
>callbacks.sv_status_cb);
                        }
                    }
                    else if (cmd == CMD_STOP) {
                        if (started) {
                            D("gps thread stopping");
                            started = 0;
                            gps_report_status(state,
GPS_STATUS_ENGINE_OFF);
                            nmea_reader_set_callback( reader, NULL,
NULL );
                        }
                    }
                }
                else if (fd == gps_fd)
                {
                    char  buff[32];
                    D("gps fd event");
                    for (;;) {
                        int  nn, ret;

                        ret = read( fd, buff, sizeof(buff) );
                        if (ret < 0) {
                            if (errno == EINTR)
                                continue;
                            if (errno != EWOULDBLOCK)
                                LOGE("error while reading from gps
daemon socket: %s:", strerror(errno));
                            break;
                        }
                        D("received %d bytes: %.*s", ret, ret, buff);
                        for (nn = 0; nn < ret; nn++)
                            nmea_reader_addc( reader, buff[nn] );
                    }
                    D("gps fd event end");
                }
                else
                {
                    LOGE("epoll_wait() returned unkown fd %d ?", fd);
                }
            }
        }
    }
Exit:
    return;
}


static void
gps_state_init( GpsState*  state )
{
    state->init       = 1;
    state->control[0] = -1;
    state->control[1] = -1;
    state->fd         = -1;

#if 0
    state->fd = qemud_channel_open(QEMU_CHANNEL_NAME);

    if (state->fd < 0) {
        D("no gps emulation detected");
        return;
    }

    D("gps emulation will read from '%s' qemud channel",
QEMU_CHANNEL_NAME );
#else
    state->fd = hw_dev_open();

    if (state->fd < 0) {
        LOGE("could not open gps serial device: %s",
strerror(errno) );
        return;
    }

    D("gps open is OK");
#endif

    if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 )
{
        LOGE("could not create thread control socket pair: %s",
strerror(errno));
        goto Fail;
    }

    if ((state->thread = state->callbacks.create_thread_cb("GPS",
gps_state_thread,
                state)) == 0) {
//    if ( pthread_create( &state->thread, NULL, gps_state_thread,
state ) != 0 ) {
        LOGE("could not create gps thread: %s", strerror(errno));
        goto Fail;
    }

    D("gps state initialized");
    return;

Fail:
    gps_state_done( state );
}


/*****************************************************************/
/*****************************************************************/
/*****                                                       *****/
/*****       I N T E R F A C E                               *****/
/*****                                                       *****/
/*****************************************************************/
/*****************************************************************/


static int
gen_gps_init(GpsCallbacks* callbacks)
{
    D("%s\n", __FUNCTION__);
    GpsState*  s = _gps_state;

    s->callbacks = *callbacks;

    /* TODO:
    callbacks->set_capabilities_cb(GPS_CAPABILITY_SCHEDULING |
                                   GPS_CAPABILITY_SINGLE_SHOT);
        */

    if (!s->init)
        gps_state_init(s);

    if (s->fd < 0)
        return -1;

    return 0;
}

static void
gen_gps_cleanup(void)
{
    D("%s\n", __FUNCTION__);
    GpsState*  s = _gps_state;

    if (s->init)
        gps_state_done(s);
}


static int
gen_gps_start()
{
    D("%s\n", __FUNCTION__);
    GpsState*  s = _gps_state;

    if (!s->init) {
        D("%s: called with uninitialized state !!", __FUNCTION__);
        return -1;
    }

    hw_dev_power(1);

    D("%s: called", __FUNCTION__);
    gps_state_start(s);
    return 0;
}


static int
gen_gps_stop()
{
    D("%s\n", __FUNCTION__);
    GpsState*  s = _gps_state;

    if (!s->init) {
        D("%s: called with uninitialized state !!", __FUNCTION__);
        return -1;
    }

    hw_dev_power(0);

    D("%s: called", __FUNCTION__);
    gps_state_stop(s);
    return 0;
}


static int
gen_gps_inject_time(GpsUtcTime time, int64_t timeReference, int
uncertainty)
{
    D("%s\n", __FUNCTION__);
    return 0;
}

static int
gen_gps_inject_location(double latitude, double longitude, float
accuracy)
{
    D("%s\n", __FUNCTION__);
    return 0;
}

static void
gen_gps_delete_aiding_data(GpsAidingData flags)
{
    D("%s\n", __FUNCTION__);
}

static int gen_gps_set_position_mode(GpsPositionMode mode,
                          GpsPositionRecurrence recurrence,
                          uint32_t min_interval,
                          uint32_t preferred_accuracy,
                          uint32_t preferred_time)
{
    D("%s\n", __FUNCTION__);
    // FIXME - support fix_frequency
    return 0;
}

static const void*
gen_gps_get_extension(const char* name)
{
    D("%s\n", __FUNCTION__);
    // no extensions supported
    return NULL;
}

static const GpsInterface  genGpsInterface = {
    sizeof(GpsInterface),
    gen_gps_init,
    gen_gps_start,
    gen_gps_stop,
    gen_gps_cleanup,
    gen_gps_inject_time,
    gen_gps_inject_location,
    gen_gps_delete_aiding_data,
    gen_gps_set_position_mode,
    gen_gps_get_extension,
};

const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)
{
    D("%s\n", __FUNCTION__);
    return &genGpsInterface;
}

static int open_gps(const struct hw_module_t* module, char const*
name,
        struct hw_device_t** device)
{
    D("%s\n", __FUNCTION__);
    struct gps_device_t *dev = malloc(sizeof(struct gps_device_t));
    memset(dev, 0, sizeof(*dev));

    dev->common.tag = HARDWARE_DEVICE_TAG;
    dev->common.version = 0;
    dev->common.module = (struct hw_module_t*)module;
//    dev->common.close = (int (*)(struct hw_device_t*))close_lights;
    dev->get_gps_interface = gps__get_gps_interface;

    *device = (struct hw_device_t*)dev;
    return 0;
}


static struct hw_module_methods_t gps_module_methods = {
    .open = open_gps
};

const struct hw_module_t HAL_MODULE_INFO_SYM = {
    .tag = HARDWARE_MODULE_TAG,
    .version_major = 1,
    .version_minor = 0,
    .id = GPS_HARDWARE_MODULE_ID,
    .name = "Goldfish GPS Module",
    .author = "The Android Open Source Project",
    .methods = &gps_module_methods,
};
####build info
target thumb C: libgps <= sdk/emulator/gps/liansp-gps/gps-liansp.c
target SharedLib: libgps (out/target/product/smdkc110/obj/
SHARED_LIBRARIES/libgps_intermediates/LINKED/libgps.so)
target Non-prelinked: libgps (out/target/product/smdkc110/symbols/
system/lib/hw/libgps.so)
target Strip: libgps (out/target/product/smdkc110/obj/lib/libgps.so)
Install: out/target/product/smdkc110/system/lib/hw/libgps.so
#### after build
./out/target/product/smdkc110/symbols/system/lib/hw/libgps.so
./out/target/product/smdkc110/system/lib/hw/libgps.so
./out/target/product/smdkc110/obj/lib/libgps.so
./out/target/product/smdkc110/obj/SHARED_LIBRARIES/
libgps_intermediates/LINKED/libgps.so
####the log while using YGPS to test
I/ActivityManager(   75): Starting: Intent
{ act=android.intent.action.MAIN
cat=[android.intent.category.LAUNCHER] flg=0x10200000
cmp=com.yunnanexplorer.android.ygps/.YGPS bnds=[262,149][391,260] }
from pid 156
I/ActivityManager(   75): Start proc com.yunnanexplorer.android.ygps
for activity com.yunnanexplorer.android.ygps/.YGPS: pid=4555 uid=10040
gids={1015}
V/RenderScript_jni(  156): surfaceDestroyed
D/AndroidRuntime( 4555): Shutting down VM
W/dalvikvm( 4555): threadid=1: thread exiting with uncaught exception
(group=0x40015560)
E/AndroidRuntime( 4555): FATAL EXCEPTION: main
E/AndroidRuntime( 4555): java.lang.RuntimeException: Unable to start
activity ComponentInfo{com.yunnanexplorer.android.ygps/
com.yunnanexplorer.android.ygps.YGPS}:
java.lang.IllegalArgumentException: provider=gps
E/AndroidRuntime( 4555):        at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:
1622)
E/AndroidRuntime( 4555):        at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:
1638)
E/AndroidRuntime( 4555):        at android.app.ActivityThread.access
$1500(ActivityThread.java:117)
E/AndroidRuntime( 4555):        at android.app.ActivityThread
$H.handleMessage(ActivityThread.java:928)
E/AndroidRuntime( 4555):        at
android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 4555):        at android.os.Looper.loop(Looper.java:
123)
E/AndroidRuntime( 4555):        at
android.app.ActivityThread.main(ActivityThread.java:3647)
E/AndroidRuntime( 4555):        at
java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 4555):        at
java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 4555):        at com.android.internal.os.ZygoteInit
$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 4555):        at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 4555):        at
dalvik.system.NativeStart.main(Native
Method)
E/AndroidRuntime( 4555): Caused by:
java.lang.IllegalArgumentException: provider=gps
E/AndroidRuntime( 4555):        at
android.os.Parcel.readException(Parcel.java:1326)
E/AndroidRuntime( 4555):        at
android.os.Parcel.readException(Parcel.java:1276)
E/AndroidRuntime( 4555):        at android.location.ILocationManager
$Stub
$Proxy.requestLocationUpdates(ILocationManager.java:646)
E/AndroidRuntime( 4555):        at
android.location.LocationManager._requestLocationUpdates(LocationManager.java:
582)
E/AndroidRuntime( 4555):        at
android.location.LocationManager.requestLocationUpdates(LocationManager.java:
446)
E/AndroidRuntime( 4555):        at
com.yunnanexplorer.android.ygps.YGPS.onCreate(YGPS.java:72)
E/AndroidRuntime( 4555):        at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:
1047)
E/AndroidRuntime( 4555):        at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:
1586)
E/AndroidRuntime( 4555):        ... 11 more
W/ActivityManager(   75):   Force finishing activity
com.yunnanexplorer.android.ygps/.YGPS
W/ActivityManager(   75): Activity pause timeout for
HistoryRecord{40676e38 com.yunnanexplorer.android.ygps/.YGPS}
V/RenderScript_jni(  156): surfaceCreated
V/RenderScript_jni(  156): surfaceChanged
D/dalvikvm(   75): GC_CONCURRENT freed 1474K, 50% free 4356K/8647K,
external 4183K/4730K, paused 3ms+4ms

W/ActivityManager(   75): Activity destroy timeout for
HistoryRecord{40676e38 com.yunnanexplorer.android.ygps/.YGPS}


On Jul 27, 10:07 pm, hedwin <[email protected]> wrote:
> what about a gps usb device.
>
> On Wed, Jul 27, 2011 at 1:12 PM, venkat k raju <[email protected]> wrote:
>
> > HI all,
>
> > any one please suggest me how to integrate GPS on beagleboard with
> > Gingerbread.
>
> > thanks in advance.
>
> > --
> > thanks&Regards
> > k.v.raju
>
> > --
> > unsubscribe: [email protected]
> > website:http://groups.google.com/group/android-porting
>
>

-- 
unsubscribe: [email protected]
website: http://groups.google.com/group/android-porting

Reply via email to