3110 lines
78 KiB
C
Executable File
3110 lines
78 KiB
C
Executable File
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <termios.h>
|
|
#include <fcntl.h>
|
|
#include <sys/epoll.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <semaphore.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <strings.h>
|
|
#include <cutils/sockets.h>
|
|
#include <cutils/properties.h>
|
|
#include <hardware/gps.h>
|
|
#include <dirent.h>
|
|
#include <sys/stat.h>
|
|
|
|
//#include <sys/socket.h>
|
|
//#include <arpa/inet.h>
|
|
//#include <netinet/in.h>
|
|
//#include <netdb.h>
|
|
|
|
#include "tdgnss.h"
|
|
#include "sdbp.h"
|
|
#include "update.h"
|
|
#include "agps.h"
|
|
#include "serial.h"
|
|
|
|
int agps_thread_go=0;
|
|
static struct configfile_item item_list[TD_CONFIGFILE_NUM];
|
|
|
|
unsigned char chip_standby[9]={0x23,0x3E,0x02,0x04,0x01,0x00,0x01,0x08,0x1E};
|
|
unsigned char fix_dop100[15]={0x23,0x3E,0x03,0x34,0x07,0x00,0x64,0x64,0x10,0x27,0x10,0x27,0x01,0x75,0xE7};
|
|
unsigned char gnssmode_bds[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x31,0x2C,0x30,0x2A,0x34,0x39,0x0D,0x0A};
|
|
unsigned char gnssmode_gps[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x32,0x2C,0x30,0x2A,0x34,0x41,0x0D,0x0A};
|
|
unsigned char gnssmode_gps_bds[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x33,0x2C,0x30,0x2A,0x34,0x42,0x0D,0x0A};
|
|
unsigned char gnssmode_gl[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x34,0x2C,0x30,0x2A,0x34,0x43,0x0D,0x0A};
|
|
unsigned char gnssmode_bds_gl[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x35,0x2C,0x30,0x2A,0x34,0x44,0x0D,0x0A};
|
|
unsigned char gnssmode_gps_gl[15]={0x24,0x43,0x43,0x53,0x49,0x52,0x2C,0x36,0x2C,0x30,0x2A,0x34,0x45,0x0D,0x0A};
|
|
unsigned char cold_start1[9]={0x23,0x3E,0x02,0x01,0x01,0x00,0x01,0x05,0x12};
|
|
unsigned char cold_start2[10]={0x23,0x3E,0x02,0x01,0x02,0x00,0x01,0x00,0x06,0x1B};
|
|
|
|
unsigned char get_version[8]={0x23,0x3E,0x05,0x01,0x00,0x00,0x06,0x17};
|
|
|
|
unsigned char baud9600[14]={0x23,0x3E,0x03,0x21,0x06,0x00,0x01,0x02,0x00,0x00,0x00,0x01,0x2E,0x88};
|
|
unsigned char baud19200[14]={0x23,0x3E,0x03,0x21,0x06,0x00,0x01,0x03,0x00,0x00,0x00,0x01,0x2F,0x8D};
|
|
unsigned char baud38400[14]={0x23,0x3E,0x03,0x21,0x06,0x00,0x01,0x04,0x00,0x00,0x00,0x01,0x30,0x92};
|
|
unsigned char baud57600[14]={0x23,0x3E,0x03,0x21,0x06,0x00,0x01,0x05,0x00,0x00,0x00,0x01,0x31,0x97};
|
|
unsigned char baud115200[14]={0x23,0x3E,0x03,0x21,0x06,0x00,0x01,0x06,0x00,0x00,0x00,0x01,0x32,0x9C};
|
|
|
|
unsigned int fixed[256];
|
|
|
|
enum nmea_state nmeastate;
|
|
extern TD_INFO td_agps_info;
|
|
|
|
TD1030Config tdconfig;
|
|
TDMODE td_mode = {0,0,0,0};
|
|
typedef struct
|
|
{
|
|
const char *p;
|
|
const char *end;
|
|
} Token;
|
|
|
|
|
|
#define CMD_MAX_LEN 4096
|
|
static char cmd_buff[CMD_MAX_LEN] = {0};
|
|
static int cmd_length = 0;
|
|
|
|
#define MAX_NMEA_TOKENS 32
|
|
|
|
typedef struct
|
|
{
|
|
int count;
|
|
Token tokens[ MAX_NMEA_TOKENS ];
|
|
} NmeaTokenizer;
|
|
|
|
static char *GetItemValue(char *name);
|
|
static char *remove_cr_lf(char *buf, char ch);
|
|
static int set_itemvalue(char *name, char *value);
|
|
static void intercept(char *line);
|
|
static int load_properties(const char *path);
|
|
static void LoadDriverPath(void);
|
|
static void LoadUartBaudRate(void);
|
|
static void LoadBeiDouPrnAdd(void);
|
|
static void FreeItemList(void);
|
|
static int LoadConfigFile(void);
|
|
|
|
void update_nmea(const char *p, const char *end );
|
|
void PowerOn(void);
|
|
void PowerOff(void);
|
|
int UartTxData(unsigned char *buffer, int length);
|
|
|
|
void update_gps_location(GpsLocation *location);
|
|
void update_gps_status(GpsStatusValue value);
|
|
void update_gps_svstatus(GpsSvStatus *svstatus);
|
|
static int _LibNMEA_Xor(char *p_chk_str);
|
|
static int td_set_update_mode(void);
|
|
|
|
int update_mode = 0;
|
|
struct __GSAPRN
|
|
{
|
|
int fixprnnum;
|
|
int fixprn[GPS_MAX_SVS];
|
|
// unsigned char fixprnflag;
|
|
} GsaPrn;
|
|
struct supl_agps_data td_agps_data;
|
|
|
|
GpsState _gps_state[1];
|
|
|
|
|
|
static char *GetItemValue(char *name)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < TD_CONFIGFILE_NUM; i++)
|
|
{
|
|
if (!item_list[i].name)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (strcmp(item_list[i].name, name) == 0)
|
|
{
|
|
return item_list[i].value;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
static char *remove_cr_lf(char *buf, char ch)
|
|
{
|
|
int len = strlen(buf);
|
|
int i;
|
|
|
|
if (len == 0)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for (i = len - 1; i >= 0; i--)
|
|
{
|
|
if (buf[i] == ch)
|
|
{
|
|
return &buf[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int set_itemvalue(char *name, char *value)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < TD_CONFIGFILE_NUM; i++)
|
|
{
|
|
char *n, *v;
|
|
|
|
if (item_list[i].name && strcmp(item_list[i].name, name))
|
|
continue;
|
|
|
|
if (item_list[i].name == NULL)
|
|
{
|
|
n = malloc(strlen(name) + 1);
|
|
|
|
if (!n)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
memset(n, 0x00, strlen(name) + 1);
|
|
|
|
v = malloc(strlen(value) + 1);
|
|
|
|
if (!v)
|
|
{
|
|
free(n);
|
|
return -1;
|
|
}
|
|
|
|
memset(v, 0x00, strlen(value) + 1);
|
|
|
|
strcpy(n, name);
|
|
}
|
|
else
|
|
{
|
|
n = item_list[i].name;
|
|
v = item_list[i].value;
|
|
|
|
if (strlen(v) < strlen(value))
|
|
{
|
|
v = malloc(strlen(value) + 1);
|
|
|
|
if (!v)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
memset(v, 0x00, strlen(value) + 1);
|
|
|
|
free(item_list[i].value);
|
|
}
|
|
}
|
|
|
|
strcpy(v, value);
|
|
|
|
item_list[i].name = n;
|
|
item_list[i].value = v;
|
|
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void intercept(char *line)
|
|
{
|
|
char *buf = line;
|
|
char *name, *value;
|
|
|
|
if (line[0] == '#')
|
|
return;
|
|
|
|
name = strsep(&buf, "=");
|
|
value = strsep(&buf, "=");
|
|
|
|
set_itemvalue(name, value);
|
|
|
|
return ;
|
|
}
|
|
|
|
static int load_default_properties()
|
|
{
|
|
D("%s", __FUNCTION__);
|
|
strcat(tdconfig.strconfigfile.uartpath, DEFAULT_UART_DRIVER);
|
|
D("%s",tdconfig.strconfigfile.uartpath);
|
|
tdconfig.bdprnaddr = DEFAULT_BDPRNADD;
|
|
tdconfig.uartboadrate = DEFAULT_UART_BAUD_RATE;
|
|
tdconfig.gnss_mode = DEFAULT_GNSS_MODE;
|
|
tdconfig.fast_fix = 0;
|
|
tdconfig.agnss_enable = 0;
|
|
tdconfig.debugmask = 0x60;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
static int load_properties(const char *path)
|
|
{
|
|
char line[256];
|
|
FILE *fp;
|
|
int i = 0;
|
|
|
|
fp = fopen(path, "r");
|
|
|
|
if (!fp)
|
|
{
|
|
D("%s: can not to open %s (%d)\n", __FUNCTION__, path, errno);
|
|
return -1;
|
|
}
|
|
|
|
while (fgets(line, sizeof(line), fp))
|
|
{
|
|
i++;
|
|
char *nl;
|
|
if((line[0] == 0)||(line[0]==0xa)||(line[0]==' '))
|
|
break;
|
|
while ((nl = remove_cr_lf(line, '\n')) || (nl = remove_cr_lf(line, '\r')) )
|
|
{
|
|
*nl = '\0';
|
|
}
|
|
|
|
if (GetDebugMaskBit(D_CONFIGFILE) == 1)
|
|
{
|
|
D("%s: item open %s \n", __FUNCTION__, line);
|
|
}
|
|
intercept(line);
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|
|
static void LoadDriverPath(void)
|
|
{
|
|
char *uartpath = GetItemValue("UART_DRIVER");
|
|
|
|
if (!uartpath)
|
|
{
|
|
D("Uart Path is NULL!");
|
|
}else{
|
|
memset(tdconfig.strconfigfile.uartpath,0,sizeof(tdconfig.strconfigfile.uartpath));
|
|
strcpy(tdconfig.strconfigfile.uartpath, uartpath);
|
|
D("Uart Path : %s", tdconfig.strconfigfile.uartpath);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void LoadUartBaudRate(void)
|
|
{
|
|
char *baudrate = GetItemValue("UART_BAUD_RATE");
|
|
int selectbaudrate = 0;
|
|
|
|
if (baudrate)
|
|
{
|
|
selectbaudrate = atoi(baudrate);
|
|
}
|
|
else
|
|
{
|
|
selectbaudrate = DEFAULT_UART_BAUD_RATE;
|
|
}
|
|
|
|
|
|
if((selectbaudrate != 9600) && (selectbaudrate != 115200) && (selectbaudrate != 19200) && (selectbaudrate != 38400) && (selectbaudrate != 57600))
|
|
{
|
|
|
|
selectbaudrate = DEFAULT_UART_BAUD_RATE;
|
|
}
|
|
|
|
tdconfig.uartboadrate = selectbaudrate;
|
|
if (GetDebugMaskBit(D_CONFIGFILE) == 1)
|
|
{
|
|
D("Uart Baudrate : %d", selectbaudrate);
|
|
}
|
|
|
|
|
|
return;
|
|
}
|
|
static void LoadBeiDouPrnAdd(void)
|
|
{
|
|
char *beidouprn = GetItemValue("BDPRNADD");
|
|
int bdprnaddr = 0;
|
|
|
|
if (beidouprn)
|
|
{
|
|
bdprnaddr = atoi(beidouprn);
|
|
}
|
|
else
|
|
{
|
|
bdprnaddr = DEFAULT_BDPRNADD;
|
|
}
|
|
|
|
if(bdprnaddr <= 0)
|
|
bdprnaddr = DEFAULT_BDPRNADD;
|
|
|
|
tdconfig.bdprnaddr = bdprnaddr;
|
|
|
|
return;
|
|
}
|
|
static void LoadGnssMode(void)
|
|
{
|
|
char *p_ch = GetItemValue("GNSS_MODE");
|
|
int mode = 3;
|
|
|
|
if (p_ch)
|
|
{
|
|
mode = atoi(p_ch);
|
|
}
|
|
else
|
|
{
|
|
mode = DEFAULT_GNSS_MODE;
|
|
}
|
|
if((mode < 1) || (mode > 6))
|
|
mode = DEFAULT_GNSS_MODE;
|
|
|
|
tdconfig.gnss_mode= mode;
|
|
D("GNSS_MODE:%d",tdconfig.gnss_mode);
|
|
return;
|
|
}
|
|
static void LoadFastFix(void)
|
|
{
|
|
char *p_ch = GetItemValue("FAST_FIX");
|
|
int ff = 0;
|
|
|
|
if (p_ch)
|
|
{
|
|
ff = atoi(p_ch);
|
|
}
|
|
else
|
|
{
|
|
ff = 0;
|
|
}
|
|
if((ff < 0) || (ff > 1))
|
|
ff = 0;
|
|
|
|
tdconfig.fast_fix= ff;
|
|
D("FAST_FIX:%d",tdconfig.fast_fix);
|
|
return;
|
|
}
|
|
|
|
static void LoadAgnssEnable(void)
|
|
{
|
|
char *p_ch = GetItemValue("AGNSS_ENABLE");
|
|
int ae = 0;
|
|
|
|
if (p_ch)
|
|
{
|
|
ae = atoi(p_ch);
|
|
}
|
|
else
|
|
{
|
|
ae = 0;
|
|
}
|
|
if((ae < 0) || (ae > 1))
|
|
ae = 0;
|
|
|
|
tdconfig.agnss_enable= ae;
|
|
D("AGNSS_ENABLE:%d",tdconfig.agnss_enable);
|
|
return;
|
|
}
|
|
|
|
|
|
static void LoadDebugSetting(void)
|
|
{
|
|
char *p_ch;
|
|
unsigned int mask = 0;
|
|
// p_ch = GetItemValue("TD_DEBUG_TOKEN");
|
|
//
|
|
// if (p_ch)
|
|
// {
|
|
// mask |= atoi(p_ch)<<D_TOKEN;
|
|
// }
|
|
// else
|
|
// {
|
|
// mask |= 0<<D_TOKEN;
|
|
// }
|
|
|
|
p_ch = GetItemValue("TD_DEBUG_GSV");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_GSV;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_GSV;
|
|
}
|
|
|
|
p_ch = GetItemValue("TD_DEBUG_GSA");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_GSA;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_GSA;
|
|
}
|
|
|
|
p_ch = GetItemValue("TD_DEBUG_NMEA");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_NMEA;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_NMEA;
|
|
}
|
|
p_ch = GetItemValue("TD_DEBUG_FIX");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_FIX;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_FIX;
|
|
}
|
|
p_ch = GetItemValue("TD_DEBUG_FUCTION");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_FUCTION;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_FUCTION;
|
|
}
|
|
|
|
p_ch = GetItemValue("TD_DEBUG_CONFIGFILE");
|
|
|
|
if (p_ch)
|
|
{
|
|
mask |= atoi(p_ch)<<D_CONFIGFILE;
|
|
}
|
|
else
|
|
{
|
|
mask |= 0<<D_CONFIGFILE;
|
|
}
|
|
|
|
tdconfig.debugmask= mask;
|
|
|
|
if (GetDebugMaskBit(D_CONFIGFILE) == 1)
|
|
{
|
|
D("[DebugMask:0x%x]",tdconfig.debugmask);
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
unsigned int GetDebugMaskBit(enum debug_mask_bit bit)
|
|
{
|
|
return (tdconfig.debugmask>>bit)&0x01;
|
|
}
|
|
|
|
static void FreeItemList(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < TD_CONFIGFILE_NUM; i++)
|
|
{
|
|
if (!item_list[i].name)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
free(item_list[i].name);
|
|
free(item_list[i].value);
|
|
|
|
item_list[i].name = NULL;
|
|
item_list[i].value = NULL;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
static int LoadConfigFile(void)
|
|
{
|
|
char *path = TD_CONFIGFILE_PATH;
|
|
int n;
|
|
|
|
n = load_properties(path);
|
|
|
|
if (n < 0)
|
|
{
|
|
D("Load tdgnss.conf config file error!");
|
|
load_default_properties();
|
|
return -1;
|
|
}
|
|
LoadDebugSetting();
|
|
LoadDriverPath();
|
|
LoadUartBaudRate();
|
|
LoadBeiDouPrnAdd();
|
|
LoadGnssMode();
|
|
LoadAgnssEnable();
|
|
LoadFastFix();
|
|
|
|
FreeItemList();
|
|
D("Load config file ok!");
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int TdUartOpen(void)
|
|
{
|
|
int fd;
|
|
|
|
|
|
//rpdzkj
|
|
char property[PROPERTY_VALUE_MAX];
|
|
|
|
|
|
property_get("ro.factory.hasGPS", property, "true");
|
|
D("<<rpdzkj>> : gps_use_property_get*** %s ***", property);
|
|
if (strcmp(property,"false")==0) {
|
|
return -1;
|
|
}
|
|
|
|
property_get("ro.sf.gps.serial", property, "/dev/ttyS4");
|
|
D("<<rpdzkj>> : gps_uart_property_get*** %s ***", property);
|
|
// char property[PROPERTY_VALUE_MAX];
|
|
|
|
|
|
// fd = open(tdconfig.strconfigfile.uartpath, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); //O_RDONLY
|
|
fd = open(property, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); //O_RDONLY
|
|
//end
|
|
|
|
if (fd < 0)
|
|
{
|
|
perror("SERIAL ERROR : no gps_bd serial detected ");
|
|
|
|
D("ERROR : Uart Open %s", strerror(errno));
|
|
|
|
return (-1);
|
|
}
|
|
|
|
|
|
D("Succeed : open uart %s boadrate = %d\n", tdconfig.strconfigfile.uartpath, tdconfig.uartboadrate);
|
|
|
|
if ( isatty( fd ) )
|
|
{
|
|
struct termios ios;
|
|
tcgetattr( fd, &ios );
|
|
ios.c_lflag = 0;
|
|
ios.c_oflag = 0;
|
|
ios.c_iflag = 0;
|
|
|
|
ios.c_cflag |= (CLOCAL | CREAD);
|
|
ios.c_cflag &= ~CSTOPB; //stop bit 1
|
|
ios.c_cflag |= CS8; //data bit 8
|
|
ios.c_cflag &= ~PARENB; //parity non
|
|
ios.c_cflag &= ~CRTSCTS; //no flow control, need update kernel
|
|
|
|
//cfsetispeed(&ios, B115200);
|
|
//cfsetospeed(&ios, B115200);
|
|
cfsetispeed(&ios, B9600);
|
|
cfsetospeed(&ios, B9600);
|
|
tcflush(fd,TCIOFLUSH);
|
|
tcsetattr(fd, TCSANOW, &ios);
|
|
|
|
}
|
|
|
|
D("TDGPS HAL open sussed");
|
|
|
|
return fd;
|
|
}
|
|
|
|
void SetApUartbaud(int baud)
|
|
{
|
|
|
|
D("AP baud=%d\n",baud);
|
|
struct termios options;
|
|
tcgetattr(_gps_state->fd, &options );
|
|
options.c_lflag = 0;
|
|
options.c_oflag = 0;
|
|
options.c_iflag = 0;
|
|
|
|
|
|
options.c_cflag |= (CLOCAL | CREAD);
|
|
options.c_cflag &= ~CSTOPB; //stop bit 1
|
|
options.c_cflag |= CS8; //data bit 8
|
|
options.c_cflag &= ~PARENB; //parity non
|
|
options.c_cflag &= ~CRTSCTS;
|
|
if(baud==9600){
|
|
cfsetispeed(&options, B9600);
|
|
cfsetospeed(&options, B9600);
|
|
}
|
|
else if(baud==115200)
|
|
{
|
|
cfsetispeed(&options, B115200);
|
|
cfsetospeed(&options, B115200);
|
|
}
|
|
else if(baud==19200)
|
|
{
|
|
cfsetispeed(&options, B19200);
|
|
cfsetospeed(&options, B19200);
|
|
}
|
|
else if(baud==38400)
|
|
{
|
|
cfsetispeed(&options, B38400);
|
|
cfsetospeed(&options, B38400);
|
|
}
|
|
else if(baud==57600)
|
|
{
|
|
cfsetispeed(&options, B57600);
|
|
cfsetospeed(&options, B57600);
|
|
}
|
|
else
|
|
{
|
|
cfsetispeed(&options, B9600);
|
|
cfsetospeed(&options, B9600);
|
|
}
|
|
|
|
tcflush(_gps_state->fd,TCIOFLUSH);
|
|
tcsetattr(_gps_state->fd, TCSANOW, &options);
|
|
}
|
|
|
|
static int
|
|
nmea_tokenizer_init( NmeaTokenizer *t, const char *p, const char *end )
|
|
{
|
|
int count = 0;
|
|
|
|
|
|
// the initial '$' is optional
|
|
if (p < end && p[0] == '$')
|
|
p += 1;
|
|
|
|
// remove trailing newline
|
|
if (end > p && end[-1] == '\n')
|
|
{
|
|
end -= 1;
|
|
|
|
if (end > p && end[-1] == '\r')
|
|
end -= 1;
|
|
}
|
|
|
|
// get rid of checksum at the end of the sentecne
|
|
if (end >= p + 3 && end[-3] == '*')
|
|
{
|
|
end -= 3;
|
|
}
|
|
|
|
while (p < end)
|
|
{
|
|
const char *q = p;
|
|
|
|
q = memchr(p, ',', end - p);
|
|
|
|
if (q == NULL)
|
|
q = end;
|
|
|
|
if (q >= p)
|
|
{
|
|
if (count < MAX_NMEA_TOKENS)
|
|
{
|
|
t->tokens[count].p = p;
|
|
t->tokens[count].end = q;
|
|
count += 1;
|
|
}
|
|
}
|
|
|
|
if (q < end)
|
|
q += 1;
|
|
|
|
p = q;
|
|
}
|
|
|
|
t->count = count;
|
|
return count;
|
|
}
|
|
|
|
static Token
|
|
nmea_tokenizer_get( NmeaTokenizer *t, int index )
|
|
{
|
|
Token tok;
|
|
static const char *dummy = "";
|
|
static const char *changestring = "00";
|
|
|
|
if (index < 0 || index >= t->count)
|
|
{
|
|
tok.p = tok.end = dummy;
|
|
}
|
|
else if(t->tokens[index].p == t->tokens[index].end)
|
|
{
|
|
tok.p = changestring;
|
|
tok.end = changestring + 1;
|
|
}
|
|
else
|
|
tok = t->tokens[index];
|
|
|
|
return tok;
|
|
}
|
|
|
|
|
|
static int
|
|
str2int( const char *p, const char *end )
|
|
{
|
|
int result = 0;
|
|
int len = end - p;
|
|
|
|
for ( ; len > 0; len--, p++ )
|
|
{
|
|
int c;
|
|
|
|
if (p >= end)
|
|
goto Fail;
|
|
|
|
c = *p - '0';
|
|
|
|
if ((unsigned)c >= 10)
|
|
goto Fail;
|
|
|
|
result = result * 10 + c;
|
|
}
|
|
|
|
return result;
|
|
|
|
Fail:
|
|
return -1;
|
|
}
|
|
|
|
static double
|
|
str2float( const char *p, const char *end )
|
|
{
|
|
int len = end - p;
|
|
char temp[16];
|
|
|
|
if (len >= (int)sizeof(temp))
|
|
return 0.;
|
|
|
|
memcpy( temp, p, len );
|
|
temp[len] = 0;
|
|
return strtod( temp, NULL );
|
|
}
|
|
|
|
|
|
void write_agps_data(int fd)
|
|
{
|
|
if(update_mode == 1 ) return;
|
|
int i=0,cnt_w=0;
|
|
//int len;
|
|
//unsigned int temp_eph_mask;
|
|
//time_t time1,time2;
|
|
unsigned char pack_sdbpbuf[73],pack_time[24];
|
|
|
|
td_agps_data = td_agps_info.agps_data;
|
|
//temp_eph_mask = td_agps_data.ehp_new.eph_mask;
|
|
//memset(&ap_chip_agps,0,sizeof(ap_chip_agps));
|
|
//td_mode.work = 0;
|
|
|
|
UartTxData((unsigned char*)"agps",4);
|
|
|
|
//ack=0;nck=0;
|
|
if(td_agps_data.time_loc_new.mask>0){
|
|
D("\n%s",td_agps_data.time_loc_new.line);
|
|
D("\n%X\n",td_agps_data.ehp_new.eph_mask);
|
|
if((pack_sdbp_time(td_agps_data.time_loc_new.line,pack_time))==-1)
|
|
return;
|
|
write(fd,pack_time,24);
|
|
//for(i=0;i<24;i++)
|
|
// D("%X",pack_time[i]);
|
|
}else{
|
|
if(td_agps_data.ehp_new.eph_mask>0){
|
|
pack_sdbp_time_local(pack_time);
|
|
write(fd,pack_time,24);
|
|
}
|
|
}
|
|
|
|
for(i=0;i<EPH_MAX_LINES;i++){
|
|
if(((td_agps_data.ehp_new.eph_mask>>i) & 0x01) == 1)
|
|
{
|
|
//len = strlen(td_agps_data.ehp_new.line[i]);
|
|
//D("AGPS:CEP-w:%s\n",td_agps_data.ehp_new.line[i]);
|
|
memset(pack_sdbpbuf,0,sizeof(pack_sdbpbuf));
|
|
//D("\n%s\n",td_agps_data.ehp_new.line[i]);
|
|
pack_sdbp_agps(td_agps_data.ehp_new.line[i],pack_sdbpbuf);
|
|
//if(cnt_w>17)
|
|
/*{
|
|
for(j=0;j<7;j++){
|
|
D("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",pack_sdbpbuf[j*10+0],pack_sdbpbuf[j*10+1],pack_sdbpbuf[j*10+2],pack_sdbpbuf[j*10+3],pack_sdbpbuf[j*10+4],pack_sdbpbuf[j*10+5],pack_sdbpbuf[j*10+6],pack_sdbpbuf[j*10+7],pack_sdbpbuf[j*10+8],pack_sdbpbuf[j*10+9]);
|
|
}
|
|
D("%02X %02X %02X\n",pack_sdbpbuf[70],pack_sdbpbuf[71],pack_sdbpbuf[72]);
|
|
}*/
|
|
//write(fd, td_agps_data.ehp_new.line[i], len);
|
|
write(fd,pack_sdbpbuf,73);
|
|
usleep(10000);
|
|
cnt_w++;
|
|
//if(cnt_w>17)
|
|
//break;
|
|
//D("\n cnt_w =%d \n",cnt_w);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
char *cmd_response = 0;
|
|
static int write_agps_ok=0;
|
|
|
|
|
|
void write_agps_data_td()
|
|
{
|
|
int ret, response_size = 0;
|
|
|
|
//UartTxData(get_version,8);
|
|
D("AGPS_TD");
|
|
memset(&td_agps_info.pos_time, 0, sizeof(struct gps_time));
|
|
memset(&td_agps_info.pos, 0, sizeof(struct gps_pos));
|
|
memset(td_agps_info.gps_ephemeris, 0, sizeof(struct supl_ephemeris_s) * 32);
|
|
td_agps_info.cnt_eph = 0;
|
|
memset(&td_agps_info.eph_time, 0, sizeof(struct gps_time));
|
|
memset(&td_agps_info.agps_data.ehp_new, 0, sizeof(struct supl_ephemeris_new));
|
|
memset(&td_agps_info.agps_data.time_loc_new, 0, sizeof(struct supl_time_loc_new));
|
|
|
|
cmd_response = (char *)malloc(SUPL_RESPONSE_BUFF_SIZE);
|
|
memset(cmd_response, 0, SUPL_RESPONSE_BUFF_SIZE);
|
|
|
|
// get_agps_data();
|
|
|
|
FILE *fp;
|
|
char *p = cmd_response;
|
|
const char *path = TD_AGPSFILE_PATH;
|
|
|
|
fp = fopen(path, "r");
|
|
|
|
if(!fp)
|
|
D("no .agpsdata file\n");
|
|
else {
|
|
while(!feof(fp))
|
|
{
|
|
*p++ = fgetc(fp);
|
|
}
|
|
fclose(fp);
|
|
}
|
|
|
|
|
|
response_size = strlen(cmd_response);
|
|
// D("receive: %s",cmd_response);
|
|
D("SUPL : get response:%d bytes", response_size);
|
|
|
|
ret = handle_supl_client_response(cmd_response, response_size);
|
|
|
|
if(ret !=0){
|
|
D("agps data not ready %d",ret);
|
|
write_agps_ok=0;
|
|
}
|
|
else {
|
|
D("write agps data");
|
|
write_agps_ok=1;
|
|
int gps_fd = _gps_state->fd;
|
|
write_agps_data(gps_fd);
|
|
}
|
|
|
|
}
|
|
|
|
static time_t last_update =0;
|
|
int agps_update()
|
|
{
|
|
time_t now = time(NULL);
|
|
if(((now-last_update > 7200) ||(write_agps_ok == 0)) && tdconfig.agnss_enable) //7200
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
static void agps_thread()
|
|
{
|
|
write_agps_data_td();
|
|
last_update = time(NULL);
|
|
agps_thread_go=0;
|
|
}
|
|
|
|
#define NMEA_MAX_SIZE 255
|
|
|
|
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;
|
|
gps_location_callback callback;
|
|
char in[ NMEA_MAX_SIZE + 1 ];
|
|
} NmeaReader;
|
|
|
|
static void
|
|
nmea_reader_init( NmeaReader *r )
|
|
{
|
|
memset( r, 0, sizeof(r) );
|
|
|
|
r->pos = 0;
|
|
r->overflow = 0;
|
|
r->utc_year = -1;
|
|
r->utc_mon = -1;
|
|
r->utc_day = -1;
|
|
r->callback = NULL;
|
|
r->fix.size = sizeof(r->fix);
|
|
r->sv_status.size = sizeof(GpsSvStatus);
|
|
}
|
|
|
|
|
|
static void
|
|
nmea_reader_set_callback( NmeaReader *r, gps_location_callback cb )
|
|
{
|
|
r->callback = cb;
|
|
|
|
if (cb != NULL && r->fix.flags != 0)
|
|
{
|
|
//D("%s: sending latest fix to new callback", __FUNCTION__);
|
|
// r->callback( &r->fix );
|
|
r->fix.flags = 0;
|
|
}
|
|
}
|
|
|
|
static int
|
|
nmea_reader_update_time( NmeaReader *r, Token tok )
|
|
{
|
|
int hour, minute;
|
|
double seconds;
|
|
struct tm tm;
|
|
time_t fix_time;
|
|
time_t now;
|
|
struct tm *local_tm;
|
|
struct tm *utc_tm;
|
|
long local_time;
|
|
long utc_time;
|
|
long delta_time;
|
|
|
|
if (tok.p + 6 > tok.end)
|
|
return -1;
|
|
|
|
hour = str2int(tok.p, tok.p + 2);
|
|
minute = str2int(tok.p + 2, tok.p + 4);
|
|
seconds = str2float(tok.p + 4, tok.end);
|
|
struct utc_t GPS;
|
|
GPS.year=r->utc_year;
|
|
GPS.month=r->utc_mon;
|
|
GPS.day=r->utc_day;
|
|
GPS.hour=hour;
|
|
GPS.min=minute;
|
|
GPS.sec=seconds;
|
|
|
|
tm.tm_hour = GPS.hour;
|
|
tm.tm_min = GPS.min;
|
|
tm.tm_sec = (int) seconds;
|
|
tm.tm_year = GPS.year - 1900;
|
|
tm.tm_mon = GPS.month - 1;
|
|
tm.tm_mday = GPS.day;
|
|
tm.tm_isdst = -1;
|
|
|
|
fix_time = mktime( &tm );
|
|
|
|
now = time(NULL);
|
|
local_tm = localtime(&now);
|
|
local_time = local_tm->tm_sec + 60*(local_tm->tm_min + 60*(local_tm->tm_hour + 24*(local_tm->tm_yday + 365*local_tm->tm_year)));
|
|
utc_tm = gmtime(&now);
|
|
utc_time = utc_tm->tm_sec + 60*(utc_tm->tm_min + 60*(utc_tm->tm_hour + 24*(utc_tm->tm_yday + 365*utc_tm->tm_year)));
|
|
delta_time = local_time - utc_time;
|
|
|
|
r->fix.timestamp = (long long)(fix_time + delta_time) * 1000 + (int)(seconds * 1000) % 1000;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
nmea_reader_update_date( NmeaReader *r, Token date, Token time )
|
|
{
|
|
Token tok = date;
|
|
int day, mon, year;
|
|
|
|
if (tok.p + 6 != tok.end)
|
|
{
|
|
D("date not properly formatted");
|
|
return -1;
|
|
}
|
|
|
|
day = str2int(tok.p, tok.p + 2);
|
|
mon = str2int(tok.p + 2, tok.p + 4);
|
|
year = str2int(tok.p + 4, tok.p + 6) + 2000;
|
|
|
|
if ((day | mon | year) < 0)
|
|
{
|
|
D("date not properly formatted");
|
|
return -1;
|
|
}
|
|
|
|
r->utc_year = year;
|
|
r->utc_mon = mon;
|
|
r->utc_day = day;
|
|
|
|
return nmea_reader_update_time( r, time );
|
|
}
|
|
|
|
|
|
static double
|
|
convert_from_hhmm( Token tok )
|
|
{
|
|
double val = str2float(tok.p, tok.end);
|
|
int degrees = (int)(floor(val) / 100);
|
|
double minutes = val - degrees * 100.;
|
|
double dcoord = degrees + minutes / 60.0;
|
|
return dcoord;
|
|
}
|
|
|
|
static int
|
|
nmea_reader_update_latlong( NmeaReader *r,
|
|
Token latitude,
|
|
char latitudeHemi,
|
|
Token longitude,
|
|
char longitudeHemi )
|
|
{
|
|
double lat, lon;
|
|
Token tok;
|
|
tok = latitude;
|
|
char temp1[30] = {0}, temp2[30] = {0};
|
|
int len1, len2;
|
|
len1 = latitude.end - latitude.p;
|
|
len2 = longitude.end - longitude.p;
|
|
memcpy(temp1, latitude.p, len1);
|
|
temp1[len1] = 0;
|
|
memcpy(temp2, longitude.p, len2);
|
|
temp2[len2] = 0;
|
|
//D("nmea latitude : %s longitude : %s ", temp1,temp2);
|
|
|
|
|
|
if (tok.p + 6 > tok.end)
|
|
{
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_LAT_LONG);
|
|
return -1;
|
|
}
|
|
|
|
lat = convert_from_hhmm(tok);
|
|
|
|
if (latitudeHemi == 'S')
|
|
lat = -lat;
|
|
|
|
tok = longitude;
|
|
|
|
if (tok.p + 6 > tok.end)
|
|
{
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_LAT_LONG);
|
|
return -1;
|
|
}
|
|
|
|
lon = convert_from_hhmm(tok);
|
|
|
|
if (longitudeHemi == 'W')
|
|
lon = -lon;
|
|
|
|
if(((lat < 0.00000001) && (lat > -0.00000001)) || ((lon < 0.00000001) && (lon > -0.00000001)))
|
|
{
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_LAT_LONG);
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
r->fix.latitude = lat;
|
|
r->fix.longitude = lon;
|
|
r->fix.flags |= GPS_LOCATION_HAS_LAT_LONG;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int nmea_reader_update_altitude( NmeaReader *r,Token altitude)
|
|
{
|
|
Token tok = altitude;
|
|
char temp1[30] = {0};
|
|
int len1;
|
|
len1 = altitude.end - altitude.p;
|
|
memcpy(temp1, altitude.p, len1);
|
|
temp1[len1] = 0;
|
|
//D("nmea altitude : %s ",temp1);
|
|
|
|
|
|
if (tok.p >= tok.end){
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_ALTITUDE);
|
|
return -1;
|
|
}
|
|
|
|
r->fix.flags |= GPS_LOCATION_HAS_ALTITUDE;
|
|
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_LAT_LONG))
|
|
{
|
|
r->fix.altitude = str2float(altitude.p, altitude.end);
|
|
}
|
|
if (GetDebugMaskBit(D_FIX) == 1)
|
|
{
|
|
D("altitude : %f ", r->fix.altitude);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
nmea_reader_update_accuracy( NmeaReader *r, Token accuracy )
|
|
{
|
|
|
|
|
|
Token tok = accuracy;
|
|
char temp1[30] = {0};
|
|
int len1;
|
|
len1 = accuracy.end - accuracy.p;
|
|
memcpy(temp1, accuracy.p, len1);
|
|
temp1[len1] = 0;
|
|
//D("nmea accuracy : %s ",temp1);
|
|
|
|
|
|
if (tok.p >= tok.end){
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_ACCURACY);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
if (r->fix.accuracy == 99.99)
|
|
{
|
|
r->fix.flags &= ~(GPS_LOCATION_HAS_ACCURACY);
|
|
return 0;
|
|
|
|
}
|
|
*/
|
|
|
|
r->fix.flags |= GPS_LOCATION_HAS_ACCURACY;
|
|
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_LAT_LONG))
|
|
{
|
|
r->fix.accuracy = str2float(tok.p, tok.end);
|
|
}
|
|
else
|
|
{
|
|
r->fix.accuracy = 0.0;
|
|
}
|
|
|
|
|
|
if (GetDebugMaskBit(D_FIX) == 1)
|
|
{
|
|
D("accuracy : %f", r->fix.accuracy);
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
nmea_reader_update_bearing( NmeaReader *r,
|
|
Token bearing )
|
|
{
|
|
Token tok = bearing;
|
|
char temp1[30] = {0};
|
|
int len1;
|
|
len1 = bearing.end - bearing.p;
|
|
memcpy(temp1, bearing.p, len1);
|
|
temp1[len1] = 0;
|
|
//D("nmea bearing : %s ", temp1);
|
|
|
|
|
|
if (tok.p >= tok.end){
|
|
r->fix.flags &= (~GPS_LOCATION_HAS_BEARING);
|
|
return -1;
|
|
}
|
|
|
|
r->fix.flags |= GPS_LOCATION_HAS_BEARING;
|
|
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_LAT_LONG)){
|
|
r->fix.bearing = str2float(tok.p, tok.end);
|
|
}
|
|
|
|
if (GetDebugMaskBit(D_FIX) == 1)
|
|
{
|
|
D("bearing : %f ", r->fix.bearing);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
nmea_reader_update_speed( NmeaReader *r,
|
|
Token speed )
|
|
{
|
|
Token tok = speed;
|
|
char temp1[30] = {0};
|
|
int len1;
|
|
len1 = speed.end - speed.p;
|
|
memcpy(temp1, speed.p, len1);
|
|
temp1[len1] = 0;
|
|
//D("nmea speed : %s ",temp1);
|
|
|
|
|
|
if (tok.p >= tok.end){
|
|
r->fix.flags &= (~GPS_LOCATION_HAS_SPEED);
|
|
return -1;
|
|
}
|
|
|
|
r->fix.flags |= GPS_LOCATION_HAS_SPEED;
|
|
/*
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_LAT_LONG)){
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_BEARING)){
|
|
r->fix.speed = (float)str2float(tok.p, tok.end) * 1.852 / 3.6;
|
|
if(r->fix.speed < 2.0) {
|
|
r->fix.speed = r->fix.speed / 2.0;
|
|
}
|
|
}
|
|
else{
|
|
r->fix.speed = 0.0;
|
|
}
|
|
}
|
|
*/
|
|
if((r->fix.flags)&(GPS_LOCATION_HAS_LAT_LONG)){
|
|
r->fix.speed = (float)str2float(tok.p, tok.end) * 1.852 / 3.6;
|
|
}
|
|
if (GetDebugMaskBit(D_FIX) == 1)
|
|
{
|
|
D("speed : %f ", r->fix.speed);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void update_gps_svstatus(GpsSvStatus *svstatus);
|
|
|
|
|
|
static int NmeaCheck(NmeaReader *r)
|
|
{
|
|
unsigned char buff[500];
|
|
char *p, *end;
|
|
|
|
int res;
|
|
p = r->in;
|
|
end = r->in + r->pos;
|
|
memset(buff, 0, sizeof(buff));
|
|
memcpy(buff, p, (end - p));
|
|
|
|
update_nmea(r->in, r->in + r->pos);
|
|
res = _LibNMEA_Xor((char *)buff);
|
|
return res;
|
|
}
|
|
|
|
static int _LibNMEA_Xor(char *p_chk_str)
|
|
{
|
|
unsigned int check_sum = 0;
|
|
int n, i;
|
|
char crcbuf[4];
|
|
memset(crcbuf, 0, sizeof(crcbuf));
|
|
p_chk_str++;
|
|
n = strlen(p_chk_str) - 5;
|
|
|
|
if(n < 0)
|
|
return -1;
|
|
|
|
for(i = 0; i < n; i++)
|
|
{
|
|
check_sum ^= (*p_chk_str);
|
|
//D("sum:0x%x : %c",check_sum,*p_chk_str);
|
|
p_chk_str++;
|
|
|
|
if(n == 500)
|
|
return -1;
|
|
}
|
|
|
|
if(check_sum < 0x10)
|
|
sprintf(crcbuf, "0%X", check_sum);
|
|
else
|
|
sprintf(crcbuf, "%X", check_sum);
|
|
|
|
p_chk_str++;
|
|
|
|
if(memcmp(crcbuf, p_chk_str, 2) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
//D("nmea crc f : %s", p_chk_str);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static void FixSattileCheck(int prn, NmeaReader *r)
|
|
{
|
|
int i;
|
|
|
|
if(GsaPrn.fixprnnum == 0)
|
|
return;
|
|
|
|
if((prn<=0) ||(prn>256))
|
|
return;
|
|
|
|
for(i = 0; i < GsaPrn.fixprnnum; i++)
|
|
{
|
|
if((prn == GsaPrn.fixprn[i]) || (fixed[prn] == 1))
|
|
{
|
|
fixed[prn] = 1;
|
|
r->sv_status.used_in_fix_mask |= (1 << (r->sv_status.num_svs));
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void up_svstatus(NmeaReader *r )
|
|
{
|
|
//if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
if(r->callback!=NULL)
|
|
update_gps_svstatus(&r->sv_status);
|
|
memset(&GsaPrn, 0, sizeof(GsaPrn));
|
|
memset(&r->sv_status, 0, sizeof(r->sv_status));
|
|
return;
|
|
}
|
|
|
|
static void ClearSv( NmeaReader *r )
|
|
{
|
|
memset(&r->sv_status.used_in_fix_mask, 0, sizeof(r->sv_status.used_in_fix_mask));
|
|
memset(&r->sv_status, 0, sizeof(r->sv_status));
|
|
memset(&GsaPrn, 0, sizeof(GsaPrn));
|
|
r->sv_status.size = sizeof(GpsSvStatus);
|
|
return;
|
|
}
|
|
|
|
static void
|
|
nmea_reader_parse( NmeaReader *r )
|
|
{
|
|
NmeaTokenizer tzer[1];
|
|
Token tok;
|
|
int rmcmode=0;
|
|
int ret;
|
|
|
|
char gsvhead[5] = {0, 0, 0, 0, 0};
|
|
static int GNModeList[2] = {MODE_GPS,MODE_BD};//
|
|
//int i;
|
|
|
|
nmea_tokenizer_init(tzer, r->in, r->in + r->pos);
|
|
if(td_mode.work==0)
|
|
td_mode.work=1;
|
|
tdconfig.power_flag = TD_ON;
|
|
|
|
// if (GetDebugMaskBit(D_TOKEN) == 1)
|
|
// {
|
|
// int n;
|
|
// //D("Found %d tokens", tzer->count);
|
|
//
|
|
// for (n = 0; n < tzer->count; n++)
|
|
// {
|
|
// nmea_tokenizer_get(tzer, n);
|
|
//
|
|
// }
|
|
// }
|
|
|
|
|
|
tok = nmea_tokenizer_get(tzer, 0);
|
|
|
|
if (tok.p + 5 > tok.end)
|
|
{
|
|
D("nmea sentence too short, ignored.");
|
|
return;
|
|
}
|
|
|
|
memcpy(gsvhead, tok.p, 5);
|
|
tok.p += 2;
|
|
|
|
if(!memcmp(tok.p, "GSV", 3))
|
|
{
|
|
if(!memcmp(gsvhead, "GPGSV", 5))
|
|
{
|
|
|
|
|
|
Token tok_noSatellites = nmea_tokenizer_get(tzer, 3);//visibility satellites
|
|
int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end);
|
|
|
|
if(GNModeList[1] != MODE_GPS)
|
|
{
|
|
GNModeList[0] = GNModeList[1];
|
|
GNModeList[1] = MODE_GPS;
|
|
}
|
|
|
|
if ((noSatellites > 0) && (r->sv_status.num_svs < GPS_MAX_SVS))
|
|
{
|
|
int prn;
|
|
int i = 0;
|
|
|
|
while (i < 4)
|
|
{
|
|
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);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
if(prn > 0)
|
|
{
|
|
if(r->sv_status.num_svs > (GPS_MAX_SVS - 1))
|
|
{
|
|
r->sv_status_changed = 1;
|
|
return;
|
|
}
|
|
|
|
r->sv_status.sv_list[r->sv_status.num_svs].prn = prn;
|
|
FixSattileCheck(prn, r);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].elevation = str2float(tok_elevation.p, tok_elevation.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].snr = str2float(tok_snr.p, tok_snr.end);
|
|
r->sv_status.num_svs += 1;
|
|
r->sv_status_changed = 1;
|
|
if (GetDebugMaskBit(D_GSV) == 1)
|
|
{
|
|
D("GPGSV numsv:%d sv[%2d] prn:%d elevation:%f azimuth:%f snr:%f mask:0x%x", r->sv_status.num_svs, r->sv_status.num_svs - 1, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].prn, r->sv_status.sv_list[r->sv_status.num_svs - 1].elevation, r->sv_status.sv_list[r->sv_status.num_svs - 1].azimuth, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].snr, r->sv_status.used_in_fix_mask);
|
|
}
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(!memcmp(gsvhead, "BDGSV", 5))
|
|
{
|
|
Token tok_noSatellites = nmea_tokenizer_get(tzer, 3);//visibility satellites
|
|
int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end);
|
|
|
|
if(GNModeList[1] != MODE_BD)
|
|
{
|
|
|
|
GNModeList[0] = GNModeList[1];
|
|
GNModeList[1] = MODE_BD;
|
|
}
|
|
|
|
if ((noSatellites > 0) && (r->sv_status.num_svs < (GPS_MAX_SVS)))
|
|
{
|
|
int prn;
|
|
int i = 0;
|
|
|
|
while (i < 4)
|
|
{
|
|
if(r->sv_status.num_svs > (GPS_MAX_SVS - 1))
|
|
{
|
|
r->sv_status_changed=1;
|
|
return;
|
|
}
|
|
|
|
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);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
if(prn > 0)
|
|
{
|
|
prn += tdconfig.bdprnaddr;
|
|
r->sv_status.sv_list[r->sv_status.num_svs].prn = prn;
|
|
FixSattileCheck(prn, r);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].elevation = str2float(tok_elevation.p, tok_elevation.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].snr = str2float(tok_snr.p, tok_snr.end);
|
|
r->sv_status.num_svs += 1;
|
|
r->sv_status_changed = 1;
|
|
if (GetDebugMaskBit(D_GSV) == 1)
|
|
{
|
|
D("BDGSV numsv:%d sv[%2d] prn:%d elevation:%f azimuth:%f snr:%f mask:0x%x", r->sv_status.num_svs, r->sv_status.num_svs - 1, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].prn, r->sv_status.sv_list[r->sv_status.num_svs - 1].elevation, r->sv_status.sv_list[r->sv_status.num_svs - 1].azimuth, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].snr, r->sv_status.used_in_fix_mask);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(!memcmp(gsvhead, "GLGSV", 5))
|
|
{
|
|
Token tok_noSatellites = nmea_tokenizer_get(tzer, 3);//visibility satellites
|
|
int noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end);
|
|
|
|
if(GNModeList[1] != MODE_GL)
|
|
{
|
|
GNModeList[0] = GNModeList[1];
|
|
GNModeList[1] = MODE_GL;
|
|
}
|
|
|
|
if ((noSatellites > 0) && (r->sv_status.num_svs < (GPS_MAX_SVS)))
|
|
{
|
|
int prn;
|
|
int i = 0;
|
|
|
|
while (i < 4)
|
|
{
|
|
if(r->sv_status.num_svs > (GPS_MAX_SVS - 1))
|
|
{
|
|
r->sv_status_changed=1;
|
|
return;
|
|
}
|
|
|
|
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);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
|
|
|
|
if(prn > 0)
|
|
{
|
|
r->sv_status.sv_list[r->sv_status.num_svs].prn = prn;
|
|
FixSattileCheck(prn, r);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].elevation = str2float(tok_elevation.p, tok_elevation.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
|
|
r->sv_status.sv_list[r->sv_status.num_svs].snr = str2float(tok_snr.p, tok_snr.end);
|
|
|
|
r->sv_status.num_svs += 1;
|
|
r->sv_status_changed = 1;
|
|
if (GetDebugMaskBit(D_GSV) == 1)
|
|
{
|
|
D("GLGSV numsv:%d sv[%2d] prn:%d elevation:%f azimuth:%f snr:%f mask:0x%x", r->sv_status.num_svs, r->sv_status.num_svs - 1, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].prn, r->sv_status.sv_list[r->sv_status.num_svs - 1].elevation, r->sv_status.sv_list[r->sv_status.num_svs - 1].azimuth, \
|
|
r->sv_status.sv_list[r->sv_status.num_svs - 1].snr, r->sv_status.used_in_fix_mask);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////GGA
|
|
else if ( !memcmp(tok.p, "GGA", 3) )
|
|
{
|
|
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_fixStatus = nmea_tokenizer_get(tzer, 6);
|
|
Token tok_accuracy = nmea_tokenizer_get(tzer, 8);
|
|
Token tok_altitude = nmea_tokenizer_get(tzer, 9);
|
|
|
|
nmea_reader_update_latlong(r, tok_latitude,
|
|
tok_latitudeHemi.p[0],
|
|
tok_longitude,
|
|
tok_longitudeHemi.p[0]);
|
|
nmea_reader_update_accuracy(r, tok_accuracy);
|
|
nmea_reader_update_altitude(r, tok_altitude);
|
|
nmea_reader_update_time(r, tok_time);
|
|
|
|
if ((r->callback) && (tok_fixStatus.p[0] != '0'))
|
|
{
|
|
if (GetDebugMaskBit(D_FIX) == 1)
|
|
{
|
|
D("fixstatus : %c", tok_fixStatus.p[0]);
|
|
D("lat : %f lon : %f ", r->fix.latitude, r->fix.longitude);
|
|
}
|
|
|
|
r->callback( &r->fix );//callback up fix
|
|
r->fix.flags = 0;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////RMC
|
|
}
|
|
else if ( !memcmp(tok.p, "RMC", 3))
|
|
{
|
|
if(!memcmp(gsvhead, "GNRMC", 5))
|
|
{
|
|
nmeastate = NMEA_GNRMC;
|
|
|
|
if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_BD)
|
|
{
|
|
rmcmode=0x30;
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_GL)
|
|
{
|
|
|
|
rmcmode=0x60;
|
|
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_BD + MODE_GL)
|
|
{
|
|
rmcmode=0x50;
|
|
}
|
|
|
|
|
|
}
|
|
else if(!memcmp(gsvhead, "BDRMC", 5)){
|
|
nmeastate = NMEA_BDRMC;
|
|
rmcmode=0x10;
|
|
}
|
|
else if(!memcmp(gsvhead, "GPRMC", 5)){
|
|
nmeastate = NMEA_GPRMC;
|
|
rmcmode=0x20;
|
|
}
|
|
else if(!memcmp(gsvhead, "GLRMC", 5)){
|
|
nmeastate = NMEA_GLRMC;
|
|
rmcmode=0x40;
|
|
}
|
|
|
|
td_mode.nv_mode=rmcmode;
|
|
|
|
if((r->sv_status_changed) == 1)
|
|
{
|
|
up_svstatus(r);
|
|
r->sv_status_changed = 0;
|
|
}
|
|
else
|
|
{
|
|
ClearSv(r);
|
|
up_svstatus(r);
|
|
}
|
|
|
|
|
|
|
|
Token tok_time = nmea_tokenizer_get(tzer, 1);
|
|
Token tok_fixStatus = nmea_tokenizer_get(tzer, 2);
|
|
Token tok_latitude = nmea_tokenizer_get(tzer, 3);
|
|
Token tok_latitudeHemi = nmea_tokenizer_get(tzer, 4);
|
|
Token tok_longitude = nmea_tokenizer_get(tzer, 5);
|
|
Token tok_longitudeHemi = nmea_tokenizer_get(tzer, 6);
|
|
Token tok_speed = nmea_tokenizer_get(tzer, 7);
|
|
Token tok_bearing = nmea_tokenizer_get(tzer, 8);
|
|
Token tok_date = nmea_tokenizer_get(tzer, 9);
|
|
|
|
if (tok_fixStatus.p[0] == 'A')
|
|
{
|
|
nmea_reader_update_date( r, tok_date, tok_time );
|
|
nmea_reader_update_latlong(r, tok_latitude,
|
|
tok_latitudeHemi.p[0],
|
|
tok_longitude,
|
|
tok_longitudeHemi.p[0]);
|
|
nmea_reader_update_bearing( r, tok_bearing );
|
|
nmea_reader_update_speed ( r, tok_speed );
|
|
}else{
|
|
r->fix.flags &= (~GPS_LOCATION_HAS_BEARING);
|
|
r->fix.flags &= (~GPS_LOCATION_HAS_SPEED);
|
|
if (agps_thread_go == 0 && agps_update())
|
|
{
|
|
agps_thread_go = 1;
|
|
ret = _gps_state->callbacks.create_thread_cb("agps_thread", agps_thread, _gps_state);
|
|
if (!ret)
|
|
{
|
|
agps_thread_go = 0;
|
|
D("agps_thread: could not create thread, ret=%d, errno=%d\n", ret, errno);
|
|
}
|
|
else
|
|
{
|
|
D("agps_thread create\n");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
///////////////////////////////////////////////////////GSA
|
|
}
|
|
else if ( !memcmp(tok.p, "GSA", 3) )
|
|
{
|
|
Token tok_fixStatus = nmea_tokenizer_get(tzer, 2);
|
|
if((!memcmp(gsvhead, "GNGSA", 5))&&(nmeastate == NMEA_GNRMC))
|
|
{
|
|
nmeastate = NMEA_1ST_GNGSA;
|
|
if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_BD)
|
|
{
|
|
gsvhead[1]='P';
|
|
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_GL)
|
|
{
|
|
gsvhead[1]='P';
|
|
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_BD + MODE_GL)
|
|
{
|
|
gsvhead[1]='L';
|
|
|
|
}
|
|
}
|
|
|
|
if((!memcmp(gsvhead, "GNGSA", 5))&&(nmeastate == NMEA_1ST_GNGSA))
|
|
{
|
|
|
|
nmeastate = NMEA_2ND_GNGSA;
|
|
|
|
if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_BD)
|
|
{
|
|
gsvhead[0]='B';
|
|
gsvhead[1]='D';
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_GPS + MODE_GL)
|
|
{
|
|
gsvhead[0]='G';
|
|
gsvhead[1]='L';
|
|
|
|
}
|
|
else if(GNModeList[0] + GNModeList[1] == MODE_BD + MODE_GL)
|
|
{
|
|
gsvhead[0]='B';
|
|
gsvhead[1]='D';
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1')
|
|
{
|
|
int i;
|
|
int prn;
|
|
|
|
if((!memcmp(gsvhead, "GPGSA", 5)) && (GsaPrn.fixprnnum < GPS_MAX_SVS))
|
|
{
|
|
for(i = 3; i < 14; i++)
|
|
{
|
|
Token tok_prn = nmea_tokenizer_get(tzer, i);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
if(prn > 0)
|
|
{
|
|
if(GsaPrn.fixprnnum >= GPS_MAX_SVS)
|
|
break;
|
|
|
|
GsaPrn.fixprn[GsaPrn.fixprnnum] = prn;
|
|
if (GetDebugMaskBit(D_GSA) == 1)
|
|
{
|
|
D("GPGSA useprn=%d", GsaPrn.fixprn[GsaPrn.fixprnnum]);
|
|
}
|
|
GsaPrn.fixprnnum++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
else if((!memcmp(gsvhead, "BDGSA", 5)) && (GsaPrn.fixprnnum < GPS_MAX_SVS))
|
|
{
|
|
for(i = 3; i < 14; i++)
|
|
{
|
|
Token tok_prn = nmea_tokenizer_get(tzer, i);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
if(prn > 0)
|
|
{
|
|
if(GsaPrn.fixprnnum >= GPS_MAX_SVS)
|
|
break;
|
|
|
|
GsaPrn.fixprn[GsaPrn.fixprnnum] = prn + tdconfig.bdprnaddr;
|
|
if (GetDebugMaskBit(D_GSA) == 1)
|
|
{
|
|
D("BDGSA useprn=%d", GsaPrn.fixprn[GsaPrn.fixprnnum]);
|
|
}
|
|
GsaPrn.fixprnnum++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
else if((!memcmp(gsvhead, "GLGSA", 5)) && (GsaPrn.fixprnnum < GPS_MAX_SVS))
|
|
{
|
|
for(i = 3; i < 14; i++)
|
|
{
|
|
Token tok_prn = nmea_tokenizer_get(tzer, i);
|
|
prn = str2int(tok_prn.p, tok_prn.end);
|
|
|
|
if(prn > 0)
|
|
{
|
|
if(GsaPrn.fixprnnum >= GPS_MAX_SVS)
|
|
break;
|
|
|
|
GsaPrn.fixprn[GsaPrn.fixprnnum] = prn;
|
|
if (GetDebugMaskBit(D_GSA) == 1)
|
|
{
|
|
D("GLGSA useprn=%d", GsaPrn.fixprn[GsaPrn.fixprnnum]);
|
|
}
|
|
GsaPrn.fixprnnum++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
tok.p -= 2;
|
|
}
|
|
}
|
|
|
|
static void SDBP_Prase(int data)
|
|
{
|
|
#define Maxlen 256
|
|
static unsigned char ACKData[Maxlen] = {0};
|
|
static unsigned int DataIndex = 0;
|
|
char tmp_buff[Maxlen] = {0};
|
|
char tmp[4] = {0};
|
|
unsigned int i;
|
|
unsigned int datalen;
|
|
unsigned short crc16 = 0;
|
|
//int ret = 0;
|
|
|
|
for(i = 0; i < Maxlen - 1;i ++)
|
|
{
|
|
ACKData[i] = ACKData[i + 1];
|
|
}
|
|
ACKData[Maxlen - 1] = data;
|
|
|
|
if(DataIndex > 0)DataIndex --;
|
|
|
|
if(ACKData[Maxlen - 2] == 0x23 && ACKData[Maxlen - 1] == 0x3e)
|
|
{
|
|
DataIndex = Maxlen - 2;
|
|
return;
|
|
}
|
|
|
|
|
|
if((DataIndex + 7)< Maxlen)
|
|
{
|
|
if(ACKData[DataIndex] == 0x23 && ACKData[DataIndex + 1] == 0x3e)
|
|
{
|
|
datalen = ACKData[DataIndex + 4] + (ACKData[DataIndex + 5]<<8) + 8;
|
|
|
|
if(DataIndex + datalen - 1 < Maxlen)
|
|
{
|
|
crc16 = ACKData[DataIndex + datalen - 2] + (ACKData[DataIndex + datalen - 1]<<8);
|
|
if(crc16 != FletCher16_sdbp(&ACKData[DataIndex + 2],0,datalen - 4))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else return;
|
|
|
|
}
|
|
else return;
|
|
|
|
}
|
|
else return;
|
|
|
|
|
|
|
|
if( ACKData[DataIndex + 2] == 0x05 && ACKData[DataIndex + 3] == 0x01)
|
|
{
|
|
|
|
snprintf(tmp_buff, datalen - 8 + 1,"%s",ACKData + DataIndex + 6);//
|
|
|
|
D("SDBP : Ver %s",tmp_buff);
|
|
}
|
|
else
|
|
{
|
|
|
|
for(i = 0;i < datalen;i ++)
|
|
{
|
|
sprintf(tmp, "%02x ",ACKData[DataIndex + i]);
|
|
strcat(tmp_buff, tmp);
|
|
}
|
|
D("SDBP : %s",tmp_buff);
|
|
}
|
|
|
|
|
|
if(update_mode == 1)//update mode rx
|
|
{
|
|
update_td_handler_return(&ACKData[DataIndex]);
|
|
}
|
|
|
|
memset(&ACKData[DataIndex],0,datalen);
|
|
DataIndex = 0;
|
|
|
|
}
|
|
|
|
static void
|
|
nmea_reader_addc( NmeaReader *r, int c )
|
|
{
|
|
|
|
if (r->overflow)
|
|
{
|
|
r->overflow = (c != '\n');//restart from a new parase
|
|
return;
|
|
}
|
|
|
|
//r->overflow
|
|
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' && r->in[r->pos - 2] == '\r')
|
|
{
|
|
|
|
if(NmeaCheck(r) == 0)
|
|
nmea_reader_parse( r );
|
|
|
|
r->pos = 0;
|
|
}
|
|
}
|
|
|
|
void update_gps_status(GpsStatusValue value)
|
|
{
|
|
// D("%s(): GpsStatusValue=%d", __FUNCTION__, value);
|
|
GpsState *state = _gps_state;
|
|
state->status.status = value;
|
|
|
|
if(state->callbacks.status_cb)
|
|
state->callbacks.status_cb(&state->status);
|
|
}
|
|
|
|
static void
|
|
td_gps_state_done( GpsState *s )
|
|
{
|
|
update_gps_status(GPS_STATUS_ENGINE_OFF);
|
|
|
|
char cmd = CMD_QUIT;
|
|
void *dummy;
|
|
write( s->control[0], &cmd, 1 );
|
|
pthread_join(s->thread, &dummy);
|
|
|
|
close( s->control[0] );
|
|
s->control[0] = -1;
|
|
close( s->control[1] );
|
|
s->control[1] = -1;
|
|
|
|
close( s->fd );
|
|
s->fd = -1;
|
|
s->init = 0;
|
|
}
|
|
|
|
|
|
static void
|
|
td_gps_state_start( GpsState *s )
|
|
{
|
|
// Navigation started.
|
|
update_gps_status(GPS_STATUS_SESSION_BEGIN);//up gps navigation status
|
|
|
|
char cmd = CMD_START;
|
|
int ret;
|
|
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, 1 );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
if (ret != 1)
|
|
D("%s: could not send CMD_START command: ret=%d: %s",
|
|
__FUNCTION__, ret, strerror(errno));
|
|
}
|
|
|
|
|
|
static void
|
|
td_gps_state_stop( GpsState *s )
|
|
{
|
|
// Navigation ended.
|
|
update_gps_status(GPS_STATUS_SESSION_END);
|
|
|
|
char cmd = CMD_STOP;
|
|
int ret;
|
|
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, 1 );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
if (ret != 1)
|
|
D("%s: could not send CMD_STOP command: ret=%d: %s",
|
|
__FUNCTION__, ret, strerror(errno));
|
|
}
|
|
|
|
|
|
static int
|
|
epoll_register( int epoll_fd, int fd )
|
|
{
|
|
struct epoll_event ev;
|
|
int ret, flags;
|
|
|
|
flags = fcntl(fd, F_GETFL);
|
|
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
|
|
|
ev.events = EPOLLIN;
|
|
ev.data.fd = fd;
|
|
|
|
do
|
|
{
|
|
ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
void update_gps_location(GpsLocation *location)
|
|
{
|
|
// D("%s(): GpsLocation=%f, %f", __FUNCTION__, location->latitude, location->longitude);
|
|
GpsState *state = _gps_state;
|
|
|
|
//Should be made thread safe...
|
|
if(state->callbacks.location_cb)
|
|
state->callbacks.location_cb(location);
|
|
}
|
|
|
|
void ChipUpdateResult(unsigned char flag)
|
|
{
|
|
GpsState *state = _gps_state;
|
|
char buff[256] = {0};
|
|
int percent;
|
|
memset(buff, 0, sizeof(buff));
|
|
GpsUtcTime system_time;
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
system_time = (GpsUtcTime) tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
|
if(flag == 1)
|
|
{
|
|
strcpy(buff, "TD Chip Update Succeed");
|
|
D("CallBack : %s",buff);
|
|
}
|
|
else if(flag == 2 )
|
|
{
|
|
int sync_now, sync_toall;
|
|
update_td_get_sync(&sync_now, &sync_toall);
|
|
|
|
if(sync_toall > 0)
|
|
percent = 100 * sync_now / sync_toall;
|
|
else percent = 0;
|
|
|
|
sprintf(buff, "Percent:%d", percent);
|
|
D("CallBack : %s",buff);
|
|
}
|
|
else
|
|
{
|
|
strcpy(buff, "TD Chip Update Failed");
|
|
D("CallBack : %s",buff);
|
|
}
|
|
|
|
if(state->callbacks.nmea_cb != 0)
|
|
{
|
|
state->callbacks.nmea_cb(system_time, buff, strlen(buff));
|
|
}
|
|
}
|
|
|
|
void SendResultToApp(int res)
|
|
{
|
|
if(res == 2)
|
|
{
|
|
ChipUpdateResult(2);
|
|
}
|
|
else if(res == 1)
|
|
{
|
|
D("update_td success");
|
|
ChipUpdateResult(1);
|
|
update_mode = 0;
|
|
if(td_mode.on_need==0)
|
|
PowerOff();
|
|
}
|
|
else if(res == 3)
|
|
{
|
|
ChipUpdateResult(3);
|
|
D("update_td failed");
|
|
update_mode = 0;
|
|
if(td_mode.on_need==0)
|
|
PowerOff();
|
|
}
|
|
}
|
|
|
|
void update_gps_svstatus(GpsSvStatus *svstatus) // callback of svstatus in _gps_state
|
|
{
|
|
//if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
GpsState *state = _gps_state;
|
|
|
|
if(state->callbacks.sv_status_cb)
|
|
state->callbacks.sv_status_cb(svstatus);
|
|
}
|
|
|
|
void update_nmea(const char *p, const char *end )
|
|
{
|
|
GpsState *state = _gps_state;
|
|
char buff[500];
|
|
memset(buff, 0, sizeof(buff));
|
|
memcpy(buff, p, (end - p));
|
|
GpsUtcTime system_time;
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
system_time = (GpsUtcTime) tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
|
|
|
if (GetDebugMaskBit(D_NMEA) == 1)
|
|
{
|
|
D("nmea:%s", buff);
|
|
}
|
|
|
|
if(state->callbacks.nmea_cb && update_mode == 0)
|
|
{
|
|
state->callbacks.nmea_cb(system_time, buff, end - p);
|
|
}
|
|
}
|
|
|
|
int UartTxData(unsigned char *buffer, int length)
|
|
{
|
|
int tx_len = 0;
|
|
int com_fd = _gps_state->fd;
|
|
if(com_fd != -1)
|
|
{
|
|
|
|
do
|
|
{
|
|
tx_len = write( com_fd, buffer, length );
|
|
}
|
|
while (tx_len < 0 && (errno == EINTR || errno == EAGAIN));
|
|
|
|
return tx_len;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gps_state_thread( void *arg )
|
|
{
|
|
GpsState *state = (GpsState *) arg;
|
|
NmeaReader reader[1];
|
|
int epoll_fd = epoll_create(2);
|
|
int started = 0;
|
|
int gps_fd = state->fd;
|
|
int control_fd = state->control[1];
|
|
int nn, ret;
|
|
char buff[32];
|
|
static int cnt=0;
|
|
int wret = 0;
|
|
//static int ack=0;
|
|
nmea_reader_init( reader );
|
|
memset(&GsaPrn, 0, sizeof(GsaPrn));
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
// register control file descriptors for polling
|
|
epoll_register( epoll_fd, control_fd );
|
|
epoll_register( epoll_fd, gps_fd );
|
|
|
|
D("Enter : %s",__FUNCTION__);
|
|
|
|
// now loop
|
|
for (;;)
|
|
{
|
|
struct epoll_event events[2];
|
|
int ne, nevents;
|
|
|
|
nevents = epoll_wait( epoll_fd, events, 2, -1 );
|
|
|
|
if (nevents < 0)
|
|
{
|
|
if (errno != EINTR)
|
|
D("epoll_wait() unexpected error: %s", strerror(errno));
|
|
|
|
continue;
|
|
}
|
|
|
|
//D("gps thread received %d events", nevents);
|
|
for (ne = 0; ne < nevents; ne++)
|
|
{
|
|
reader[0].sv_status.size = sizeof(GpsSvStatus);
|
|
if ((events[ne].events & (EPOLLERR | EPOLLHUP)) != 0)
|
|
{
|
|
D("EPOLLERR or EPOLLHUP after epoll_wait() !?");
|
|
return;
|
|
}
|
|
|
|
if ((events[ne].events & EPOLLIN) != 0)
|
|
{
|
|
int fd = events[ne].data.fd;
|
|
|
|
if (fd == control_fd)
|
|
{
|
|
char cmd = 255;
|
|
int ret;
|
|
D("Event : gps control fd event %d",fd);
|
|
|
|
do
|
|
{
|
|
ret = read( fd, &cmd, 1 );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
D("Event : gps control cmd %d",cmd);
|
|
if (cmd == CMD_QUIT)
|
|
{
|
|
D("CMD : TD gps quitting on demand");
|
|
return;
|
|
}
|
|
else if (cmd == CMD_START)
|
|
{
|
|
if (!started)
|
|
{
|
|
D("CMD : TD gps starting navigation");
|
|
memset(fixed,0,sizeof(fixed));
|
|
started = 1;
|
|
nmea_reader_set_callback( reader, state->callbacks.location_cb);
|
|
//reader->fix.flags = 0x1f;
|
|
//update_gps_location(&reader->fix);
|
|
}
|
|
}
|
|
else if (cmd == CMD_STOP)
|
|
{
|
|
if (started)
|
|
{
|
|
if(tdconfig.power_flag != TD_OFF)
|
|
{
|
|
PowerOff();
|
|
D("CMD : TD gps stopping Power off");
|
|
}
|
|
tdconfig.power_flag = TD_OFF;
|
|
|
|
started = 0;
|
|
nmea_reader_set_callback( reader, NULL );
|
|
}
|
|
}
|
|
else if(cmd == CMD_ENABLE_GPS && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_GPS");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_GPS_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_ENABLE_BD && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_BDS");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_BD_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_ENABLE_GL && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_GLO");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_GL_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_ENABLE_BD_GP && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_BDS_GPS");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_BD_GP_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_ENABLE_GP_GL && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_GPS_GLO");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_GP_GL_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_ENABLE_BD_GL && update_mode == 0)//
|
|
{
|
|
D("CMD : CMD_ENABLE_BDS_GLO");
|
|
memset(fixed,0,sizeof(fixed));
|
|
write( gps_fd, CMD_BD_GL_HOT, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == GPS_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : GPS_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_GPS_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == GL_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : GLO_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_GL_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
|
|
else if(cmd == BD_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : BD_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_BD_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == BD_GL_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : BDS_GLO_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_BD_GL_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == BD_GP_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : BDS_GPS_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_BD_GP_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == GP_GL_COLD && update_mode == 0)
|
|
{
|
|
D("CMD : GPS+GLO_COLD");
|
|
memset(fixed,0,sizeof(fixed));
|
|
|
|
write( gps_fd, CMD_GP_GL_COLD, SET_CMD_TDMODULE_LEN);
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_AGPS && update_mode == 0)
|
|
{
|
|
if (started)
|
|
{
|
|
D("CMD : CMD_AGPS");
|
|
write_agps_data(gps_fd);
|
|
}
|
|
}
|
|
else if(cmd == CMD_UPDATE_TD && update_mode == 0)
|
|
{
|
|
D("CMD : CMD_UPDATE_TD update_td_handler");
|
|
Creat_update_thread();
|
|
update_mode = 1;
|
|
memset(fixed,0,sizeof(fixed));
|
|
memset(reader->sv_status.sv_list, 0, sizeof(reader->sv_status.sv_list));
|
|
}
|
|
else if(cmd == CMD_SENT_TO_CHIP && update_mode == 0)
|
|
{
|
|
D("CMD : SENT_CMD_TO_CHIP");
|
|
|
|
wret = write( gps_fd, cmd_buff, cmd_length);
|
|
}
|
|
}
|
|
else if (fd == gps_fd)
|
|
{
|
|
//for (;;)
|
|
{
|
|
ret = read( fd, buff, sizeof(buff) );
|
|
|
|
if (ret < 0)
|
|
{ cnt++;
|
|
if(cnt<6)
|
|
D("ret%d",ret);
|
|
if (errno == EINTR)
|
|
continue;
|
|
if (errno != EWOULDBLOCK)
|
|
D("error while reading from gps daemon socket: %s:", strerror(errno));
|
|
break;
|
|
}
|
|
|
|
for(nn = 0; nn < ret; nn++)
|
|
{
|
|
SDBP_Prase(buff[nn]);
|
|
}
|
|
|
|
for (nn = 0; nn < ret; nn++)
|
|
{
|
|
nmea_reader_addc( reader, buff[nn] );
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
D("epoll_wait() returned unkown fd %d ?", fd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
gps_state_init( GpsState *state, GpsCallbacks *callbacks )
|
|
{
|
|
static int isInitialized = 0;
|
|
state->init = 1;
|
|
state->control[0] = -1;
|
|
state->control[1] = -1;
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
if( (callbacks != NULL) && (callbacks->size == sizeof(GpsCallbacks)) )
|
|
{
|
|
state->callbacks = *callbacks;
|
|
}
|
|
else
|
|
{
|
|
D("Error : gps_state_init Callback Function Error");
|
|
return;
|
|
}
|
|
|
|
if(isInitialized == 1)
|
|
{
|
|
D(" GPS/BD has been initialized!!!");
|
|
return;
|
|
}
|
|
isInitialized=1;
|
|
|
|
if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, state->control ) < 0 )
|
|
{
|
|
D("could not create thread control socket pair: %s", strerror(errno));
|
|
goto Fail;
|
|
}
|
|
|
|
callbacks->set_capabilities_cb(GPS_CAPABILITY_NAV_MESSAGES);
|
|
state->thread = callbacks->create_thread_cb( "gps_state_thread", gps_state_thread, state );
|
|
|
|
if ( !state->thread )
|
|
{
|
|
D("Error : Fail to create gps thread: %s", strerror(errno));
|
|
goto Fail;
|
|
}
|
|
|
|
return;
|
|
|
|
Fail:
|
|
td_gps_state_done( state );
|
|
}
|
|
|
|
void PowerOn(void)
|
|
{
|
|
D("Enter Normal WorkMode");
|
|
UartTxData((unsigned char*)"on",2);
|
|
usleep(150000);
|
|
|
|
if(tdconfig.fast_fix)
|
|
UartTxData(fix_dop100,15);
|
|
tdconfig.power_flag = TD_ON;
|
|
}
|
|
|
|
|
|
|
|
void PowerOff(void)
|
|
{
|
|
|
|
if(update_mode==0){
|
|
|
|
|
|
if(tdconfig.power_flag == TD_ON)
|
|
{
|
|
D("Enter Standby WorkMode");
|
|
UartTxData((unsigned char*)"off",3);
|
|
usleep(150000);
|
|
UartTxData(chip_standby,9);
|
|
tdconfig.power_flag = TD_OFF;
|
|
}
|
|
}else
|
|
D(" TD chip is updateing not poweroff");
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
td_gps_init(GpsCallbacks *callbacks)
|
|
{
|
|
|
|
GpsState *s = _gps_state;
|
|
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
if ((!s->init) || (s->fd < 0))
|
|
gps_state_init(s, callbacks);
|
|
|
|
// if (s->fd < 0)
|
|
// return -1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
td_gps_cleanup(void)
|
|
{
|
|
GpsState *s = _gps_state;
|
|
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
char cmd = CMD_STOP;
|
|
int ret;
|
|
if(update_mode==1)
|
|
return;
|
|
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, 1 );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
// if (s->init)
|
|
// td_gps_state_done(s);
|
|
}
|
|
|
|
static int
|
|
td_gps_start()
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
GpsState *s = _gps_state;
|
|
PowerOn();
|
|
|
|
if (!s->init)
|
|
{
|
|
D("%s: called with uninitialized state !!", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
td_gps_state_start(s);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
td_gps_stop()
|
|
{
|
|
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
GpsState *s = _gps_state;
|
|
td_mode.on_need=0;
|
|
if (!s->init)
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)
|
|
{
|
|
D("%s: called with uninitialized state !!", __FUNCTION__);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
td_gps_state_stop(s);
|
|
PowerOff();
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
td_gps_inject_time(GpsUtcTime time, int64_t timeReference, int uncertainty)
|
|
{
|
|
if(tdconfig.power_flag == TD_ON)
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s(%d,%lld,%d)", __FUNCTION__,(int)time,(long long)timeReference,uncertainty);
|
|
|
|
int gps_fd = _gps_state->fd;
|
|
write_agps_data(gps_fd);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
td_gps_inject_location(double latitude, double longitude, float accuracy)
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s(%f,%f,%f)", __FUNCTION__,latitude,longitude,accuracy);
|
|
|
|
int gps_fd = _gps_state->fd;
|
|
unsigned char pack_loc[24];
|
|
pack_sdbp_location(latitude,longitude,accuracy,pack_loc);
|
|
|
|
write(gps_fd,pack_loc,24);
|
|
write_agps_data(gps_fd);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
td_gps_delete_aiding_data(GpsAidingData flags)
|
|
{
|
|
(void)flags;
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
UartTxData(cold_start1,9);
|
|
UartTxData(cold_start2,10);
|
|
usleep(150000);
|
|
return;
|
|
}
|
|
|
|
static int td_gps_set_position_mode(GpsPositionMode mode, GpsPositionRecurrence recurrence,
|
|
unsigned int min_interval, unsigned int preferred_accuracy, unsigned int preferred_time)
|
|
{
|
|
char cmd = 0x00;
|
|
int ret ;
|
|
GpsState *s = _gps_state;
|
|
int t_mode=0;
|
|
time_t time1,time2;
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
if(update_mode == 1)
|
|
return 0;
|
|
|
|
D("Set : Fix Mode:0x%X %d %d %d %d", mode,recurrence,min_interval,preferred_accuracy,preferred_time);
|
|
|
|
td_mode.on_need=1;
|
|
td_mode.work=0;
|
|
|
|
UartTxData((unsigned char*)"mode",4);
|
|
if(tdconfig.fast_fix)
|
|
UartTxData(fix_dop100,15);
|
|
|
|
time1 = time(NULL);
|
|
|
|
|
|
while(td_mode.work==0)
|
|
{
|
|
usleep(200000);
|
|
time2 = time(NULL);
|
|
if((time2-time1)>5){
|
|
D("Error : TD gps not work break!!!");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
t_mode = td_mode.nv_mode;
|
|
|
|
if(t_mode==(int)mode)
|
|
{
|
|
D("Warning : POSITION MODE SET ALREADY");
|
|
return 0;
|
|
}
|
|
switch(mode&0xff)
|
|
{
|
|
case 0x02:cmd = CMD_START_AGPS;break;
|
|
|
|
case 0x10:cmd = CMD_ENABLE_BD;break;
|
|
case 0x20:cmd = CMD_ENABLE_GPS;break;
|
|
case 0x30:cmd = CMD_ENABLE_BD_GP;break;
|
|
case 0x40:cmd = CMD_ENABLE_GL;break;
|
|
case 0x50:cmd = CMD_ENABLE_BD_GL;break;
|
|
case 0x60:cmd = CMD_ENABLE_GP_GL;break;
|
|
|
|
case 0x11:cmd = BD_COLD;break;
|
|
case 0x21:cmd = GPS_COLD;break;
|
|
case 0x31:cmd = BD_GP_COLD;break;
|
|
case 0x41:cmd = GL_COLD;break;
|
|
case 0x51:cmd = BD_GL_COLD;break;
|
|
case 0x61:cmd = GP_GL_COLD;break;
|
|
|
|
//default:cmd = 0x00;D("Warning : Undefined work mode!!!");break;
|
|
default:cmd = 0x00;break;
|
|
}
|
|
|
|
if(cmd != 0x00)
|
|
{
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, sizeof(cmd) );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int td_set_update_mode(void)
|
|
{
|
|
char cmd;
|
|
int ret ;
|
|
GpsState *s = _gps_state;
|
|
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
cmd = CMD_UPDATE_TD;
|
|
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, sizeof(cmd) );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CheckSDBPData(const unsigned char *pdata,const int len)
|
|
{
|
|
int i;
|
|
//least sdbp data lenth is 8
|
|
if(len < 8)return 0;
|
|
|
|
for(i = 0;i < len - 8 + 5;i ++)
|
|
{
|
|
if(pdata[i] == 0x23 && pdata[i + 1] == 0x3e)
|
|
{
|
|
if(pdata[i + 2] == 0x02 && pdata[i + 3] == 0x04)
|
|
{
|
|
tdconfig.power_flag = TD_OFF;
|
|
D("Warning : Send Standby Mode CMD");
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CheckStringCmd(const unsigned char *pdata,const int len)
|
|
{
|
|
if(pdata[0] == '$' && pdata[len - 1] == '\n')
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void send_cmd_to_TDchip(char cmd)
|
|
{
|
|
int ret ;
|
|
GpsState *s = _gps_state;
|
|
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
|
|
do
|
|
{
|
|
ret = write( s->control[0], &cmd, sizeof(cmd) );
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
return ;
|
|
}
|
|
|
|
static void command_handler(const char *data, const int length)
|
|
{
|
|
//int i = 0;
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
memset(cmd_buff,0,CMD_MAX_LEN);
|
|
|
|
if(length < CMD_MAX_LEN)
|
|
{
|
|
memcpy(cmd_buff, data, length);
|
|
cmd_length = length;
|
|
}
|
|
else
|
|
{
|
|
D("length > CMD_MAX_LEN %d",length);
|
|
memcpy(cmd_buff, data, CMD_MAX_LEN);
|
|
cmd_length = CMD_MAX_LEN;
|
|
}
|
|
send_cmd_to_TDchip(CMD_SENT_TO_CHIP);
|
|
|
|
}
|
|
|
|
int td_xtra_init( GpsXtraCallbacks *callbacks )
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
if(callbacks == 0)return 0;
|
|
return 0;
|
|
}
|
|
|
|
unsigned char img_data[1200*1024];
|
|
int img_length = 0;
|
|
int td_inject_xtra_data( char *data, int length )
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s", __FUNCTION__);
|
|
|
|
if(data == NULL || length <= 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
int ret;
|
|
int is_img_data1 = 0;
|
|
int is_img_data2 = 0;
|
|
|
|
if(update_mode == 1)
|
|
return 0;
|
|
|
|
is_img_data1 = CheckImgData1((unsigned char *)data, 0, length);
|
|
|
|
if(is_img_data1)
|
|
{
|
|
img_length = length - 4;
|
|
//img_data = (unsigned char *)data + 4;
|
|
memcpy(img_data, data+4,length-4);
|
|
D("Succeed : Img data1 size is %d",img_length);
|
|
return 1;
|
|
}
|
|
|
|
is_img_data2 = CheckImgData2((unsigned char *)data, 0, length);
|
|
if(is_img_data2)
|
|
{
|
|
memcpy(img_data+img_length, data+4,length-4);
|
|
img_length += length - 4;
|
|
//img_data = (unsigned char *)data + 4;
|
|
|
|
if(img_length > 0)
|
|
{
|
|
D("Succeed : Img total data size is %d",img_length);
|
|
|
|
if((ret = update_td_init((unsigned char *)img_data, img_length, _gps_state[0].fd)) < 0)
|
|
{
|
|
D("Error : update_td_init failed %d .",ret);
|
|
return ret;
|
|
}
|
|
img_length =0;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
|
|
if(is_img_data2)
|
|
{
|
|
td_set_update_mode();
|
|
return 1;
|
|
}
|
|
|
|
|
|
if(CheckSDBPData((unsigned char *)data,length))
|
|
{
|
|
command_handler(data, length);
|
|
//D("Succeed : Send SDBP Data To Chip TD1030");
|
|
}
|
|
else if(CheckStringCmd((unsigned char *)data,length))
|
|
{
|
|
command_handler(data, length);
|
|
//D("Succeed : Send String CMD To Chip TD1030");
|
|
}
|
|
else
|
|
{
|
|
//td_update_rtcm(data, length);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static const GpsXtraInterface xtraInterface =
|
|
{
|
|
sizeof(GpsXtraInterface),
|
|
td_xtra_init,
|
|
td_inject_xtra_data,
|
|
};
|
|
static const void *
|
|
td_gps_get_extension(const char *name)
|
|
{
|
|
if (GetDebugMaskBit(D_FUCTION) == 1)D("Enter : %s(%s)", __FUNCTION__,name);
|
|
|
|
if(0 == strcmp(name, GPS_XTRA_INTERFACE))
|
|
{
|
|
return &xtraInterface;
|
|
}
|
|
|
|
// if(0 == strcmp(name, AGPS_INTERFACE))
|
|
// {
|
|
// return &tdAGpsInterface;
|
|
// }
|
|
|
|
// if(0 == strcmp(name, GPS_NI_INTERFACE))
|
|
// {
|
|
// return &tdGpsNiInterface;
|
|
// }
|
|
|
|
// if (0 == strcmp(name, GPS_DEBUG_INTERFACE))
|
|
// {
|
|
// return &tdGpsDebugInterface;
|
|
// }
|
|
|
|
// if (0 == strcmp(name, AGPS_RIL_INTERFACE))
|
|
// {
|
|
// return &tdAGpsRilInterface;
|
|
// }
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static GpsInterface hardwareGpsInterface =
|
|
{
|
|
sizeof(GpsInterface),
|
|
td_gps_init,
|
|
td_gps_start,
|
|
td_gps_stop,
|
|
td_gps_cleanup,
|
|
td_gps_inject_time,
|
|
td_gps_inject_location,
|
|
td_gps_delete_aiding_data,
|
|
td_gps_set_position_mode,
|
|
td_gps_get_extension,
|
|
};
|
|
|
|
void InitTdconfig(void)
|
|
{
|
|
memset(&tdconfig, 0, sizeof(tdconfig));
|
|
}
|
|
|
|
void InitTdModule(void)
|
|
{
|
|
GpsState *state = _gps_state;
|
|
|
|
D("Ver:2020-11");
|
|
LoadConfigFile();
|
|
|
|
//VCC LDO enable
|
|
//system("echo -wmode 138 0 > /sys/devices/virtual/misc/mtgpio/pin");
|
|
//system("echo -wdir 138 1 > /sys/devices/virtual/misc/mtgpio/pin");
|
|
//system("echo -wdout 138 1 > /sys/devices/virtual/misc/mtgpio/pin");
|
|
|
|
usleep(150000);
|
|
|
|
state->fd = TdUartOpen();
|
|
|
|
if(state->fd == -1)
|
|
{
|
|
state->init = 0;
|
|
return;
|
|
}
|
|
|
|
usleep(500000);
|
|
|
|
switch(tdconfig.uartboadrate)
|
|
{
|
|
case 9600:
|
|
UartTxData(baud9600,14);
|
|
usleep(50000);
|
|
UartTxData(baud9600,14);
|
|
usleep(50000);
|
|
UartTxData(baud9600,14);
|
|
break;
|
|
|
|
case 115200:
|
|
UartTxData(baud115200,14);
|
|
usleep(50000);
|
|
UartTxData(baud115200,14);
|
|
usleep(50000);
|
|
UartTxData(baud115200,14);
|
|
break;
|
|
|
|
case 19200:
|
|
UartTxData(baud19200,14);
|
|
usleep(50000);
|
|
UartTxData(baud19200,14);
|
|
usleep(50000);
|
|
UartTxData(baud19200,14);
|
|
break;
|
|
|
|
case 38400:
|
|
UartTxData(baud38400,14);
|
|
usleep(50000);
|
|
UartTxData(baud38400,14);
|
|
usleep(50000);
|
|
UartTxData(baud38400,14);
|
|
break;
|
|
|
|
case 57600:
|
|
UartTxData(baud57600,14);
|
|
usleep(50000);
|
|
UartTxData(baud57600,14);
|
|
usleep(50000);
|
|
UartTxData(baud57600,14);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SetApUartbaud(tdconfig.uartboadrate);
|
|
|
|
UartTxData((unsigned char*)"init",4);
|
|
usleep(150000);
|
|
|
|
switch(tdconfig.gnss_mode)
|
|
{
|
|
case 1:UartTxData(gnssmode_bds,15);break;
|
|
case 2:UartTxData(gnssmode_gps,15);break;
|
|
case 3:UartTxData(gnssmode_gps_bds,15);break;
|
|
case 4:UartTxData(gnssmode_gl,15);break;
|
|
case 5:UartTxData(gnssmode_bds_gl,15);break;
|
|
case 6:UartTxData(gnssmode_gps_gl,15);break;
|
|
default:UartTxData(gnssmode_gps_bds,15);break;
|
|
}
|
|
|
|
usleep(150000);
|
|
if(tdconfig.fast_fix)
|
|
UartTxData(fix_dop100,15);
|
|
|
|
// usleep(150000);
|
|
// UartTxData(chip_standby,9);
|
|
// tdconfig.power_flag = TD_OFF;
|
|
|
|
D("Init Module END");
|
|
}
|
|
|
|
const GpsInterface *get_gps_interface()
|
|
{
|
|
static int check = 0;
|
|
if(check == 0)
|
|
{
|
|
check = 1;
|
|
InitTdModule();
|
|
}
|
|
|
|
return &hardwareGpsInterface;
|
|
}
|
|
|
|
static int open_gps(const struct hw_module_t *module, char const *name,
|
|
struct hw_device_t **device)
|
|
{
|
|
D("Enter : %s name = %s", __FUNCTION__,name);
|
|
|
|
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 = 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 = 2,
|
|
.version_minor = 0,
|
|
.id = GPS_HARDWARE_MODULE_ID,
|
|
.name = "TD1030",
|
|
.author = "Techtotop",
|
|
.methods = &gps_module_methods,
|
|
};
|
|
|
|
static pthread_t update_thread_id = 0;
|
|
|
|
void Creat_update_thread(void)
|
|
{
|
|
int ret;
|
|
pthread_attr_t attr;
|
|
|
|
pthread_attr_init (&attr);
|
|
ret = pthread_create(&update_thread_id, &attr, update_td_handler_thread, NULL);
|
|
|
|
if ( ret != 0 )
|
|
{
|
|
D("Error : Could not create thread:update_td_handler_thread");
|
|
return;
|
|
}
|
|
else
|
|
D("Succeed : create thread:update_td_handler_thread");
|
|
}
|
|
|