/************************************************************************************
* 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;
}