[Feature][ZXW-159] add gnss firmware update function

Only Configure:No
Affected branch:master
Affected module:GNSS
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I2e523bd6758828907c7cc292ae9ee787fac7d855
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
index 6ef9412..2ba0f08 100755
--- a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
+++ b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
@@ -194,6 +194,7 @@
         liblynq-at-factory \
         liblynq-gpio \
         liblynq-irq \
+        liblynq-at-common \
 	"
 
 zxic_lib += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', 'libril', 'libtelsvr', d)}"
@@ -273,6 +274,7 @@
         lynq-qser-autosuspend-demo \
         lynq-gpio-demo \
         lynq-irq-demo \
+        lynq-gnss-update \
         "
 
 zxic_app_open += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', 'rild', '', d)}"
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
index 46f2a37..469ee92 100755
--- a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
+++ b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/liblynq-qser-gnss/liblynq-qser-gnss.bb
@@ -17,9 +17,11 @@
 BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"

 BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"

 

+FILES_${PN} += "${bindir} /data/gnss_update"

+

 EXTRA_OEMAKE = "'TARGET_PLATFORM = ${TARGET_PLATFORM}'"

 

-FILES_${PN} = "${base_libdir}/*.so "

+FILES_${PN} += "${base_libdir}/*.so "

 

 FILES_${PN}-dev = "/test \

                    ${includedir}"

@@ -45,6 +47,11 @@
     if [ -d "${WORKONSRC}" ] ; then

         install -d ${D}${includedir}/

         cp -raf ${SRC-DIR}/include/ ${D}${includedir}/

+        install -d ${D}/data/gnss_update

+	    install -m 644 ${WORKONSRC}UC6228CI-R3.2.10.100Build8019_mfg.pkg ${D}/data/gnss_update

+        install -m 644 ${WORKONSRC}bootloader_r3.0.0_build6773_uartboot_921600.pkg ${D}/data/gnss_update

+        ln -sf ./UC6228CI-R3.2.10.100Build8019_mfg.pkg ${D}/data/gnss_update/firmware.pkg

+        ln -sf ./bootloader_r3.0.0_build6773_uartboot_921600.pkg ${D}/data/gnss_update/bootloader.pkg

     fi 

 }

 

diff --git a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/lynq-gnss-update.cpp b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/lynq-gnss-update.cpp
new file mode 100755
index 0000000..29abd03
--- /dev/null
+++ b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/files/lynq-gnss-update.cpp
@@ -0,0 +1,1337 @@
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <sched.h>
+#include <limits.h>
+#include <linux/serial.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define RTM_FILE_NAME "rtm.bin"
+
+#define PARA_ERR                -1
+#define FILE_CHECK_ERR          -2
+#define ENTER_UPDATE_MODE_ERR   -3
+#define UPDATE_ERR              -4
+#define UART_DEV_ERR            -5
+
+#define XMODEM_SOH 0x01
+#define XMODEM_STX 0x02
+#define XMODEM_EOT 0x04
+#define XMODEM_ACK 0x06
+#define XMODEM_NAK 0x15
+#define XMODEM_CAN 0x18
+#define XMODEM_CRC_CHR	'C'
+#define XMODEM_CRC_SIZE 2		/* Crc_High Byte + Crc_Low Byte */
+#define XMODEM_FRAME_ID_SIZE 2 		/* Frame_Id + 255-Frame_Id */
+#define XMODEM_DATA_SIZE_SOH 128  	/* for Xmodem protocol */
+#define XMODEM_DATA_SIZE_STX 1024 	/* for 1K xmodem protocol */
+#define USE_1K_XMODEM 1  		/* 1 for use 1k_xmodem 0 for xmodem */
+#define	TIMEOUT_USEC	0
+#define	TIMEOUT_SEC		10
+
+#if (USE_1K_XMODEM)
+#define XMODEM_DATA_SIZE 	XMODEM_DATA_SIZE_STX
+#define XMODEM_HEAD		XMODEM_STX
+#else
+#define XMODEM_DATA_SIZE 	XMODEM_DATA_SIZE_SOH
+#define XMODEM_HEAD 		XMODEM_SOH
+#endif
+
+
+/******************************************************************************
+ * 时间处理相关的宏
+ *****************************************************************************/
+// 时间超时标志
+int timeout_sign = 1;
+// 获取当前时间
+#define GET_TIME()  { gettimeofday(&time_m, NULL); \
+    time_m.tv_sec += TIMEOUT_SEC;\
+}
+// 设置从循环中退出的时间
+#define SET_TIME_OUT(x)  { gettimeofday(&time_m, NULL); \
+    time_m.tv_sec += x;\
+}
+// 检测时间是否超时,超时则退出当前函数
+#define CHK_TIME()  { gettimeofday(&time_n, NULL); \
+    if(time_n.tv_sec > time_m.tv_sec) { \
+    printf("\ntimeout!!!\n\n");\
+    close(fd); \
+    return ret; \
+} \
+}
+// 检测时间是否超时,超时则退出当前循环
+#define CHK_TIME_BREAK()  { gettimeofday(&time_n, NULL); \
+    if(time_n.tv_sec > time_m.tv_sec) { \
+    timeout_sign = 1; 	\
+    printf("\ntimeout!!!\n\n");\
+    break; \
+} \
+}
+// 检测延时是否到达,到达则退出当前循环
+#define DELAY_TIME_BREAK()  { gettimeofday(&time_n, NULL); \
+    if(time_n.tv_sec > time_m.tv_sec) { \
+    timeout_sign = 1; 	\
+    break; \
+} \
+}
+
+// 检测时间是否超时,超时则退出当前函数
+#define CHK_TIME1()  { gettimeofday(&time_n, NULL); \
+    if(time_n.tv_sec > time_m.tv_sec) { \
+    printf("\ntimeout!!!\n\n");\
+    if(datafile != NULL) \
+    fclose(datafile); \
+    return ret; \
+} \
+}
+
+
+/******************************************************************************
+ * APData 相关定义、声明
+ *****************************************************************************/
+// APData 数据头部定义
+typedef struct {
+    unsigned int  ih_magic;		// Image Header Magic Number
+    unsigned int  ih_dcrc;		// Image Data CRC checksum
+    unsigned int  ih_time;		// Image Creation Timestamp
+    unsigned int  ih_size;		// Image Data Size
+    unsigned int  ih_compress;		// Image Header compress or not:0, not compress
+    unsigned int  pkg_flash_addr;	// flash memory offset for package
+    unsigned int  pkg_run_addr;		// Run time address for this package
+    unsigned int  ih_hcrc;		// Image Header CRC checksum
+} uc_image_header_t;
+
+// APData 数据头部长度
+#define HEADERLEN 32
+// APData 接收状态类型
+typedef enum ReceStat{
+    WAIT_FD = 1,
+    WAIT_FC,
+    WAIT_FB,
+    WAIT_FA,
+    RECE_HEADER,
+    RECE_DATA,
+} RecvStat_t;
+// APData 接收状态变量
+static RecvStat_t recvStat = WAIT_FD;
+// APData 接收状态变量
+static int isStartReceive = 0;
+// APData 开始接收
+void af_start_receive();
+// APData 停止接收,在数据接收完成或出错时调用
+void af_stop_receive();
+// 获取isStartReceive 变量值
+int af_is_start_receive();
+// APData 数据接收入口
+int af_add_char(char *file, unsigned char c);
+// 校验 APData 数据头
+int af_check_header(unsigned char *pbuf, unsigned int len);
+// 校验 APData 数据区
+int af_check_data(unsigned int * pbuf, unsigned int len);
+// 获取 APData 数据长度
+int af_get_data_len();
+// APData 数据接收缓存
+
+int check_file(char *fname);
+
+/******************************************************************************
+ * 与接收机串口通讯相关定义、声明
+ *****************************************************************************/
+// select功能使用变量
+static int use_select = 1;
+// 初始化串口资源
+int initial_serialPort(char * serial_device);
+// 设置串口波特率
+static int set_baudrate(int fd, int baudrate);
+// 检测串口数据
+static int select_read(int fd, int timeout);
+// 读取串口数据
+static ssize_t deal_read(int fd, void *buf, size_t count);
+// 向接收机发送串口数据
+static void gps_dev_send(int fd, char *msg);
+// 通过xmodem协议向接收机发送串口数据
+int xmodem_send(int fd, char *fname);
+
+/******************************************************************************
+ * apflash 功能函数
+ *****************************************************************************/
+// 检测接收机发送的'YC'信号,如果收到,则标志着接收机进入boot模式,并可以通过xmodem发送数据
+int check_YC(char newchar);
+// 获取 APData 数据, 应该在接收机定位且星历数据接收完整时获取
+int getAPData(int fd, char *file);
+// 向接收机发送 APData 数据,有效的APData数据可以让CI模块迅速定位
+int sendAPData(int fd, char *ap);
+// 校验 APData 数据文件
+int checkAPData(char *apFile);
+// 为接收机加载BootLoader,该流程执行时,需要根据终端提示,给接收机下电和上电,确保接收机进入boot模式
+int downloadBL(int fd, char *bl);
+// 为接收机加载Firmware,该流程必须在加载BootLoader之后进行
+int downloadFW(int fd, char *fw);
+unsigned int recv_buf[1024 * 2];
+unsigned char *pbuf;
+int data_len;
+volatile int nmea_state = 0;
+volatile int nmea_reading = 0;
+// 校验文件
+void printGetapUsage(char *app)
+{
+    printf("\n%s getap -d receiverPort [-b baudrate] [-h] -a apfile \n", app);
+    printf("\tfunction: read APData from receiver\n");
+    printf("\tparas:\n");
+    printf("\t\treceiverPort: Port that connected to receiver\n");
+    printf("\t\tbaudrate: baudrate of receiverPort\n");
+}
+
+void printSendapUsage(char *app)
+{
+    printf("\n%s sendap -d receiverPort [-b baudrate] [-h] -a apfile\n", app);
+    printf("\tfunction: send APData to receiver\n");
+    printf("\tparas:\n");
+    printf("\t\treceiverPort: Port that connected to receiver\n");
+    printf("\t\tbaudrate: baudrate of receiverPort\n");
+}
+
+void printCheckapUsage(char *app)
+{
+    printf("\n%s checkap -a apfile [-h]\n", app);
+    printf("\tfunction: check APData\n");
+    printf("\tparas:\n");
+    printf("\t\tapfile: APData file\n");
+}
+
+void printDownloadblUsage(char *app)
+{
+    printf("\n%s downbl -d receiverPort [-b baudrate] -l bootloader [-h]\n", app);
+    printf("\tfunction: download bootloader to receiver\n");
+    printf("\tparas:\n");
+    printf("\t\treceiverPort: Port that connected to receiver\n");
+    printf("\t\tbaudrate: baudrate of receiverPort\n");
+    printf("\t\tbootloader: bootloader file\n");
+}
+
+void printDownloadfwUsage(char *app)
+{
+    printf("\n%s downfw -d receiverPort [-b baudrate] -f firmware [-h]\n", app);
+    printf("\tfunction: download firmware to receiver\n");
+    printf("\tparas:\n");
+    printf("\t\treceiverPort: Port that connected to receiver\n");
+    printf("\t\tbaudrate: baudrate of receiverPort\n");
+    printf("\t\tfirmware: firmware file\n");
+}
+
+void printUsage(char *app)
+{
+    printGetapUsage(app);
+    printSendapUsage(app);
+    printCheckapUsage(app);
+    printDownloadblUsage(app);
+    printDownloadfwUsage(app);
+}
+
+int exec_cmd(const char *cmd, char *result)
+{
+    FILE *pipe = popen(cmd, "r");
+    if(!pipe)
+        return -1;
+
+    char buffer[256] = {0};
+    while(!feof(pipe))
+    {
+        if(fgets(buffer, 256, pipe))
+        {
+            memset(buffer, 0, sizeof(buffer));
+        }
+    }
+    pclose(pipe);
+    return 0;
+}
+
+int mopen_open_gps(int state)
+{
+    char cmd[128] = "echo '86' > /sys/class/gpio/export && cd /sys/class/gpio/gpio86";
+    int ret;
+
+    if(0 == state)
+    {
+        nmea_state = 0;
+        for(int cont = 0; cont < 200; cont++)
+        {
+            if (nmea_reading == 0)
+            {
+                break;
+            }
+            usleep(10000);
+        }
+        ret = exec_cmd(cmd,NULL);
+        if(0 != ret)
+        {
+            printf("stop fail %x\n", ret);
+        }
+        char cmd2[128] = "echo '0' > /sys/class/gpio/gpio86/value && echo '86' > /sys/class/gpio/unexport";
+        ret = exec_cmd(cmd2,NULL);
+        if(0 != ret)
+        {
+            printf("stop fail %x\n", ret);
+        }
+    }
+
+    if(1 == state)
+    {
+        nmea_state = 1;
+
+        ret = exec_cmd(cmd,NULL);
+        if(0 != ret)
+        {
+            printf("start fail %x\n", ret);
+            return -1;
+        }
+        char cmd3[128] = "echo '1' > /sys/class/gpio/gpio86/value && echo '86' > /sys/class/gpio/unexport";
+        ret = exec_cmd(cmd3,NULL);
+        if(0 != ret)
+        {
+            printf("start fail %x\n", ret);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+int main(int argc, char *argv[])
+{
+    int c;
+    int ret = 0;
+    int fd = -1;
+    int paraMask = 0;
+    int baud = 115200;
+    char devPort[200] = {0};
+    char fw[200] = {0};
+    char bl[200] = {0};
+    char ap[200] = {0};
+    int func = 0; // 1:getap, 2:sendap, 3:downbl, 4:downfw, 5:checkap
+
+    // Verify arguments
+    if (argc < 2) {
+        printf("Usage:\n");
+        printUsage(argv[0]);
+        exit(1);
+    }
+
+    if(strcmp(argv[1], "getap") == 0) {
+        func = 1;
+        paraMask = 1;
+    } else if (strcmp(argv[1], "sendap") == 0) {
+        func = 2;
+        paraMask = 1;
+    } else if (strcmp(argv[1], "downbl") == 0) {
+        func = 3;
+        paraMask = 9;
+    } else if (strcmp(argv[1], "downfw") == 0) {
+        func = 4;
+        paraMask = 5;
+    } else if (strcmp(argv[1], "checkap") == 0) {
+        func = 5;
+        paraMask = 16;
+    } else {
+        printf("Usage:\n");
+        printUsage(argv[0]);
+        exit(1);
+    }
+
+    for(;;) {
+        opterr = 0;
+        c = getopt(argc, argv, "d:b:f:l:a:h");
+        if(c < 0)
+            break;
+        switch(c) {
+        case 'd':
+            snprintf(devPort, 200, "%s", optarg);
+            printf("receiver port: %s\n", devPort);
+            paraMask &= ~1;
+            break;
+        case 'b':
+            baud = atoi(optarg);
+            printf("baud rate: %d\n", baud);
+            break;
+        case 'f':
+            snprintf(fw, 200, "%s", optarg);
+            printf("firmware: %s\n", fw);
+            paraMask &= ~4;
+            break;
+        case 'l':
+            snprintf(bl, 200, "%s", optarg);
+            printf("bootloader: %s\n", bl);
+            paraMask &= ~8;
+            break;
+        case 'a':
+            snprintf(ap, 200, "%s", optarg);
+            printf("apdata file: %s\n", ap);
+            paraMask &= ~16;
+            break;
+        case 'h':
+        default:
+            printf("Usage:\n");
+            if (func == 1)
+                printGetapUsage(argv[0]);
+            else if (func == 2)
+                printSendapUsage(argv[0]);
+            else if (func == 3)
+                printDownloadblUsage(argv[0]);
+            else if (func == 4)
+                printDownloadfwUsage(argv[0]);
+            else if (func == 5)
+                printCheckapUsage(argv[0]);
+            else
+                printUsage(argv[0]);
+            exit(1);
+        }
+    }
+    if (paraMask) {
+        if (func == 1)
+            printGetapUsage(argv[0]);
+        else if (func == 2)
+            printSendapUsage(argv[0]);
+        else if (func == 3)
+            printDownloadblUsage(argv[0]);
+        else if (func == 4)
+            printDownloadfwUsage(argv[0]);
+        else if (func == 5)
+            printCheckapUsage(argv[0]);
+        else
+            printUsage(argv[0]);
+        exit(1);
+    }
+
+    // Open serial port
+    if (func != 5) {
+        if ((fd = initial_serialPort(devPort)) == -1)
+        {
+            printf("Can't open COM\n");
+            return UART_DEV_ERR;
+        }
+        if (baud == 115200) {
+            set_baudrate(fd, B115200);
+        } else if (baud == 230400) {
+            set_baudrate(fd, B230400);
+        } else if (baud == 921600) {
+            set_baudrate(fd, B921600);
+        } else if (baud == 1843200) {
+            set_baudrate(fd, B1500000);
+        } else {
+            printf("baudrate %d not supported\n", baud);
+            close(fd);
+            exit(1);
+        }
+    }
+
+    // execute function
+    switch(func) {
+    case 1:
+        ret = getAPData(fd, ap);
+        break;
+    case 2:
+        ret = sendAPData(fd, ap);
+        break;
+    case 3:
+        ret = downloadBL(fd, bl);
+        break;
+    case 4:
+        ret = downloadFW(fd, fw);
+        break;
+    case 5:
+        ret = checkAPData(ap);
+        break;
+    default:break;
+    }
+    close(fd);
+    return ret;
+
+}
+
+int getAPData(int fd, char *file)
+{
+    int rByte = 0;
+    char rbuf[4096];
+    int ret = 0, i;
+    struct timeval time_m, time_n;
+
+    if (NULL == file) {
+        printf("Please input file!! \n");
+        return 1;
+    }
+    if (!fd)
+        return 1;
+    printf("Get apdata\n");
+    gps_dev_send(fd, "$ReqRecvFlash\r\n");
+    af_start_receive();
+    GET_TIME();
+    while(1) {
+        CHK_TIME();
+        if(select_read(fd,1) > 0)
+            usleep(50000);
+        else
+            continue;
+
+        rByte = deal_read(fd,&rbuf,sizeof(rbuf));
+        if(rByte >= 1){
+            if(af_is_start_receive()) {
+                for(i = 0; i < rByte; i++)
+                    af_add_char(file, rbuf[i]);
+            } else {
+                break;
+            }
+        }
+    }
+
+    checkAPData(file);
+    return 0;
+}
+
+int sendAPData(int fd, char *apFile)
+{
+    int rByte = 0;
+    char rbuf[4096];
+    int ret = 0;
+    struct timeval time_m, time_n;
+
+    if(access(apFile, F_OK) != -1)
+    {
+        // Download APData only if the file exits
+        printf("Download APData...\n");
+        if(xmodem_send(fd, apFile))
+        {
+            printf("xmodem error!\n");
+            close(fd);
+            return ENTER_UPDATE_MODE_ERR;
+        }
+        // Waiting for 'C'
+        GET_TIME();
+        while(1)
+        {
+            CHK_TIME();
+            if(select_read(fd,1) > 0)
+                usleep(500000);
+            else
+                continue;
+            rByte = deal_read(fd,&rbuf,sizeof(rbuf)-1);
+            rbuf[rByte] = 0;
+            if(rByte > 0)
+            {
+                if(rbuf[rByte - 1] == 'C')
+                    break;
+            }
+        }
+        printf("download APData success\n");
+    }
+    else
+    {
+        printf("file err!\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int checkAPData(char *apFile)
+{
+    printf("Checking %s\n", apFile);
+    if(check_file(apFile))
+    {
+        printf("file error!\n");
+        return FILE_CHECK_ERR;
+
+    }
+    else
+    {
+        printf("pass\r\n");
+    }
+    return 0;
+}
+
+int downloadFW(int fd, char *fw)
+{
+    int ret;
+    struct timeval time_m, time_n;
+    char rbuf[512];
+
+    if(NULL == fw) {
+        printf("Error: Can't find firmware.\n");
+        return -1;
+    }
+    printf("Download firmware...\n");
+    if(xmodem_send(fd, fw) < 0) {
+        printf("xmodem error! send firmware failed!\n");
+        close(fd);
+        return UPDATE_ERR;
+    }
+    set_baudrate(fd, B115200);
+    printf("Download firmware success\n");
+    return 0;
+}
+
+int downloadBL(int fd, char *bl)
+{
+    int rByte = 0;
+    char rbuf[4096];
+    char name[128];
+    int ret = 0;
+    struct timeval time_m, time_n;
+
+    if(NULL == bl) {
+        printf("Error: Can't find bootloader.\n");
+        return -1;
+    }
+    printf("------Please Powerdown the receiver!\n");
+    mopen_open_gps(0);
+    SET_TIME_OUT(3);
+    while(1) {
+        DELAY_TIME_BREAK(); //
+        if(select_read(fd,1) > 0)
+            usleep(50000);
+        else
+            continue;
+
+        rByte = deal_read(fd,&rbuf,sizeof(rbuf));
+    }
+    int start = 0,finish = 0;
+
+    memset(name, 0, sizeof(name));
+    sprintf(name,"M!T");
+    printf("waiting for YC, timeout is %d s\n", TIMEOUT_SEC);
+    printf("-------Please Powerup the receiver!\n");
+    mopen_open_gps(1);
+    // Waiting for 'YC'
+    GET_TIME();
+    while(1) {
+        int finish = 0, i;
+        CHK_TIME_BREAK(); //
+        rByte = write(fd, name, strlen(name));
+        rByte = select_read(fd,1);
+        if(rByte <= 0)
+            continue;
+        rByte = deal_read(fd, rbuf, sizeof(rbuf) - 1);
+        rbuf[rByte] = 0;
+        for (i = 0 ; i < rByte; i++)
+        {
+            if (check_YC(rbuf[i])) {
+                printf("Receive 'YC'\n");
+                finish = 1;
+                break;
+            }
+        }
+        if (finish)
+            break;
+    }
+    //wait 'YC' timeout deal
+    if (timeout_sign == 1)
+    {
+        //wait NAK
+        GET_TIME();
+        printf("2222\n");
+        while(1)
+        {
+            CHK_TIME();
+            if(select_read(fd,1) <= 0)
+                continue;
+
+            rByte = deal_read(fd, rbuf,sizeof(rbuf));
+            if (rbuf[rByte-1] == 'C')
+            {
+                printf("###read xmodem start character 'C'.\n");
+                break;
+            }
+        }
+    }
+    //use_select = 1;
+    printf("download bootloader...\n");
+
+    // Transfer bootloader via xmodem protocal
+    // if(xmodem_send(fd, "./bootloader.bin")) {
+    if(xmodem_send(fd, bl)) {
+        printf("xmodem error!\n");
+        close(fd);
+        return ENTER_UPDATE_MODE_ERR;
+    }
+    printf("download bootloader success\n");
+    return 0;
+}
+
+int check_YC(char newchar)
+{
+    int static state = 0;
+    int ret = 0;
+    switch (state) {
+    case 0:
+        if (newchar == 'Y')
+            state = 1;
+        break;
+    case 1:
+        if (newchar == 'C') {
+            state = 1;
+            ret = 1;
+        }
+        break;
+    default:
+        state = 0;
+    }
+    return ret;
+}
+
+const unsigned short CRC16_Table[256] = {
+    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+unsigned short crc16_ccitt(const unsigned char *buf, int len)
+{
+    register int counter;
+    register unsigned short crc = 0;
+    for (counter = 0; counter < len; counter++)
+        crc = (crc << 8) ^ CRC16_Table[((crc >> 8) ^ *(char *)buf++) & 0x00FF];
+    return crc;
+}
+
+
+unsigned int checksum32(unsigned int * pbuf, unsigned int len)
+{
+    unsigned int i, sumValue = 0;
+    len >>=2;
+
+    for(i=0;i<len;i++)
+    {
+        sumValue += *pbuf++;
+    }
+    return sumValue;
+}
+
+void af_start_receive()
+{
+    recvStat = WAIT_FD;
+    isStartReceive = 1;
+    return;
+}
+
+void af_stop_receive()
+{
+    int i;
+    printf("%s:%d\r\n", __FUNCTION__, __LINE__);
+    printf("%s:%d  recvStat = %d\r\n", __FUNCTION__, __LINE__, recvStat);
+    pbuf = (unsigned char *)recv_buf;
+    for(i = 0; i < 4636; i++){
+        if(i % 32 == 0)printf("\r\n");
+        printf("%02X ", pbuf[i]);
+    }
+    printf("\r\n");
+    isStartReceive = 0;
+    return;
+}
+
+int af_is_start_receive()
+{
+    return isStartReceive;
+}
+
+int af_check_header(unsigned char *pbuf, unsigned int len)
+{
+    unsigned int crc = crc16_ccitt(pbuf, len-4);
+
+    if(crc == *(unsigned int *)(pbuf + len - 4))
+        return 1;
+    else
+        return 0;
+}
+
+int af_check_data(unsigned int * pbuf, unsigned int len)
+{
+    unsigned int cs = checksum32(pbuf + 8, len);
+    if(cs == pbuf[1])
+        return 1;
+    else
+        return 0;
+}
+
+int af_get_data_len()
+{
+    int len = *(int *)(recv_buf+3);
+    return len;
+}
+
+int af_add_char(char *file, unsigned char c)
+{
+    int ret = 0;
+    switch(recvStat){
+    case WAIT_FD:
+        if(c == 0xfd){
+            pbuf = (unsigned char *)recv_buf;
+            pbuf[0] = c;
+            recvStat = WAIT_FC;
+            printf("------------received 0xfd\r\n");
+        }
+        break;
+    case WAIT_FC:
+        if(c == 0xfc){
+            pbuf[1] = c;
+            recvStat = WAIT_FB;
+            printf("------------received 0xfc\r\n");
+        }else{
+            af_stop_receive();
+        }
+        break;
+    case WAIT_FB:
+        if(c == 0xfb){
+            pbuf[2] = c;
+            recvStat = WAIT_FA;
+            printf("------------received 0xfb\r\n");
+        }else{
+            af_stop_receive();
+        }
+        break;
+    case WAIT_FA:
+        if(c == 0xfa){
+            pbuf[3] = c;
+            recvStat = RECE_HEADER;
+            pbuf += 4;
+            printf("------------received 0xfa\r\n");
+        }else{
+            af_stop_receive();
+        }
+        break;
+    case RECE_HEADER:
+        *pbuf = c;
+        pbuf++;
+        if((pbuf - (unsigned char *)recv_buf) == HEADERLEN){
+            if(af_check_header((unsigned char *)recv_buf, HEADERLEN)){
+                recvStat = RECE_DATA;
+                data_len = af_get_data_len();
+            }else{
+                af_stop_receive();
+            }
+        }
+        break;
+    case RECE_DATA:
+        *pbuf = c;
+        pbuf++;
+        if((pbuf - (unsigned char *)recv_buf) == data_len + HEADERLEN){
+            if(af_check_data(recv_buf, recv_buf[3])){
+                int fd = open(file, O_WRONLY|O_CREAT, S_IRWXU);
+                write(fd, recv_buf, pbuf - (unsigned char *)recv_buf);
+                printf("%s:%d rtm len = %ld\r\n", __FUNCTION__, __LINE__, pbuf-(unsigned char *)recv_buf);
+                close(fd);
+                printf("receive rtm\n");
+            }else{
+                printf("af_check_data false!");
+            }
+            af_stop_receive();
+        }
+        ret = 1;
+        break;
+    default:
+        printf("%s:recvStat = %d\r\n", __FUNCTION__, recvStat);
+        break;
+    }
+    return ret;
+}
+
+
+
+ssize_t deal_read(int fd, void *buf, size_t count)
+{
+    int ret = 0;
+
+    while (1)
+    {
+        ret = read(fd, buf, count);
+        if (ret == 0)
+        {
+            printf("read serial return 0, please check serial device.\n");
+            exit(UART_DEV_ERR);
+        }
+        if(ret < 0)
+        {
+            if ((errno == EAGAIN) || (errno == EINTR))
+            {
+                printf("read serial return -1, errno = %d, retry.\n", errno);
+                continue;
+            }
+            else
+            {
+                printf("read serial return -1, errno = %d, please check serial device.\n", errno);
+                exit(UART_DEV_ERR);
+            }
+        }
+        return ret;
+    }
+}
+
+unsigned short get_crc16 ( char *ptr, unsigned short count )
+{
+    unsigned short crc, i;
+
+    crc = 0;
+    while(count--)
+    {
+        crc = crc ^ (int) *ptr++ << 8;
+
+        for(i = 0; i < 8; i++)
+        {
+            if(crc & 0x8000)
+                crc = crc << 1 ^ 0x1021;
+            else
+                crc = crc << 1;
+        }
+    }
+
+    return (crc & 0xFFFF);
+}
+
+void dump_u(void *buf, int len)
+{
+    unsigned char *p = (unsigned char *)buf;
+    int i;
+
+    for(i = 0; i < len; i++) {
+        if(i % 16 == 0) printf("%04x:", i);
+        if(i % 16 == 8) printf(" -");
+        printf(" %02x", p[i]);
+        if(i % 16 == 15) printf("\n");
+    }
+    if(i % 16) printf("\n");
+}
+
+unsigned int get_file_size(const char * name)
+{
+    struct stat statbuff;
+    //unsigned int size, checksum;
+    if(stat(name, &statbuff) < 0)
+        return -1;
+    else
+        return statbuff.st_size;
+}
+
+
+int check_file(char * fname)
+{
+    FILE *fd;
+    uc_image_header_t header;
+    unsigned int buf[1024];
+    unsigned int fsize, checksum, i;
+    unsigned int len;
+    unsigned short crc;
+    size_t rByte;
+
+    if((fd=fopen(fname,"rb"))==NULL)
+    {
+        printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno));
+        return -1;
+    }
+
+    fsize = get_file_size(fname);
+
+    printf("file size [%d]\n",fsize);
+
+    if(fsize == 0)
+        return -1;
+
+    while(fsize > sizeof(header)) {
+        rByte = fread((char *)&header, sizeof(char), sizeof(header), fd);
+
+        dump_u((char *)&header, sizeof(header));
+
+        crc = get_crc16 ( (char *) &header, sizeof(header)-4);
+        printf("crc16  [%08x]\n", crc);
+
+        if((header.ih_hcrc & 0xFFFF) != crc) {
+            fclose(fd);
+            return -1;
+        }
+
+        fsize -= sizeof(header);
+        fsize -= header.ih_size;
+        checksum = 0;
+        len = header.ih_size;
+        while(len > 0)
+        {
+            if(len >= 1024 )
+                rByte = 1024;
+            else
+                rByte = len;
+
+            memset(buf, 0, sizeof(buf));
+            rByte = fread((char *)buf, 1, rByte, fd);
+            for(i = 0; i < (rByte+3)/4; i++)
+                checksum += buf[i];
+
+            len -= rByte;
+        }
+        printf("checksum  [%08x]\n\n",checksum);
+
+        if( checksum != header.ih_dcrc) {
+            fclose(fd);
+            return -1;
+        }
+    }
+
+    fclose(fd);
+    return 0;
+}
+
+static int select_read(int fd, int timeout) //1ms
+{
+    fd_set set;
+    struct timeval t;
+    int ret;
+    int i = timeout;
+
+    if(use_select) {
+        do {
+            FD_ZERO(&set);
+            FD_SET(fd, &set);
+            t.tv_sec = 0;
+            t.tv_usec = 100;
+            ret = select(FD_SETSIZE, &set, NULL, NULL, &t );
+            if(ret == 0) continue;
+            if(ret < 0 && errno == EINTR)continue;
+            else return ret;
+        } while(i--);
+    } else {
+        struct timeval t0, t1;
+        long dt = 0;
+        int c;
+        printf("22222\n");
+        gettimeofday(&t0, NULL);
+        do {
+            c = 0;
+            ret = ioctl(fd, FIONREAD, &c);
+            if(c > 0) { ret = c; break; }
+
+            gettimeofday(&t1, NULL);
+            dt = t1.tv_usec - t0.tv_usec;
+            dt += (t1.tv_sec-t0.tv_sec)*1000*1000;
+        } while(dt/1000 < timeout);
+    }
+
+    return ret;
+}
+
+int set_baudrate(int fd, int baudrate)
+{
+    struct termios options, oldtio;
+
+    if(fcntl(fd, F_SETFL, 0) < 0) {
+        printf("fcntl failed!\n");
+        return -1;
+    }
+
+    if(tcgetattr(fd, &oldtio) != 0) {
+        printf("setup serial error!\n");
+        return -1;
+    }
+
+    /* Get the current options for the port... */
+    tcgetattr(fd, &options);
+
+    /* Set the baud rates to baudrate... */
+    cfsetispeed(&options,baudrate);
+    cfsetospeed(&options,baudrate);
+    tcsetattr(fd, TCSANOW, &options);
+
+    if (0 != tcgetattr(fd, &options))
+    {
+        printf("get options error!\n");
+        return -1;
+    }
+
+    /*
+         * 8bit Data,no partity,1 stop bit...
+         */
+    options.c_cflag &= ~PARENB;//无奇偶校验
+    options.c_cflag &= ~CSTOPB;//停止位,1位
+    options.c_cflag &= ~CSIZE; //数据位的位掩码
+    options.c_cflag |= CS8;    //数据位,8位
+
+    cfmakeraw(&options);
+
+    /*
+         * Set the new options for the port...
+         */
+    if (tcsetattr(fd, TCSANOW, &options) != 0)
+    {
+        printf("setup serial error!\n");
+        return -1 ;
+    }
+
+    return 0 ;
+}
+
+int initial_serialPort(char * serial_device)
+{
+    int fd;
+    fd = open( serial_device , O_RDWR );
+    if ( fd == -1 )
+    {
+        /* open error! */
+        printf("Can't open serial port(%s)!(errno=%d:%s) \n", serial_device, errno, strerror(errno));
+        return -1;
+    }
+
+    set_baudrate(fd, B9600);
+
+    return fd ;
+}
+
+static void gps_dev_send(int fd, char *msg)
+{
+    int i, n, ret;
+
+    i = strlen(msg);
+
+    n = 0;
+
+    printf("function gps_dev_send: %s", msg);
+    do {
+
+        ret = write(fd, msg + n, i - n);
+
+        if (ret < 0 && errno == EINTR) {
+            continue;
+        }
+
+        n += ret;
+
+    } while (n < i);
+
+    // drain cmd
+    tcdrain(fd);
+
+    return;
+}
+
+int xmodem_send(int fd, char *fname)
+{
+    char packet_data[XMODEM_DATA_SIZE];
+    char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];
+    int ret = -1;
+
+    FILE *datafile;
+    int complete,retry_num,pack_counter,read_number,write_number,i;
+    unsigned short crc_value;
+    unsigned char ack_id = 'C';
+    struct timeval time_m, time_n;
+
+    datafile = NULL;
+    pack_counter = 0;	// 包计数器清零
+    complete = 0;
+    retry_num = 0;
+
+    printf("[%s]\n",fname);
+    //只读方式打开一个准备发送的文件,如果不存在就报错,退出程序。
+    if((datafile=fopen(fname,"rb"))==NULL)
+    {
+        printf("\n can't open (%s) or not exist!(errno=%d:%s) \n", fname, errno, strerror(errno));
+        return -1;
+    }
+    else
+    {
+        printf("Ready to send the file:%s\n",fname);
+    }
+
+    printf("Waiting for signal C/NAK!\n");
+    GET_TIME();
+    while(1)
+    {
+        CHK_TIME1();
+        if(select_read(fd,1) > 0)
+            usleep(10000);
+        else
+            continue;
+
+        //read(fd,&ack_id,1);
+        deal_read(fd,&ack_id,1);
+        if(ack_id == 'C')
+            break;
+    }
+
+    printf("The signal NAK: %02x ok!!!\n",ack_id);//打印接收到的NAK信息
+
+    while(!complete)
+    {
+        switch(ack_id)
+        {
+        case XMODEM_CRC_CHR:	// 接收到字符'C'开始启动传输,并使用CRC校验
+            printf("begining to Send file %s...\n",fname);
+
+        case XMODEM_ACK:        //0x06
+            retry_num = 0;
+            pack_counter++;
+
+            read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, datafile);
+            //从打开的datafile指向的文件中读取
+            //XMODEM_DATA_SIZE 个(char)数据,
+            //放到packet_data这个数组中
+            if(read_number > 0)//read_number为返回的读取实际字节数
+            {
+                //printf("test:read_number:%d\n", read_number);
+                if(read_number < XMODEM_DATA_SIZE_STX)
+                {
+                    printf("Start filling the last frame!\n");
+                    for(; read_number < XMODEM_DATA_SIZE; read_number++)
+                        packet_data[read_number] = 0x1A;  // 不足128字节用0x1A填充
+                    //printf("replenish data.\n");
+                }
+
+                frame_data[0] = XMODEM_HEAD;  // 帧开始字符
+                frame_data[1] = (char)pack_counter;  // 信息包序号
+                frame_data[2] = (char)(255 - frame_data[1]);  // 信息包序号的补码
+
+                for(i=0; i < XMODEM_DATA_SIZE; i++)  // 128字节的数据段
+                    frame_data[i+3] = packet_data[i];//把收到的字符和信息头一起打包
+
+                crc_value = get_crc16(packet_data, XMODEM_DATA_SIZE); // 16位crc校验
+                frame_data[XMODEM_DATA_SIZE+3] = (unsigned char)(crc_value >> 8);// 高八位数据
+                frame_data[XMODEM_DATA_SIZE+4] = (unsigned char)(crc_value);     //低八位数据
+
+                /* 发送133字节数据 */
+                write_number = write( fd, frame_data, XMODEM_DATA_SIZE + 5);//向串口写一个包数据,即133字节数据
+                printf("."); //ADD: process
+                fflush(stdout);
+                //printf("waiting for next ACK... \n......\n");
+
+                GET_TIME();
+                while(1)
+                {
+                    CHK_TIME1();
+                    if(select_read(fd,1) > 0)
+                        usleep(10000);
+                    else
+                        continue;
+
+                    //read(fd,&ack_id,1);
+                    deal_read(fd,&ack_id,1);
+                    break;
+                }
+
+                if(ack_id == XMODEM_ACK) {
+                    //printf("ACK Ok!!Ready sending next pack!\n");
+                    ;
+                }
+                else
+                {
+                    printf("ACK Error!\n");
+                    printf("0x%02X\n",ack_id);
+                    //printf("pack_counter = %d\n", pack_counter);
+                }
+            }
+
+            else  // 文件发送完成
+            {
+                ack_id = XMODEM_EOT;
+                complete = 1;
+                printf("Complete ACK\n");
+
+                GET_TIME();
+                while(ack_id != XMODEM_ACK)
+                {
+                    CHK_TIME1();
+                    ack_id = XMODEM_EOT;
+                    write_number = write(fd,&ack_id,1);
+                    while((deal_read(fd, &ack_id, 1)) <= 0);
+                }
+                printf("Send file successful!!!\n");
+                fclose(datafile);
+                datafile = NULL;
+            }
+            break;
+
+        case XMODEM_NAK:
+            if( retry_num++ > 10)
+            {
+                printf("Retry too many times,Quit!\n");
+                complete = 1;
+            }
+            else //重试,发送
+            {
+                write_number = write(fd, frame_data, XMODEM_DATA_SIZE + 5);
+                printf("Retry for ACK,%d,%d...", pack_counter, write_number);
+
+                GET_TIME();
+                while(1)
+                {
+                    CHK_TIME1();
+                    if(select_read(fd,1) > 0)
+                        usleep(100);
+                    else
+                        continue;
+
+                    //read(fd,&ack_id,1);
+                    deal_read(fd,&ack_id,1);
+                    break;
+                }
+
+                if( ack_id == XMODEM_ACK )
+                    printf("OK\n");
+                else
+                    printf("Error!\n");
+            }
+            break;
+        default:
+            printf("Fatal Error! %d\n", ack_id);
+            complete = 1;
+            return -1;
+            break;
+        }
+    }
+
+    if( datafile != NULL )
+        fclose(datafile);
+
+    return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/lynq-gnss-update.bb b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/lynq-gnss-update.bb
new file mode 100755
index 0000000..9ada3c1
--- /dev/null
+++ b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-gnss-update/lynq-gnss-update.bb
@@ -0,0 +1,33 @@
+# Package summary

+SUMMARY = "lynq-gnss-update"

+# License, for example MIT

+LICENSE = "MIT"

+# License checksum file is always required

+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

+

+SRC_URI = " file://lynq-gnss-update.cpp"

+

+SRC-DIR = "${S}/../lynq-gnss-update"

+TARGET_CC_ARCH += "${LDFLAGS}"

+

+#Parameters passed to do_compile()

+EXTRA_OEMAKE = "'TARGET_PLATFORM = ${TARGET_PLATFORM}'\"

+EXTRA_OEMAKE += "'MOBILETEK_RIL_CFG = ${MOBILETEK_RIL_CFG}'"

+

+LOCAL_C_INCLUDES = "-I."

+

+LOCAL_LIBS = "-L. -ldl -lstdc++"

+

+#INHIBIT_PACKAGE_STRIP = "1"

+S = "${WORKDIR}"

+

+#INHIBIT_PACKAGE_STRIP = "1"

+do_compile () {

+

+	${CXX} -Wall lynq-gnss-update.cpp ${LOCAL_LIBS} ${LOCAL_C_INCLUDES} -o lynq-gnss-update

+}

+

+do_install() {

+	install -d ${D}${bindir}/

+	install -m 0755 ${S}/lynq-gnss-update ${D}${bindir}/

+}
\ No newline at end of file
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/UC6228CI-R3.2.10.100Build8019_mfg.pkg b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/UC6228CI-R3.2.10.100Build8019_mfg.pkg
new file mode 100755
index 0000000..5310f03
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/UC6228CI-R3.2.10.100Build8019_mfg.pkg
Binary files differ
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/bootloader_r3.0.0_build6773_uartboot_921600.pkg b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/bootloader_r3.0.0_build6773_uartboot_921600.pkg
new file mode 100755
index 0000000..3cfd1fb
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/bootloader_r3.0.0_build6773_uartboot_921600.pkg
Binary files differ
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/lynq_qser_gnss.h b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/lynq_qser_gnss.h
index 6c6c051..d69af22 100755
--- a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/lynq_qser_gnss.h
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/lynq_qser_gnss.h
@@ -114,6 +114,7 @@
 int qser_Gnss_Stop(uint32_t h_gnss);
 int qser_Gnss_Delete_Aiding_Data(uint32_t h_gnss,DELETE_AIDING_DATA_TYPE_T flags);
 int qser_Gnss_InjectTime(uint32_t h_gnss,LYNQ_INJECT_TIME_INTO_T *time_info);
+int qser_firmware_update(uint32_t* ph_gnss);
 #ifdef __cplusplus
 }
 #endif
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/mbtk_gnss_internal.h b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/mbtk_gnss_internal.h
index eb7002c..dfced9c 100755
--- a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/mbtk_gnss_internal.h
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/include/mbtk_gnss_internal.h
@@ -302,7 +302,7 @@
 int mopen_gnss_set_nema_config(uint32 h_gnss, int mode);
 int mopen_gnss_download_tle(void);
 int mopen_gnss_injects_aidpos(uint32 h_gnss);
-int mopen_gnss_firmware_update(void);
+int mopen_gnss_firmware_update(uint32 ph_gnss);
 int mbtk_at_gnss_start_ttff(int type, int timeout_sec, int count);
 int lynq_gnss_send_cmd(uint32 h_gnss, const char *cmd, int cmd_len);
 int mopen_gnss_write(int fd, const char* buf, unsigned int buf_len);
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/lynq_qser_gnss.cpp b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/lynq_qser_gnss.cpp
index 65414ed..735f467 100755
--- a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/lynq_qser_gnss.cpp
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/lynq_qser_gnss.cpp
@@ -222,6 +222,17 @@
     return 0;
 }
 
+int qser_firmware_update(uint32_t* ph_gnss)
+{
+    int ret;
+    mopen_gnss_firmware_update(*ph_gnss);
+    if(ret < 0)
+    {
+        return -1;
+    }
+    return 0;
+}
+
 void atsvc_incb_entity(char *input,int length);
 int lynq_at_cgps(int at_type,int gnss_state_type);
 int lynq_at_cgpsnmea(int at_type,int gnss_state_type);
diff --git a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/mbtk_gnss.cpp b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/mbtk_gnss.cpp
index c2f3056..cffc6a9 100755
--- a/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/mbtk_gnss.cpp
+++ b/cap/zx297520v3/src/lynq/lib/liblynq-qser-gnss/src/mbtk_gnss.cpp
@@ -16,6 +16,7 @@
 #include <sys/ioctl.h>
 #include <malloc.h>
 #include <sys/time.h>
+#include <liblog/lynq_deflog.h>
 #include "mbtk_gnss_internal.h"
 #include "ringbuffer.h"
 #ifdef __cplusplus
@@ -376,7 +377,7 @@
                 g_no_sv < (no_sv - 1) && no_sv > 5) {
 
             g_no_sv = no_sv;
-            lynq_gnss_get_ap_data();
+            //lynq_gnss_get_ap_data();
         }
     }
 }
@@ -1273,100 +1274,59 @@
     return 0;
 }
 
-#define GNSS_AP_DATA_FILE  "/etc/mbtk/rtm.bin"
-
-int lynq_gnss_get_ap_data(void)
-{
-    int state = 0;
-    uint32 *ph_gnss = NULL;
-    gnss_handler_func_t cb;
-    int current_mode;
-    const char* cmd = "mbtk_gnss_update getap -d /dev/ttyS2 -b 115200 -a /etc/mbtk/rtm.bin";
-
-    if(access(GNSS_AP_DATA_FILE, F_OK) != -1) {
-        unlink(GNSS_AP_DATA_FILE);
-    }
-    mbtk_gnss_handle->getap_status = 1;
-    sleep(1);
-    printf("Mopen Gnss Get Ap Data -> \n");
-    int ret = exec_cmd(cmd, NULL);
-
-    usleep(100000);
-    mbtk_gnss_handle->getap_status = 0;
-    if(0 != ret) {
-        printf("Gnss getap result: %x\n", ret);
-        return -1;
-    }
-    LOGI("%s %d: %d.\n", __FUNCTION__, __LINE__, ret);
-    return ret;
-}
 /*
-  sync : 1
+update API:
+Gnss_Update_File_Path:"/data/gnss_update/firmware.pkg"
+Gnss_Bootloader_File_Path: "/data/gnss_update/bootloader.pkg"
  */
-int mopen_gnss_firmware_update(void)
+int mopen_gnss_firmware_update(uint32 ph_gnss)
 {
+    int ret;
     int state = 0;
-    uint32 *ph_gnss = NULL;
-    gnss_handler_func_t cb;
-    int current_mode;
-    const char* cmd_1 = "mbtk_gnss_update downbl -d /dev/ttyS2 \
-            -l /mnt/userdata/bootloader_r3.0.0_build6773_uartboot_921600.pkg";
-
-            const char* cmd_2 = "mbtk_gnss_update sendap -d /dev/ttyS2 -b 921600 -a /etc/mbtk/rtm.bin";
-
-    const char* cmd_3 = "mbtk_gnss_update downfw -d /dev/ttyS2 -b 921600\
-            -f /mnt/userdata/UC6228CI-R3.2.10.100Build8019_mfg.pkg";
-            // /etc/mbtk/UC6228CI-R3.4.0.0Build7258_mfg.pkg
-
-            if (mbtk_gnss_handle) {
-            printf("%s gnss thread runing!!!\n", __func__);
-            if (mbtk_gnss_handle->gnss_handler_func)
-            cb = mbtk_gnss_handle->gnss_handler_func;
-
-            ph_gnss = mbtk_gnss_handle->phandle;
-            current_mode = mbtk_gnss_handle->mode;
-            // 主线程是否在运行
-            if (mbtk_gnss_handle->gnss_pthread)
+    printf("load_datafile start\n");
+    struct mbtk_gnss_handle_t *gnss_handle = (struct mbtk_gnss_handle_t* )ph_gnss;
+    const char* cmd_1 = "lynq-gnss-update downbl -d /dev/ttyS2  -b 230400 -l /data/gnss_update/bootloader.pkg";
+    const char* cmd_2 = "lynq-gnss-update downfw -d /dev/ttyS2 -b 921600 -f /data/gnss_update/firmware.pkg";
+    const char* cmd_3 = "echo \"\$PDTINFO\r\n\" > /dev/ttyS2";
+    if (ph_gnss)
+    {
+        printf("%s gnss thread runing!!!\n", __func__);
+        // 主线程是否在运行
+        if (gnss_handle->gnss_pthread)
             state = 1;
-            lynq_gnss_client_deinit((uint32)mbtk_gnss_handle);
-}
-            printf("Mopen Gnss Bootloader Update -> \n");
-    int ret = exec_cmd(cmd_1, NULL);
-    if(0 != ret) {
-        printf("Gnss update result: %x\n", ret);
+        lynq_gnss_client_deinit(ph_gnss);
+    }
+    printf("Mopen Gnss Bootloader Update -> \n");
+    ret = exec_cmd(cmd_1, NULL);
+    if(0 != ret)
+    {
+        ALOGE("Gnss update result: %x\n", ret);
         return -1;
     }
 
-    /*if(access(GNSS_AP_DATA_FILE, F_OK) != -1)
-    {
-        printf("Mopen Gnss Send AP Data  -> \n");
-        ret = exec_cmd(cmd_2, NULL);
-        if(0 != ret) {
-            printf("Gnss update result: %x\n", ret);
-        }
-    }*/
-
     printf("Mopen Gnss Firmware Update -> \n");
+    ret = exec_cmd(cmd_2, NULL);
+    if(0 != ret)
+    {
+        ALOGE("Gnss update result: %x\n", ret);
+        return -1;
+    }
+
+    printf("PDTINFO  -> \n");
     ret = exec_cmd(cmd_3, NULL);
-    if(0 != ret) {
-        printf("Gnss update result: %x\n", ret);
-        return -2;
+    if(0 != ret)
+    {
+        ALOGE("PDTINFO  ->  %x\n", ret);
+        return -1;
     }
 
     if (0 == firmware_extren_state)
         firmware_extren_state = 1;
-    if (state && ph_gnss) {
-        ret = lynq_gnss_client_init(ph_gnss);
-        if (cb) {
-            mbtk_gnss_handle->gnss_handler_func = cb;
-            mbtk_gnss_handle->mode = current_mode;
-        }
-    }
 
-    LOGI("%s %d: %d.\n", __FUNCTION__, __LINE__, ret);
     return ret;
 }
 
+
 /*update ephemeris from network*/
 #define AGNSS_TLE_FILE "/mnt/userdata/agnss_tle" //deposit ephemeris