I.MX6 GPS JNI HAL register init hacking

/************************************************************************************               
 *               I.MX6 GPS JNI HAL register init hacking                                            
 * 声明:                                                                                        
 *     1. 本文主要是对Atheros GPS JNI、HAL层的代码进行初略的跟踪,主要想知道GPS设备
 * 在这两层是如何注册、数据解析,目前还没分析Framework层进行分析。       
 *     2. 由于采用vim编辑文档,且分析文档的宽度超过博客园的文本宽度,如果想要阅读,
 * 尽量cp到自己文档里面,宽度足够,用vim进行阅读比较方便。
 *     3. 不要在本博客上直接阅读,请采纳2中的意见。
 *                                                                                                  
 *                                   2015-11-3 深圳 阴 南山平山村 曾剑锋                 
 ***********************************************************************************/               
                                                                                                    
                    \\\\\\\\\\\\-*- 目录 -*-/////////////                                         
                    |  一、参考文章:                                                        
                    |  二、JNI、HAL函数注册:                                               
                    |  三、Atheros GPS HAL初始化流程:                                      
                    ------------------------------------                                            
                                                                                                    
一、参考文章:                                                                               
    GPS 研究二 (Android 2.3__gingerbread)                                                    
        http://blog.chinaunix.net/uid-25570748-id-184090.html                                       
    android GPS HAL 回调函数实现                                                              
        http://www.xuebuyuan.com/967335.html                                                        
                                                                                                    
二、JNI、HAL函数注册:                                                                      
    cat /home/myzr/myandroid/frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp
        ...                                                                                         
        static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
            int err;                                                                                
            hw_module_t* module;                                                                    
                                                                                                    
            method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");       
            method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");                  
            method_reportSvStatus = env->GetMethodID(clazz, "reportSvStatus", "()V");               
            method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(III)V");        
            method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(J)V");                      
            method_setEngineCapabilities = env->GetMethodID(clazz, "setEngineCapabilities", "(I)V");
            method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");     
            method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",           
                    "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");            
            method_requestRefLocation = env->GetMethodID(clazz,"requestRefLocation","(I)V");        
            method_requestSetID = env->GetMethodID(clazz,"requestSetID","(I)V");                    
            method_requestUtcTime = env->GetMethodID(clazz,"requestUtcTime","()V");                 
                                                                                                    
            err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);              
            if (err == 0) {                                                                         
                hw_device_t* device;                     <----------------------------------------+ 
                err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);   --------+ | 
                if (err == 0) {                                                                 | | 
                    gps_device_t* gps_device = (gps_device_t *)device;                          | | 
                    sGpsInterface = gps_device->get_gps_interface(gps_device);          --------*-*-+
                }                                                                               | | |
            }                                                                                   | | |
            if (sGpsInterface) {                                                                | | |
                sGpsXtraInterface =                                                             | | |
                    (const GpsXtraInterface*)sGpsInterface->get_extension(GPS_XTRA_INTERFACE);  | | |
                sAGpsInterface =                                                                | | |
                    (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);         | | |
                sGpsNiInterface =                                                               | | |
                    (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);      | | |
                sGpsDebugInterface =                                                            | | |
                    (const GpsDebugInterface*)sGpsInterface->get_extension(GPS_DEBUG_INTERFACE);| | |
                sAGpsRilInterface =                                                             | | |
                    (const AGpsRilInterface*)sGpsInterface->get_extension(AGPS_RIL_INTERFACE);  | | |
            }                                                                      |            | | |
        }                                                                          +-------+    | | |
        ...                                                                                |    | | |
                                                                                           |    | | |
    cat /home/myzr/myandroid/hardware/imx/libgps/gps.c                                     |    | | |
        ...                                                                                |    | | |
        extern const GpsInterface* gps_get_hardware_interface();                ---------+ |    | | |
        const GpsInterface* gps__get_gps_interface(struct gps_device_t* dev)    <--------*-*----*-*-+
        {                                                                                | |    | | |
            return gps_get_hardware_interface();                                ---------+ |    | | |
                                                                                         | |    | | |
        }                                                                                | |    | | |
                                                                                         | |    | | |
        static int open_gps(const struct hw_module_t* module, char const* name, <---------------+ | |
                struct hw_device_t** device)                                             | |    | | |
        {                                                                                | |    | | |
            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->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                                      <------*---------------*-*----+   
        };                                                               |               | |        
                                                                         |               | |        
        struct hw_module_t HAL_MODULE_INFO_SYM = {                       |               | |        
            .tag = HARDWARE_MODULE_TAG,                                  |               | |        
            .version_major = 1,                                          |               | |        
            .version_minor = 0,                                          |               | |        
            .id = GPS_HARDWARE_MODULE_ID,                                |               | |        
            .name = "Atheros GPS Module",                                |               | |        
            .author = "FSL MAD, Inc.",                                   |               | |        
            .methods = &gps_module_methods,               ---------------+               | |        
        };                                                                               | |        
        ...                                                                              | |        
                                                                                         | |        
    cat /home/myzr/myandroid/hardware/imx/libgps/athr_gps.c                              | |        
        ...                                                                              | |        
        #ifdef ATHR_GPSNi                                                                | |        
        /*                                                                               | |        
         * Registers the callbacks for HAL to use                                        | |        
         */                                                                              | |        
        static void athr_gps_ni_init(GpsNiCallbacks* callbacks)                          | |        
        {                                                                                | |        
            GpsState*  s = _gps_state;                                                   | |        
                                                                                         | |        
            D("%s: entered", __FUNCTION__);                                              | |        
                                                                                         | |        
            if (callbacks)                                                               | |        
            {                                                                            | |        
                s->ni_init = 1;                                                          | |        
                s->ni_callbacks = *callbacks;                                            | |        
            }                                                                            | |        
        }                                                                                | |        
                                                                                         | |        
        /*                                                                               | |        
         * Sends a response to HAL                                                       | |        
         */                                                                              | |        
        static void athr_gps_ni_respond(int notif_id, GpsUserResponseType user_response) | |        
        {                                                                                | |        
            // D("%s: entered", __FUNCTION__);                                           | |        
        }                                                                                | |        
                                                                                         | |        
        static const GpsNiInterface athrGpsNiInterface = {                               | |        
            sizeof(GpsNiInterface),                                                      | |        
            athr_gps_ni_init,                                                            | |        
            athr_gps_ni_respond,                                                         | |        
        };                                                                               | |        
        #endif // ATHR_GPSNi                                                             | |        
                                                                                         | |        
                                                                                         | |        
        /**                                                                              | |        
          * 10-30 06:19:30.190: D/athr_gps(2570):                                        | |        
          *    athr_gps_get_extension: found xtra extension                              | |        
          * 10-30 06:19:30.190: D/athr_gps(2570):                                        | |        
          *    athr_gps_get_extension: no GPS extension for agps is found                | |        
          * 10-30 06:19:30.190: D/athr_gps(2570):                                        | |        
          *    athr_gps_get_extension: found ni extension                                | |        
          * 10-30 06:19:30.190: D/athr_gps(2570):                                        | |        
          *    athr_gps_get_extension: no GPS extension for gps-debug is found           | |        
          * 10-30 06:19:30.190: D/athr_gps(2570):                                        | |        
          *    athr_gps_get_extension: no GPS extension for agps_ril is foun             | |        
          */                                                                             | |        
        static const void* athr_gps_get_extension(const char* name)      <---------------*-+        
        {                                                                                | |        
            if (strcmp(name, GPS_XTRA_INTERFACE) == 0)                                   | |        
            {                                                                            | |        
        #ifdef ATHR_GPSXtra                                                              | |        
                D("%s: found xtra extension", __FUNCTION__);                             | |        
                return (&athrGpsXtraInterface);                                          | |        
        #endif // ATHR_GPSXtra                                                           | |        
            }                                                                            | |        
            else if (strcmp(name, GPS_NI_INTERFACE) == 0)                                | |        
            {                                                                            | |        
        #ifdef ATHR_GPSNi                                                                | |        
                D("%s: found ni extension", __FUNCTION__);                               | |        
                return (&athrGpsNiInterface);                                            | |        
        #endif // ATHR_GPSNi                                                             | |        
            }                                                                            | |        
            D("%s: no GPS extension for %s is found", __FUNCTION__, name);               | |        
            return NULL;                                                                 | |        
        }                                                                                | |        
                                                                                         | |        
        static const GpsInterface  athrGpsInterface = {      <----+                      | |        
            .size =sizeof(GpsInterface),                          |                      | |        
            .init = athr_gps_init,                                |                      | |        
            .start = athr_gps_start,                              |                      | |        
            .stop = athr_gps_stop,                                |                      | |        
            .cleanup = athr_gps_cleanup,                          |                      | |        
            .inject_time = athr_gps_inject_time,                  |                      | |        
            .inject_location = athr_gps_inject_location,          |                      | |        
            .delete_aiding_data = athr_gps_delete_aiding_data,    |                      | |        
            .set_position_mode = athr_gps_set_position_mode,      |                      | |        
            .get_extension = athr_gps_get_extension,              |                      | |        
        };                                                        |                      | |        
                                                                  |                      | |        
        const GpsInterface* gps_get_hardware_interface()          |  <-------------------+ |        
        {                                                         |                        |        
            return &athrGpsInterface;                        -----+                        |        
        }                                                                                  |        
        ...                                                                                |        
                                                                                           |        
                                                                                           |        
    cat /home/myzr/myandroid/hardware/libhardware/include/hardware/gps.h                   |        
        ...                                                                                |        
        /**                                                                                |        
         * Name for the GPS XTRA interface.                                                |        
         */                                                                                |        
        #define GPS_XTRA_INTERFACE      "gps-xtra"                                         |        
                                                                                           |        
        /**                                                                                |        
         * Name for the GPS DEBUG interface.                                               |        
         */                                                                                |        
        #define GPS_DEBUG_INTERFACE      "gps-debug"                                       |        
                                                                                           |        
        /**                                                                                |        
         * Name for the AGPS interface.                                                    |        
         */                                                                                |        
        #define AGPS_INTERFACE      "agps"                                                 |        
                                                                                           |        
        /**                                                                                |        
         * Name for NI interface                                                           |        
         */                                                                                |        
        #define GPS_NI_INTERFACE "gps-ni"                                                  |        
                                                                                           |        
        /**                                                                                |        
         * Name for the AGPS-RIL interface.                                                |        
         */                                                                                |        
        #define AGPS_RIL_INTERFACE      "agps_ril"                <------------------------+        
        ...                                                                                         
                                                                                                    
三、Atheros GPS HAL初始化流程:                                                             
    cat /home/myzr/myandroid/hardware/imx/libgps/athr_gps.c                                         
    ......                                                                                          
    typedef struct {                                                                                
        int     pos;                                                                                
        int     overflow;                                                                           
        int     utc_year;                                                                           
        int     utc_mon;                                                                            
        int     utc_day;                                                                            
        int     utc_diff;                                                                           
        GpsLocation  fix;                                                                           
        GpsSvStatus  sv_status;                                                                     
        int     sv_status_changed;                                                                  
        char    in[ NMEA_MAX_SIZE+1 ];                                                              
        int     gsa_fixed;                                                                          
        AthTimemap_t timemap;                                                                       
    } NmeaReader;                             <----+                                                
                                                   |                                                
    typedef struct {                               |                                                
        int                     init;              |                                                
        int                     fd;                |                                                
        GpsCallbacks            callbacks;         |     <--------+                                 
        pthread_t               thread;            |              |                                 
        pthread_t           nmea_thread;           |              |                                 
        pthread_t               tmr_thread;        |              |                                 
        int                     control[2];        |              |                                 
        int                     fix_freq;          |              |                                 
        sem_t                   fix_sem;           |              |                                 
        int                     first_fix;         |              |                                 
        NmeaReader              reader;      ------+              |                                 
    #ifdef ATHR_GPSXtra                                           |                                 
        int                     xtra_init;                        |                                 
        GpsXtraCallbacks        xtra_callbacks;                   |                                 
    #endif                                                        |                                 
    #ifdef ATHR_GPSNi                                             |                                 
        int                     ni_init;                          |                                 
        GpsNiCallbacks          ni_callbacks;                     |                                 
        GpsNiNotification       ni_notification;                  |                                 
    #endif                                                        |                                 
    } GpsState;              --------------------+                |                                 
    ......                                       |                |                                 
    static GpsState  _gps_state[1];          <---+  <-----------+ |                                 
    static GpsState *gps_state = _gps_state; <---+              | |                                 
    ......                                                      | |                                 
    GpsCallbacks* g_gpscallback = 0;    <-----------------------*-*-+                               
    ......                                                      | | |                               
                                                                | | |                               
    static const GpsInterface  athrGpsInterface = {             | | |                               
        .size =sizeof(GpsInterface),                            | | |                               
        .init = athr_gps_init,               -----------------+ | | |                               
        .start = athr_gps_start,                              | | | |                               
        .stop = athr_gps_stop,                                | | | |                               
        .cleanup = athr_gps_cleanup,                          | | | |                               
        .inject_time = athr_gps_inject_time,                  | | | |                               
        .inject_location = athr_gps_inject_location,          | | | |                               
        .delete_aiding_data = athr_gps_delete_aiding_data,    | | | |                               
        .set_position_mode = athr_gps_set_position_mode,      | | | |                               
        .get_extension = athr_gps_get_extension,              | | | |                               
    };                                                        | | | |                               
                                                              | | | |                               
    static int athr_gps_init(GpsCallbacks* callbacks)  <------+ | | |                               
    {                                                           | | |                               
        GpsState*  s = _gps_state;                 -------------+ | |                               
                                                                  | |                               
        D("gps state initializing %d",s->init);                   | |                               
                                                                  | |                               
        s->callbacks = *callbacks;       -------------------------+ |                               
        if (!s->init)                                               |                               
            gps_state_init(s);           ----------+                |                               
                                                   |                |                               
        if(!g_gpscallback)                         |                |                               
            g_gpscallback = callbacks;   ----------*----------------+                               
                                                   |                                                
        return 0;                                  |                                                
    }                                              |                                                
                                                   |                                                
    static void                                    |                                                
    gps_state_init( GpsState*  state )   <---------+                                                
    {                                                                                               
        ...                                                                                         
        if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 ) {                         
            ALOGE("could not create thread control socket pair: %s", strerror(errno));              
            goto Fail;                                                                              
        }                                                                                           
                                                                                                    
        state->thread = state->callbacks.create_thread_cb("athr_gps", gps_state_thread, state);     
            if (!state->thread)                                                 |                   
        {                                                                       |                   
            ALOGE("could not create gps thread: %s", strerror(errno));          |                   
            goto Fail;                                                          |                   
        }                                                                       |                   
            state->callbacks.set_capabilities_cb(GPS_CAPABILITY_SCHEDULING);    |                   
        D("gps state initialized");                                             |                   
        ...                                                                     |                   
    }                                                                           |                   
                                                                                |                   
    static void                                         <-----------------------+                   
    gps_state_thread( void*  arg )                                                                  
    {                                                                                               
        ...                                                                                         
        state->tmr_thread = state->callbacks.create_thread_cb("athr_gps_tmr", gps_timer_thread, state);
        if (!state->tmr_thread)                                                      |              
        {                                                                            |              
            ALOGE("could not create gps timer thread: %s", strerror(errno));         |              
            started = 0;                                                             +--------------+
            state->init = STATE_INIT;                                                               |
            goto Exit;                                                                              |
        }                                                                                           |
                                                                                                    |
        state->nmea_thread = state->callbacks.create_thread_cb("athr_nmea_thread", gps_nmea_thread, |
            state);                                                                      |          |
        if (!state->nmea_thread)                                                         |          |
        {                                                                                |          |
            ALOGE("could not create gps nmea thread: %s", strerror(errno));              |          |
            started = 0;                                                                 |          |
            state->init = STATE_INIT;                                                    |          |
            goto Exit;                                                                   |          |
        }                                                                                |          |
        ...                                                                              |          |
    }                                                                                    |          |
                                                                                         |          |
    static void                                                                          |          |
    gps_nmea_thread( void*  arg )                                      <-----------------+          |
    {                                                                                               |
        GpsState *state = (GpsState *)arg;              <----+                                      |
        NmeaReader  *reader;                   -----+        |                                      |
        reader = &state->reader;               -----+   -----+                                      |
                                                    |                                               |
        DFR("gps entered nmea thread");             |                                               |
        int versioncnt = 0;                         |                                               |
                                                    |                                               |
        // now loop                                 +------------+                                  |
        while (continue_thread)                                  |                                  |
        {                                                        |                                  |
                                                                 |                                  |
            if (FD_ISSET(state->fd, &readfds))                   |                                  |
            {                                                    |                                  |
                memset(buf,0,sizeof(buf));                       |                                  |
                ret = read( state->fd, buf, sizeof(buf) );       |                                  |
                if (ret > 0)                                     |                                  |
                {                                                |                                  |
                    if (strstr(buf, "CFG_R"))                    |                                  |
                    {                                            |                                  |
                        ALOGI("ver %s",buf);                     |                                  |
                    }                                            |                                  |
                                                                 |                                  |
                    for (nn = 0; nn < ret; nn++)                 |                                  |
                        nmea_reader_addc( reader, buf[nn] ); <---+       -----------+               |
                                                                                    |               |
                    /* ATHR in/out sentences*/                                      |               |
                    if ((buf[0] == 'O') && (buf[1] == 'A') && (buf[2] == 'P')) {    |               |
                        D("OAP200 sentences found");                                |               |
                        athr_reader_parse(buf, ret);                                |               |
                        /*                                                          |               |
                        for (nn = 0; nn < ret; nn++)                                |               |
                            D("%.2x ", buf[nn]);                                    |               |
                        */                                                          |               |
                    }else if ((buf[0] == '#') && (buf[1] == '!') && \               |               |
                              (buf[2] == 'G') && (buf[3] == 'S') && \               |               |
                              (buf[4] == 'M') && (buf[5] == 'A')) {                 |               |
                        D("GSMA sentences found");                                  |               |
                        athr_reader_parse(buf, ret);                                |               |
                    }                                                               |               |
                }                                                                   |               |
                else                                                                |               |
                {                                                                   |               |
                    DFR("Error on NMEA read :%s",strerror(errno));                  |               |
                    gps_closetty(state);                                            |               |
                    GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_END);        |               |
                    sleep(3); //wait Orion shutdown.                                |               |
                    bOrionShutdown = 1;                                             |               |
                    continue;                                                       |               |
                }                                                                   |               |
            }                                                                       |               |
                                                                                    |               |
            if(!continue_thread)                                                    |               |
                break;                                                              |               |
        }                                                                           |               |
    Exit:                                                                           |               |
        DFR("gps nmea thread destroyed");                                           |               |
        return;                                                                     |               |
    }                                                                               |               |
                                                                                    |               |
    static void                                                                     |               |
    nmea_reader_addc( NmeaReader*  r, int  c )                 <--------------------+               |
    {                                                                                               |
        int cnt;                                                                                    |
                                                                                                    |
        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') {                                                                            |
            gps_state_lock_fix(gps_state);                                                          |
            nmea_reader_parse( r );            --------+                                            |
            gps_state_unlock_fix(gps_state);           |                                            |
            r->pos = 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;                                                                         |
                                                                                                    |
        if (r->pos < 9) {                                                                           |
             return;                                                                                |
        }                                                                                           |
                                                                                                    |
        if (gps_state->callbacks.nmea_cb) {                                                         |
            struct timeval tv;                                                                      |
            unsigned long long mytimems;                                                            |
            gettimeofday(&tv,NULL);                                                                 |
            mytimems = tv.tv_sec * 1000 + tv.tv_usec / 1000;                                        |
            gps_state->callbacks.nmea_cb(mytimems, r->in, r->pos);                                  |
        }                                                                                           |
                                                                                                    |
        nmea_tokenizer_init(tzer, r->in, r->in + r->pos);                                           |
    #ifdef GPS_DEBUG_TOKEN                                                                          |
        {                                                                                           |
            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) {                                                                  |
            /* for $PUNV sentences */                                                               |
            if ( !memcmp(tok.p, "PUNV", 4) ) {                                                      |
                Token tok_cfg = nmea_tokenizer_get(tzer,1);                                         |
                                                                                                    |
                if (!memcmp(tok_cfg.p, "CFG_R", 5)) {                                               |
                } else if ( !memcmp(tok_cfg.p, "QUAL", 4) ) {                                       |
                    Token  tok_sigma_x   = nmea_tokenizer_get(tzer, 3);                             |
                                                                                                    |
                    if (tok_sigma_x.p[0] != ',') {                                                  |
                        Token tok_accuracy      = nmea_tokenizer_get(tzer, 10);                     |
                        nmea_reader_update_accuracy(r, tok_accuracy);                               |
                    }                                                                               |
                } else if (!memcmp(tok_cfg.p, "TIMEMAP", 7))                                        |
                {                                                                                   |
                    Token systime = nmea_tokenizer_get(tzer, 8); // system time token               |
                    Token timestamp = nmea_tokenizer_get(tzer, 2); // UTC time token                |
                    nmea_reader_update_timemap(r, systime, timestamp);                              |
                }                                                                                   |
            }else{                                                                                  |
            }                                                                                       |
            return;                                                                                 |
        }                                                                                           |
                                                                                                    |
        if ( !memcmp(tok.p, "GPG", 3) ) //GPGSA,GPGGA,GPGSV                                         |
            bGetFormalNMEA = 1;                                                                     |
        // ignore first two characters.                                                             |
        tok.p += 2;                                                                                 |
                                                                                                    |
        if ( !memcmp(tok.p, "GGA", 3) ) {                                                           |
            // GPS fix                                                                              |
            Token  tok_fixstaus      = nmea_tokenizer_get(tzer,6);                                  |
                                                                                                    |
            if (tok_fixstaus.p[0] > '0') {                                                          |
                                                                                                    |
              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, "GLL", 3) ) {                                                    |
                                                                                                    |
            Token  tok_fixstaus      = nmea_tokenizer_get(tzer,6);                                  |
                                                                                                    |
           if (tok_fixstaus.p[0] == 'A') {                                                          |
                                                                                                    |
              Token  tok_latitude      = nmea_tokenizer_get(tzer,1);                                |
              Token  tok_latitudeHemi  = nmea_tokenizer_get(tzer,2);                                |
              Token  tok_longitude     = nmea_tokenizer_get(tzer,3);                                |
              Token  tok_longitudeHemi = nmea_tokenizer_get(tzer,4);                                |
              Token  tok_time          = nmea_tokenizer_get(tzer,5);                                |
                                                                                                    |
              nmea_reader_update_time(r, tok_time);                                                 |
              nmea_reader_update_latlong(r, tok_latitude,                                           |
                                            tok_latitudeHemi.p[0],                                  |
                                            tok_longitude,                                          |
                                            tok_longitudeHemi.p[0]);                                |
            }                                                                                       |
        } else if ( !memcmp(tok.p, "GSA", 3) ) {                                                    |
                                                                                                    |
            Token  tok_fixStatus   = nmea_tokenizer_get(tzer, 2);                                   |
            int i;                                                                                  |
                                                                                                    |
            if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') {                          |
                                                                                                    |
              r->sv_status.used_in_fix_mask = 0ul;                                                  |
                                                                                                    |
              for (i = 3; i <= 14; ++i){                                                            |
                                                                                                    |
                Token  tok_prn  = nmea_tokenizer_get(tzer, i);                                      |
                int prn = str2int(tok_prn.p, tok_prn.end);                                          |
                                                                                                    |
               /* only available for PRN 1-32 */                                                    |
                if ((prn > 0) && (prn < 33)){                                                       |
                  r->sv_status.used_in_fix_mask |= (1ul << (prn-1));                                |
                  r->sv_status_changed = 1;                                                         |
                  /* mark this parameter to identify the GSA is in fixed state */                   |
                  r->gsa_fixed = 1;                                                                 |
                }                                                                                   |
              }                                                                                     |
                                                                                                    |
            }else {                                                                                 |
              if (r->gsa_fixed == 1) {                                                              |
                r->sv_status.used_in_fix_mask = 0ul;                                                |
                r->sv_status_changed = 1;                                                           |
                r->gsa_fixed = 0;                                                                   |
              }                                                                                     |
            }                                                                                       |
            D("%s","zengjf GSA");                                                                   |
        } 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_changed = 0;                                                         |
                  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);                          |
                                                                                                    |
                     r->sv_status.sv_list[curr].prn = str2int(tok_prn.p, tok_prn.end);              |
                     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 = str2float(tok_snr.p, tok_snr.end);            |
                                                                                                    |
                     r->sv_status.num_svs += 1;                                                     |
                                                                                                    |
                     curr += 1;                                                                     |
                                                                                                    |
                     i += 1;                                                                        |
              }                                                                                     |
                                                                                                    |
              if (sentence == totalSentences) {                                                     |
                  r->sv_status_changed = 1;                                                         |
              }                                                                                     |
            }                                                                                       |
                                                                                                    |
        } else if ( !memcmp(tok.p, "RMC", 3) )                                                      |
                                                                                                    |
            Token  tok_fixStatus     = nmea_tokenizer_get(tzer,2);                                  |
                                                                                                    |
            if (tok_fixStatus.p[0] == 'A')                                                          |
            {                                                                                       |
              Token  tok_time          = nmea_tokenizer_get(tzer,1);                                |
              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);                                |
                                                                                                    |
                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 );                                         |
            }                                                                                       |
            D("%s","zengjf RMC");                                                                   |
                                                                                                    |
        } else if ( !memcmp(tok.p, "VTG", 3) ) {                                                    |
                                                                                                    |
            Token  tok_fixStatus     = nmea_tokenizer_get(tzer,9);                                  |
                                                                                                    |
            if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != 'N')                            |
            {                                                                                       |
                Token  tok_bearing       = nmea_tokenizer_get(tzer,1);                              |
                Token  tok_speed         = nmea_tokenizer_get(tzer,5);                              |
                                                                                                    |
                nmea_reader_update_bearing( r, tok_bearing );                                       |
                nmea_reader_update_speed  ( r, tok_speed );                                         |
            }                                                                                       |
                                                                                                    |
        } else if ( !memcmp(tok.p, "ZDA", 3) ) {                                                    |
                                                                                                    |
            Token  tok_time;                                                                        |
            Token  tok_year  = nmea_tokenizer_get(tzer,4);                                          |
                                                                                                    |
            if (tok_year.p[0] != '\0') {                                                            |
                                                                                                    |
              Token  tok_day   = nmea_tokenizer_get(tzer,2);                                        |
              Token  tok_mon   = nmea_tokenizer_get(tzer,3);                                        |
                                                                                                    |
              nmea_reader_update_cdate( r, tok_day, tok_mon, tok_year );                            |
                                                                                                    |
            }                                                                                       |
                                                                                                    |
            tok_time  = nmea_tokenizer_get(tzer,1);                                                 |
                                                                                                    |
            if (tok_time.p[0] != '\0') {                                                            |
                                                                                                    |
              nmea_reader_update_time(r, tok_time);                                                 |
                                                                                                    |
            }                                                                                       |
                                                                                                    |
                                                                                                    |
        } else {                                                                                    |
            tok.p -= 2;                                                                             |
        }                                                                                           |
                                                                                                    |
        if (!gps_state->first_fix &&                                                                |
            gps_state->init == STATE_INIT &&                                                        |
            r->fix.flags & GPS_LOCATION_HAS_LAT_LONG) {                                             |
                                                                                                    |
            ath_send_ni_notification(r);                                                            |
                                                                                                    |
            if (gps_state->callbacks.location_cb) {                                                 |
                gps_state->callbacks.location_cb( &r->fix );                                        |
                r->fix.flags = 0;                                                                   |
            }                                                                                       |
                                                                                                    |
            gps_state->first_fix = 1;                                                               |
        }                                                                                           |
    }                                                                                               |
                                                                                                    |
    static void                                                                                     |
    gps_timer_thread( void*  arg )                               <----------------------------------+
    {                                                                                               
        int need_sleep = 0;                                                                         
        int sleep_val = 0;                                                                          
                                                                                                    
      GpsState *state = (GpsState *)arg;                                                            
                                                                                                    
      DFR("gps entered timer thread");                                                              
                                                                                                    
      do {                                                                                          
                                                                                                    
        while(started != 1 && continue_thread) //                                                   
        {                                                                                           
            usleep(500*1000);                                                                       
        }                                                                                           
                                                                                                    
        gps_state_lock_fix(state);                                                                  
                                                                                                    
        if ((state->reader.fix.flags & GPS_LOCATION_HAS_LAT_LONG) != 0) {                           
                                                                                                    
          //D("gps fix cb: 0x%x", state->reader.fix.flags);                                         
                                                                                                    
          if (state->callbacks.location_cb) {                                                       
              state->callbacks.location_cb( &state->reader.fix );                                   
              state->reader.fix.flags = 0;                                                          
              state->first_fix = 1;                                                                 
          }                                                                                         
                                                                                                    
          if (state->fix_freq == 0) {                                                               
            state->fix_freq = -1;                                                                   
          }                                                                                         
        }                                                                                           
                                                                                                    
        if (state->reader.sv_status_changed != 0) {                                                 
                                                                                                    
          // D("gps sv status callback");                                                           
                                                                                                    
          if (state->callbacks.sv_status_cb) {                                                      
              state->callbacks.sv_status_cb( &state->reader.sv_status );                            
              state->reader.sv_status_changed = 0;                                                  
          }                                                                                         
                                                                                                    
        }                                                                                           
                                                                                                    
        need_sleep = (state->fix_freq != -1 && (state->init != STATE_QUIT) ? 1 : 0)     ;           
        sleep_val = state->fix_freq;                                                                
                                                                                                    
        gps_state_unlock_fix(state);                                                                
                                                                                                    
        if (need_sleep) {                                                                           
            sleep(sleep_val);                                                                       
        } else {                                                                                    
            D("won't sleep because fix_freq=%d state->init=%d",state->fix_freq, sta     te->init);  
        }                                                                                           
        ath_send_ni_notification(&state->reader);                                                   
        if( state->init == STATE_INIT && lastcmd == CMD_STOP && started == 1)                       
        {                                                                                           
            int gap = 0;                                                                            
            D("Wait for NMEA coming,%d,%d,%d", state->init , lastcmd, started);                     
                                                                                                    
            while (state->init != STATE_START && bGetFormalNMEA == 0 && continue_th     read && !bOrionShutdown)
            {                                                                                       
                usleep(300*1000);                                                                   
                if (++gap > 100)                                                                    
                    break;                                                                          
            } ;                                                                                     
                                                                                                    
            D("Get NMEA %d and state %d",bGetFormalNMEA,state->init);                               
            // even we don't get nmea after 30 second, still force close it                         
            bGetFormalNMEA |= (gap >= 100);                                                         
                                                                                                    
            if( state->init == STATE_INIT && lastcmd == CMD_STOP && started == 1)                   
            {                                                                                       
                gps_sleep(state);                                                                   
            }                                                                                       
            else                                                                                    
            {                                                                                       
                D("User enter LM before sending sleep, so drop it");                                
            }                                                                                       
        }                                                                                           
                                                                                                    
      } while(continue_thread);                                                                     
                                                                                                    
                                                                                                    
      DFR("gps timer thread destroyed");                                                            
                                                                                                    
      return;                                                                                       
                                                                                                    
    }                                                                                               
                                                                                                    

 

posted on 2015-11-03 10:58  zengjf  阅读(405)  评论(0编辑  收藏  举报

导航