gnssd: add 8122 agps func

Change-Id: Ie87dcafc1da9cf5cffd9f5397f1640f19aa36aab
diff --git a/mbtk/mbtk_gnssd/Makefile b/mbtk/mbtk_gnssd/Makefile
index 4359afa..b967666 100755
--- a/mbtk/mbtk_gnssd/Makefile
+++ b/mbtk/mbtk_gnssd/Makefile
@@ -6,11 +6,12 @@
 INC_DIR += \
 		-I$(LOCAL_PATH) \
 		-I$(LOCAL_PATH)/hd8122_dl \
+		-I$(LOCAL_PATH)/agps \
 		-I$(BUILD_ROOT)/libmbtk_ril
 
 LIB_DIR +=
 
-LIBS += -lmbtk_lib -lmbtk_net -lmbtk_ril -lrilutil -lprop2uci -lmtel -laudio-apu -lcutils -ltinyalsa -lacm -lubus -lubox -lutil -lrt
+LIBS += -lmbtk_lib -lmbtk_net -lmbtk_ril -lmbtk_http -lrilutil -lprop2uci -lmtel -laudio-apu -lcutils -ltinyalsa -lacm -lubus -lubox -lutil -lrt
 
 CFLAGS +=
 
@@ -33,6 +34,8 @@
 					gnss_asr5311.c \
 					gnss_log.c \
 					gnss_n50db.c \
+					agps/8122_agnss.c \
+					agps/agnss_http_download.c \
 					hd8122_dl/port.c \
 					hd8122_dl/fwup.c
 
diff --git a/mbtk/mbtk_gnssd/agps/8122_agnss.c b/mbtk/mbtk_gnssd/agps/8122_agnss.c
new file mode 100755
index 0000000..4acbe33
--- /dev/null
+++ b/mbtk/mbtk_gnssd/agps/8122_agnss.c
@@ -0,0 +1,418 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+
+#include "8122_agnss.h"
+#include "mbtk_log.h"
+
+#define BUFFER_SIZE 1024
+
+#define INJECT_RESULT_SUCCESS 0
+#define INJECT_RESULT_FAIL    -1
+
+static int hd_fd = -1;
+static hd_eph_inject_status_type eph_inject_status = HD_EPH_INJECT_STATUS_SUCCESS;
+
+static void hd_agnss_delay(uint32_t nms)
+{
+    usleep(nms * 1000);
+}
+
+static int hd_agnss_uart_write(uint8_t *buf, uint32_t len)
+{
+    int TxLen;
+    if(hd_fd > 0)
+    {
+        TxLen = write(hd_fd,buf,len);
+        if(TxLen != (int)len)
+        {
+            LOGE("hd_agnss_uart_write fail.ret = [%d], len = [%d]", TxLen, len);
+            return INJECT_RESULT_FAIL;
+        }
+    }
+    else
+    {
+        LOGE("8122 agps fd error.");
+    }
+    return TxLen;
+}
+
+static int32_t message_package(uint8_t *dst, uint8_t *src, int32_t src_len)
+{
+    int32_t i = 0;
+    int8_t checksum1 = 0;
+    int8_t checksum2 = 0;
+
+    /* message header */
+    for (i = 0; i < 4; i++)
+    {
+        dst[i] = *(src + i);
+    }
+
+    /* message len */
+    dst[4] = src_len;
+    dst[5] = 0;
+
+    /* payload */
+    for( i = 0 ; i < src_len; i++)
+    {
+        dst[6 + i] = *(src + 4) ;
+        src++;
+    }
+
+    /* check sum */
+    for(i = 2; i < (6 + dst[4]); i++)
+    {
+        checksum1 += dst[i];
+        checksum2 += checksum1;
+    }
+
+    dst[src_len + 6] = checksum1;
+    dst[src_len + 7] = checksum2;
+
+    return src_len + 8;
+}
+
+/************************************time inject*************************************/ 
+static int gnss_inject_time(HD_AGNSS_UTC_TIME_TYPE *time)
+{
+    uint8_t cmd[24] = {0}; /* packet head+payload */
+    uint8_t message[30] = {0}; /* payload : 20, packet pad : 8 */
+    int32_t len = 0;
+
+    memset(cmd, 0, sizeof(cmd));
+
+    cmd[0] = 0xF1;
+    cmd[1] = 0xD9;
+    cmd[2] = 0x0B;
+    cmd[3] = 0x11;
+
+    cmd[4] = 0x00; /* UTC */
+    cmd[5] = 0x00; /* reserved */
+    cmd[6] = 0x12; /* leap cnt, hd8030 not used */
+
+    cmd[7] = time->year & 0xFF;
+    cmd[8] = ((time->year >> 8) & 0xFF); /* year */
+    cmd[9] = time->month; /* month */
+    cmd[10] = time->day; /* day */
+    cmd[11] = time->hour; /* hour */
+    cmd[12] = time->min; /* minu */
+    cmd[13] = time->second; /* sec */
+
+    cmd[18] = 0x00;
+    cmd[19] = 0x00;
+    for (int i = 0; i < 4; i++)
+    {
+        cmd[20 + i] = 0x00;
+    }
+
+    len = message_package(message, cmd, sizeof(cmd) - 4);
+
+    LOGE("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
+            message[0],message[1],message[2],message[3],message[4],message[5],message[6],message[7],
+            message[8],message[9],message[10],message[11],message[12],message[13],message[14],
+            message[15],message[16],message[17],message[18],message[19],message[20],
+            message[21],message[22],message[23],message[24],message[25],message[26],
+            message[27],message[28],message[29]);
+
+    hd_agnss_uart_write(message, len);
+    hd_agnss_delay(3); // just example, use wait 3ms instead of ACK
+
+    return 0;
+}
+
+/************************************location inject*************************************/
+static int gnss_inject_location(int32_t latitude, int32_t longitude, float altitude, float accuracy)
+{
+    uint8_t cmd[21] = { 0 }; /* packet head+payload */
+    uint32_t acc = (uint32_t)(fabs(accuracy));
+    uint32_t alti = (uint32_t)(altitude * 100); // m--->cm
+    uint32_t i = 0;
+    uint8_t message[25] = {0}; /* payload:17 + packet pad:8 */
+
+    memset(cmd, 0, sizeof(cmd));
+    cmd[0] = 0xF1;
+    cmd[1] = 0xD9;
+    cmd[2] = 0x0B;
+    cmd[3] = 0x10;
+
+    /* LLA : 1 */
+    cmd[4] = 0x01;
+
+    /* lat : 4 */
+    for (i = 0; i < 4; i++)
+    {
+        cmd[5 + i] = (latitude >> (i * 8)) & 0xff;
+    }
+
+    /* long : 4 */
+    for (i = 0; i < 4; i++)
+    {
+        cmd[9 + i] = (longitude >> (i * 8)) & 0xff;
+    }
+
+    /* alti : 4 */
+    for (i = 0; i < 4; i++)
+    {
+        cmd[13 + i] = (alti >> (i * 8)) & 0xff;
+    }
+
+    /* accuracy : 4 */
+    for (i = 0; i < 4; i++)
+    {
+        cmd[17 + i] = (acc >> (i * 8)) & 0xff;
+    }
+
+
+    int32_t len = message_package(message, cmd, sizeof(cmd) - 4);
+
+    LOGE("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
+                message[0],message[1],message[2],message[3],message[4],message[5],message[6],message[7],
+                message[8],message[9],message[10],message[11],message[12],message[13],message[14],
+                message[15],message[16],message[17],message[18],message[19],message[20],
+                message[21],message[22],message[23],message[24]);
+
+    hd_agnss_uart_write(message, len);
+    hd_agnss_delay(3); // just example, use wait 3ms instead of ACK
+
+    return 0;
+}
+
+/************************************eph data inject*************************************/ 
+/**
+* @brief get the eph frame and send to HD80xx
+* @param data: the pointer of the eph data file
+* @param len : the total length of eph data file(eg:the length of HD_GPS_BD.hdb )
+* @retval 0: successs -1 error
+*/
+static int gnss_eph_inject_data(const char *eph_file_path)
+{
+    int packet_length;
+    int eph_file_fd = -1;
+    int size = 0;
+    int left_size = 0;
+    int total_size = 0;
+    int write_size = 0;
+    int wait_time = 0;
+    uint8_t *databuf = (uint8_t *)malloc(BUFFER_SIZE);
+    if(databuf == NULL)
+    {
+        LOGE("malloc fail");
+        return INJECT_RESULT_FAIL;
+    }
+    
+    eph_file_fd = open(eph_file_path, O_RDWR);
+    if (eph_file_fd <= 0)
+    {
+        LOGE("%s open file FAIL. errno:%d\n", __FUNCTION__, errno);
+        goto error; 
+    }
+    while(0 < (size = read(eph_file_fd, (databuf + left_size), BUFFER_SIZE)))
+    {
+        total_size = size + left_size;
+        left_size = 0;
+        for(int i=0; i < total_size;)
+        {
+            if((databuf[i] == 0xF1) && (databuf[i + 1] == 0xD9))
+            {
+                packet_length = (databuf[i + 4] | (databuf[i + 5] << 8));
+                if (i + packet_length + 8 <= total_size)
+                {
+                    hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_WAIT_RETURN);
+                    write_size = hd_agnss_uart_write(databuf + i, packet_length + 8);
+                    if(write_size < 0)
+                    {
+                        LOGE("hd_agnss_uart_write fail");
+                        goto error; 
+                    }
+                    LOGD("%s Write[%d]\r\n", __FUNCTION__, write_size);
+                    wait_time = 0;
+                    while(1)
+                    {
+                        wait_time += 100;
+                        hd_agnss_delay(wait_time);
+                        if(wait_time < 1000)
+                        {
+                            if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_SUCCESS)
+                            {
+                                break;
+                            }
+                            else if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_FAIL)
+                            {
+                                LOGE("8122 return fail");
+                                goto error;
+                            }
+                            else
+                            {
+                                LOGE("eph inject wait 8122 return");
+                            }
+                        }
+                        else
+                        {
+                            LOGE("8122 wait 1s return timeout");
+                            goto error;
+                        }
+                    }
+                    i = i + packet_length + 8;
+                }
+                else
+                {
+                    left_size = total_size - i;
+                    uint8_t *tmp = databuf;
+                    databuf = (uint8_t *)malloc(BUFFER_SIZE + left_size);
+                    memcpy(databuf, tmp + i ,left_size);
+                    free(tmp);
+                    break;
+                }
+            }
+            else
+            {
+                i++;
+            }
+        }
+    }
+    
+    if(databuf)
+    {
+        free(databuf);
+        databuf = NULL;
+    }
+    if(eph_file_fd > 0)
+    {
+        close(eph_file_fd);
+        eph_file_fd = -1;
+    }
+    hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
+    return INJECT_RESULT_SUCCESS;
+error:
+    if(databuf)
+    {
+        free(databuf);
+        databuf = NULL;
+    }
+    if(eph_file_fd > 0)
+    {
+        close(eph_file_fd);
+        eph_file_fd = -1;
+    }
+    hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
+    return INJECT_RESULT_FAIL;
+}
+
+/************************************choice func inject*************************************/
+/**
+  * @brief  AGNSS星历注入、位置注入、时间注入。星历、位置、时间可选择性注入。
+  * @param  eph_file_path:从服务器下载的星历数据文件路径;若无则填NULL
+
+            latitude:纬度,乘以10^7;若无则填0
+            longitude:经度,乘以10^7;若无则填0
+            altitude:高程,浮点,单位为m;若无则填0
+            accuracy:精度;若无则填0
+
+            UTC_time:UTC时间;若无则填NULL
+  * @retval VOID
+**/
+int hd_agnss_inject(const char *eph_file_path, int32_t latitude, int32_t longitude, float altitude, float accuracy, /****latitude和longitude由double型乘以10^7得到*****/
+                            HD_AGNSS_UTC_TIME_TYPE *UTC_time)
+{
+    int ret = INJECT_RESULT_SUCCESS;
+    if (UTC_time != NULL) 
+    {
+        gnss_inject_time(UTC_time);
+    }
+
+    if ((latitude != 0) && (longitude != 0)) 
+    {
+        gnss_inject_location(latitude, longitude, altitude, accuracy);
+    }
+
+    if (eph_file_path != NULL) 
+    {
+        ret = gnss_eph_inject_data(eph_file_path);
+        if(ret < 0)
+        {
+            LOGE("gnss_eph_inject_data fail");
+            return INJECT_RESULT_FAIL;
+        }
+    }
+    return INJECT_RESULT_SUCCESS;
+}
+
+
+/************************************set fd*************************************/
+void hd_set_gnss_dev_fd(int fd)
+{
+    hd_fd = fd;
+}
+
+/************************************check return*************************************/
+//gps f1 d9 05 01 02 00 0b 32 46 74
+//bds f1 d9 05 01 02 00 0b 33 46 74
+//glo f1 d9 05 01 02 00 0b 34 46 74
+
+int hd_eph_inject_result_check(const uint8_t *pack, int pack_len)
+{
+    if(pack_len == 0 || pack_len % 10)
+    {
+        LOGE("pack_len(%d) error.", pack_len);
+        return -1;
+    }
+    int count = pack_len / 10;
+    int i = 0;
+    while(i < count)
+    {
+        const uint8_t *ptr = pack + i * 10;
+        if(ptr[0] != 0xf1 || ptr[1] != 0xd9)
+        {
+            LOGE("Pack head error : %02x %02x", ptr[0], ptr[1]);
+            return INJECT_RESULT_FAIL;
+        }
+
+        if(ptr[2] != 0x05)
+        {
+            LOGE("Type not 0x05 : %02x", ptr[2]);
+            return INJECT_RESULT_FAIL;
+        }
+
+        if(ptr[6] != 0x0b || (ptr[7] < 0x32 && ptr[7] > 0x36))
+        {
+            LOGE("Unknown gid - %d, sid - %d", ptr[6], ptr[7]);
+            return INJECT_RESULT_FAIL;
+        }
+
+        if(ptr[3] == 0x01)
+        {
+            return INJECT_RESULT_SUCCESS;
+        }
+        else if(ptr[3] == 0x00)
+        {
+            return INJECT_RESULT_FAIL;
+        }
+        else
+        {
+            LOGE("ID not 0x00 or 0x01 : %02x", ptr[3]);
+            return INJECT_RESULT_FAIL;
+        }
+        i++;
+    }
+
+    return INJECT_RESULT_SUCCESS;
+}
+/************************************get or set status*************************************/
+void hd_set_eph_inject_status(hd_eph_inject_status_type status)
+{
+    eph_inject_status = status;
+}
+
+hd_eph_inject_status_type hd_get_eph_inject_status(void)
+{
+    return eph_inject_status;
+}
+
diff --git a/mbtk/mbtk_gnssd/agps/8122_agnss.h b/mbtk/mbtk_gnssd/agps/8122_agnss.h
new file mode 100755
index 0000000..497a6d4
--- /dev/null
+++ b/mbtk/mbtk_gnssd/agps/8122_agnss.h
@@ -0,0 +1,45 @@
+#ifndef _8122_AGNSS_H_
+#define _8122_AGNSS_H_
+//#define PYTHON_SUPPORT 1
+
+typedef enum {
+    HD_EPH_INJECT_STATUS_SUCCESS,
+    HD_EPH_INJECT_STATUS_FAIL,
+    HD_EPH_INJECT_STATUS_WAIT_RETURN
+} hd_eph_inject_status_type;
+
+typedef struct {
+    uint16_t year; //2000 ~ 0xffff
+    uint8_t month; // 1 ~ 12
+    uint8_t day; //1 ~ 31
+    uint8_t hour; // 0 ~ 24
+    uint8_t min; // 0 ~ 60
+    uint8_t second; // 0 ~ 60
+}HD_AGNSS_UTC_TIME_TYPE;
+
+/**
+  * @brief  AGNSS星历注入、位置注入、时间注入。星历、位置、时间可选择性注入。
+  * @param  eph_file_path:从服务器下载的星历数据文件路径;若无则填NULL
+
+            latitude:纬度,乘以10^7;若无则填0
+            longitude:经度,乘以10^7;若无则填0
+            altitude:高程,浮点,单位为m;若无则填0
+            accuracy:精度;若无则填0
+
+            UTC_time:UTC时间;若无则填NULL
+  * @retval void
+**/
+int hd_agnss_inject(const char *eph_file_path, int32_t latitude, int32_t longitude, float altitude, float accuracy, /****latitude和longitude由double型乘以10^7得到*****/
+                                HD_AGNSS_UTC_TIME_TYPE *UTC_time);
+
+
+void hd_set_gnss_dev_fd(int fd);
+
+int hd_eph_inject_result_check(const uint8_t *pack, int pack_len);
+
+void hd_set_eph_inject_status(hd_eph_inject_status_type status);
+
+hd_eph_inject_status_type hd_get_eph_inject_status(void);
+
+#endif
+
diff --git a/mbtk/mbtk_gnssd/agps/agnss_http_download.c b/mbtk/mbtk_gnssd/agps/agnss_http_download.c
new file mode 100755
index 0000000..a9ca306
--- /dev/null
+++ b/mbtk/mbtk_gnssd/agps/agnss_http_download.c
@@ -0,0 +1,115 @@
+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include <unistd.h>

+#include <errno.h>

+#include <fcntl.h>

+#include <string.h>

+#include <errno.h>

+#include <arpa/inet.h>

+

+#include "agnss_http_download.h"

+#include "mbtk_log.h"

+#include "mbtk_http.h"

+

+#define HTTP_RESULT_SUCCESS 0

+#define HTTP_RESULT_FAIL    -1

+

+static char eph_file_path[128] = {0};

+static int eph_file_fd = -1;

+

+static void http_data_cb_func(int session_id, mbtk_http_data_type_enum type, void *data,int data_len)

+{

+    int ret = 0;

+

+    if(type == MBTK_HTTP_DATA_HEADER) 

+    {

+        LOGD("Header(%d):%s", data_len, (char*)data);

+        if(eph_file_fd > 0)

+        {

+            return;

+        }

+        unlink(eph_file_path);

+        eph_file_fd = open(eph_file_path, O_RDWR|O_CREAT|O_TRUNC, 0644);

+        if (eph_file_fd < 0)

+        {

+            LOGD("file open error");

+        }

+        else

+        {

+            LOGD("agnss file open: %d", eph_file_fd);

+        }

+    } 

+    else if(type == MBTK_HTTP_DATA_CONTENT) 

+    {

+        LOGD("http Data(%d)", data_len);

+

+        ret = write(eph_file_fd, (char*)data, data_len);

+        if (ret < 0) 

+        {

+            LOGE("%s: error writing to file!", __FUNCTION__);

+        } 

+        else if (ret < data_len) 

+        {

+            LOGD("%s: wrote less the buffer size!", __FUNCTION__);

+        }

+        else

+        {

+            //

+        }

+    } 

+    else 

+    {

+        LOGD(">>>>>Complete<<<<<");

+        if(eph_file_fd <= 0)

+        {

+            return;

+        }

+        close(eph_file_fd);

+        eph_file_fd = -1;

+    }

+}

+

+int eph_data_from_http_get(char *host, const char *path)

+{

+    if(host == NULL || path == NULL || strlen(path) == 0)

+    {

+        LOGE("eph_data_from_http_get param is error.");

+    }

+    

+    int http_handle = mbtk_http_handle_get(TRUE, http_data_cb_func);

+    if(http_handle < 0)

+    {

+        LOGE("mbtk_http_handle_get() fail.");

+        return HTTP_RESULT_FAIL;

+    }

+    int http_session = mbtk_http_session_create(http_handle, HTTP_OPTION_GET, HTTP_VERSION_1_1);

+    if(http_handle < 0)

+    {

+        LOGE("mbtk_http_session_create() fail.");

+        goto error;

+    }

+

+    memcpy(eph_file_path, path, strlen(path));

+    if(mbtk_http_session_url_set(http_handle, http_session, host))

+    {

+        LOGE("mbtk_http_session_url_set() fail.\n");

+        goto error;

+    }

+    if(mbtk_http_session_start(http_handle, http_session))

+    {

+        LOGE("mbtk_http_session_start() fail.\n");

+        goto error;

+    }

+    if(mbtk_http_handle_free(http_handle))

+    {

+        LOGE("mbtk_http_handle_free() fail.");

+        return HTTP_RESULT_FAIL;

+    }

+

+    return HTTP_RESULT_SUCCESS;

+error:

+    mbtk_http_handle_free(http_handle);

+    return HTTP_RESULT_FAIL;

+}

+

diff --git a/mbtk/mbtk_gnssd/agps/agnss_http_download.h b/mbtk/mbtk_gnssd/agps/agnss_http_download.h
new file mode 100755
index 0000000..8a682bd
--- /dev/null
+++ b/mbtk/mbtk_gnssd/agps/agnss_http_download.h
@@ -0,0 +1,10 @@
+#ifndef _AGNSS_HTTP_DOWNLOAD_H_

+#define _AGNSS_HTTP_DOWNLOAD_H_

+

+#if 0

+int get_eph_data_from_http(char *domain, char *file_path, char *eph_buf);

+#endif

+

+int eph_data_from_http_get(char *host, const char *path);

+

+#endif

diff --git a/mbtk/mbtk_gnssd/gnss_hd8122.c b/mbtk/mbtk_gnssd/gnss_hd8122.c
index 8b476ce..3163819 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.c
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.c
@@ -27,6 +27,8 @@
 #include "gnss_utils.h"
 #include "gnss_hd8122.h"
 #include "hd8122_dl/hd8040_upgrade.h"
+#include "agps/agnss_http_download.h"
+#include "agps/8122_agnss.h"
 
 #define UART_BITRATE_NMEA_DEF_FW    115200   // Default bitrate.
 #define GNSS_POWER_GPIO 43
@@ -37,6 +39,18 @@
 #define GNSS_FW_GQALS_PATH "/lib/firmware/HD8122.YIKE.GN3.115200.0035.720e5.53ef0.GQALS.ANT.EPH.CFG.PPS13.240115R1.bin"
 #define GNSS_FW_GAQBS_PATH "/lib/firmware/HD8122.YIKE.GN3.115200.0037.dbd12.53ef0.GAQBS.B1C.ANT.EPH.CFG.PPS13.240416R1.bin"
 
+//#define AGNSS_TEST_URL               "http://aclientt.allystar.com:80/ephemeris/HD_GPS_BDS.hdb"
+#define AGNSS_URL                    "http://uagnss.allystar.com:80/ephemeris/%s?compid=yikecs1&token=Z38w5urAuawubTxi"
+#define AGNSS_INDIVIDUATION_URL_HEAD "http://cagnss.allystar.com/api/v1/eph/rt?"
+#define AGNSS_ALLSTAR_URL_HEAD       "http://cagnss.allystar.com/api/v1/eph/rta?"
+#define AGNSS_EPH_FILE_PATH          "/lib/firmware/eph_data.txt"
+
+#define AGNSS_EPH_GPS                "HD_GPS.hdb"
+#define AGNSS_EPH_BDS                "HD_BDS.hdb"
+#define AGNSS_EPH_GLO                "HD_GLO.hdb"
+#define AGNSS_EPH_GPS_BDS            "HD_GPS_BDS.hdb"
+#define AGNSS_EPH_GPS_GLO            "HD_GPS_GLO.hdb"
+
 static pthread_cond_t read_cond;
 static pthread_mutex_t read_mutex;
 static bool setting_waitting = FALSE;
@@ -358,6 +372,7 @@
             pthread_mutex_unlock(&read_mutex);
             setting_waitting = FALSE;
         }
+        
     }
     else
     {
@@ -586,6 +601,76 @@
     return GNSS_ERR_DL_FW;
 }
 
+gnss_err_enum gnss_8122_agnss_get_eph(const char *param)
+{
+    if(param == NULL)
+    {
+        LOGD("gnss_8122_agnss_get_eph param is NULL");
+        return GNSS_ERR_ARG;
+    }
+
+    int eph_type = 0;
+    int alam_flag = 0;
+    int ret = -1;
+    char url[256] = {0};
+    if(2 == sscanf(param, "%d,%d", &eph_type, &alam_flag))
+    {
+        if((gnss_eph_data_enum)eph_type == GNSS_EPH_GPS)
+        {
+            snprintf(url, 256,AGNSS_URL, AGNSS_EPH_GPS);
+        }
+        else if((gnss_eph_data_enum)eph_type == GNSS_EPH_BDS)
+        {
+            snprintf(url, 256,AGNSS_URL, AGNSS_EPH_BDS);
+        }
+        else if((gnss_eph_data_enum)eph_type == GNSS_EPH_GLO)
+        {
+            snprintf(url, 256,AGNSS_URL, AGNSS_EPH_GLO);
+        }
+        else if((gnss_eph_data_enum)eph_type == GNSS_EPH_GPS_BDS)
+        {
+            snprintf(url, 256,AGNSS_URL, AGNSS_EPH_GPS_BDS);
+        }
+        else if((gnss_eph_data_enum)eph_type == GNSS_EPH_GPS_GLO)
+        {
+            snprintf(url, 256,AGNSS_URL, AGNSS_EPH_GPS_GLO);
+        }
+        else
+        {
+            return GNSS_ERR_UNSUPPORT;
+        }
+
+        ret = eph_data_from_http_get(url, AGNSS_EPH_FILE_PATH);
+        if (ret < 0)
+        {
+            LOGD("eph_data_from_http_get fail");
+            return GNSS_ERR_EPH_GET_FAIL;
+        }
+        LOGD("get_eph_data_from_http success");
+    }
+    else
+    {
+        LOGD("param num error");
+        return GNSS_ERR_ARG;
+    }
+    return GNSS_ERR_OK;
+}
+
+
+gnss_err_enum gnss_8122_agnss_inject(int fd)
+{
+    int ret = 0;
+    hd_set_gnss_dev_fd(fd);
+    ret = hd_agnss_inject(AGNSS_EPH_FILE_PATH, 0, 0, 0, 0, NULL);
+    hd_set_gnss_dev_fd(-1);
+    if(ret < 0)
+    {
+        LOGD("hd_agnss_inject fail");
+        return GNSS_ERR_EPH_INJECT_FAIL;
+    }
+    return GNSS_ERR_OK;
+}
+
 void gnss_8122_set_cb(const void *data, int data_len)
 {
     const char *buff = (const char*)data;
@@ -593,6 +678,20 @@
     {
         gnss_cmd_rsp_process(data, data_len);
     }
+
+    if(hd_get_eph_inject_status() == HD_EPH_INJECT_STATUS_WAIT_RETURN)
+    {
+        log_hex("EPH_RSP", (const char*)data, data_len);
+        int ret = hd_eph_inject_result_check(data, data_len);
+        if(ret < 0)
+        {
+            hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_FAIL);
+        }
+        else
+        {
+            hd_set_eph_inject_status(HD_EPH_INJECT_STATUS_SUCCESS);
+        }       
+    }
 }
 
 gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len)
diff --git a/mbtk/mbtk_gnssd/gnss_hd8122.h b/mbtk/mbtk_gnssd/gnss_hd8122.h
index 4cd4f46..7df7e7a 100755
--- a/mbtk/mbtk_gnssd/gnss_hd8122.h
+++ b/mbtk/mbtk_gnssd/gnss_hd8122.h
@@ -118,6 +118,9 @@
 
 int gnss_8122_fw_dl(int fd, const char *fw_name, const char *dev);
 
+gnss_err_enum gnss_8122_agnss_get_eph(const char *param);
+
+gnss_err_enum gnss_8122_agnss_inject(int fd);
 //void gnss_8122_dl_read_cb(const void *data, int data_len);
 
 gnss_err_enum gnss_8122_set(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
diff --git a/mbtk/mbtk_gnssd/gnss_info.h b/mbtk/mbtk_gnssd/gnss_info.h
index f29946f..f7e0ed2 100755
--- a/mbtk/mbtk_gnssd/gnss_info.h
+++ b/mbtk/mbtk_gnssd/gnss_info.h
@@ -76,6 +76,8 @@
 typedef void (*gnss_dl_read_cb_func)(const void *data, int data_len);
 typedef gnss_err_enum (*gnss_set_func)(int fd, const char *cmd, void *cmd_rsp, int cmd_rsp_len);
 typedef void (*gnss_set_cb_func)(const void *data, int data_len);
+typedef gnss_err_enum (*gnss_agnss_get_eph_func)(const char *param);
+typedef gnss_err_enum (*gnss_agnss_inject_func)(int fd);
 
 typedef enum {
     GNSS_TYPE_6228 = 0,
@@ -85,6 +87,14 @@
 } gnss_id_enum;
 
 typedef enum {
+    GNSS_EPH_GPS = 0,
+    GNSS_EPH_BDS,
+    GNSS_EPH_GLO,
+    GNSS_EPH_GPS_BDS,
+    GNSS_EPH_GPS_GLO
+} gnss_eph_data_enum;
+
+typedef enum {
     GNSS_STATE_CLOSE,       // GNSS is closed.
     GNSS_STATE_CLOSING,       // GNSS is closing.
     GNSS_STATE_OPEN,        // GNSS is opened.
@@ -118,6 +128,8 @@
     gnss_dl_read_cb_func gnss_dl_read_cb;
     gnss_set_func gnss_set;
     gnss_set_cb_func gnss_set_cb;
+    gnss_agnss_get_eph_func gnss_agnss_get_eph;
+    gnss_agnss_inject_func  gnss_agnss_inject;
 } gnss_info_t;
 
 int gnss_init(uint32 print_port);
@@ -128,6 +140,10 @@
 
 int gnss_dl_fw(const char* fw_name, void *rsp, int rsp_len);
 
+int gnss_agnss_get_ept(const void* param);
+
+int gnss_agnss_inject(void);
+
 int gnss_ind_set(int fd, int ind_type);
 
 #endif /* _GNSS_INFO_H */
diff --git a/mbtk/mbtk_gnssd/gnss_ipc.c b/mbtk/mbtk_gnssd/gnss_ipc.c
index 5ea9bfa..c343cd0 100755
--- a/mbtk/mbtk_gnssd/gnss_ipc.c
+++ b/mbtk/mbtk_gnssd/gnss_ipc.c
@@ -88,6 +88,18 @@
         char rsp[100] = {0};
         sprintf(rsp, "%cgnss_dl:%d%c", MBTK_IND_START_FLAG, ret, MBTK_IND_END_FLAG);
         gnss_write(fd, rsp, strlen(rsp));
+    } else if(memcmp(msg, "gnss_agnss_get", 14) == 0) {// gnss_agps_get
+        int ret = gnss_agnss_get_eph(msg + 15);
+
+        char rsp[100] = {0};
+        sprintf(rsp, "%cgnss_agnss_get:%d%c", MBTK_IND_START_FLAG, ret, MBTK_IND_END_FLAG);
+        gnss_write(fd, rsp, strlen(rsp));
+    } else if(memcmp(msg, "gnss_agnss_set", 14) == 0) {// gnss_agps_set
+        int ret = gnss_agnss_inject();
+
+        char rsp[100] = {0};
+        sprintf(rsp, "%cgnss_agnss_set:%d%c", MBTK_IND_START_FLAG, ret, MBTK_IND_END_FLAG);
+        gnss_write(fd, rsp, strlen(rsp));
     } else if(memcmp(msg, "gnss_ind", 8) == 0) {// gnss_ind:ind_type
         int ind_type = atoi(msg + 9);
         int ret = gnss_ind_set(fd, ind_type);
diff --git a/mbtk/mbtk_gnssd/gnss_main.c b/mbtk/mbtk_gnssd/gnss_main.c
index 3d48ea0..8b91df2 100755
--- a/mbtk/mbtk_gnssd/gnss_main.c
+++ b/mbtk/mbtk_gnssd/gnss_main.c
@@ -959,6 +959,40 @@
     }
 }
 
+int gnss_agnss_get_eph(const void* param)
+{
+    if(gnss_info.gnss_agnss_get_eph)
+    {
+        return gnss_info.gnss_agnss_get_eph(param);
+    }
+    else
+    {
+        return GNSS_ERR_UNSUPPORT;
+    }
+
+    return GNSS_ERR_OK;
+}
+
+int gnss_agnss_inject(void)
+{
+    if(gnss_info.state != GNSS_STATE_READY)
+    {
+        LOGE("gnss not ready");
+        return GNSS_ERR_UNKNOWN;
+    }
+    
+    if(gnss_info.gnss_agnss_inject)
+    {
+        return gnss_info.gnss_agnss_inject(gnss_info.fd);
+    }
+    else
+    {
+        return GNSS_ERR_UNSUPPORT;
+    }
+    
+    return GNSS_ERR_OK;
+}
+
 int gnss_ind_set(int fd, int ind_type)
 {
     int index = 0;
@@ -1092,6 +1126,8 @@
         gnss_info.gnss_dl_read_cb = gnss_6228_dl_read_cb;
         gnss_info.gnss_set = gnss_6228_set;
         gnss_info.gnss_set_cb = gnss_6228_set_cb;
+        gnss_info.gnss_agnss_get_eph = NULL;
+        gnss_info.gnss_agnss_inject = NULL;
     } else if(!strcmp(argv[1], GNSS_ID_8122)) {
         gnss_info.gnss_id = GNSS_TYPE_8122;
         gnss_info.auto_open = (bool)atoi(argv[3]);
@@ -1105,6 +1141,8 @@
         gnss_info.gnss_dl_read_cb = NULL;
         gnss_info.gnss_set = gnss_8122_set;
         gnss_info.gnss_set_cb = gnss_8122_set_cb;
+        gnss_info.gnss_agnss_get_eph = gnss_8122_agnss_get_eph;
+        gnss_info.gnss_agnss_inject = gnss_8122_agnss_inject;
     } else if(!strcmp(argv[1], GNSS_ID_5311)) {
         gnss_info.gnss_id = GNSS_TYPE_5311;
         gnss_info.auto_open = (bool)atoi(argv[3]);
@@ -1118,6 +1156,8 @@
         gnss_info.gnss_dl_read_cb = NULL;
         gnss_info.gnss_set = gnss_5311_set;
         gnss_info.gnss_set_cb = gnss_5311_set_cb;
+        gnss_info.gnss_agnss_get_eph = NULL;
+        gnss_info.gnss_agnss_inject = NULL;
     } else if(!strcmp(argv[1], GNSS_ID_N50DB)) {
         gnss_info.gnss_id = GNSS_TYPE_N50DB;
         gnss_info.auto_open = (bool)atoi(argv[3]);
@@ -1131,6 +1171,8 @@
         gnss_info.gnss_dl_read_cb = NULL;
         gnss_info.gnss_set = gnss_n50db_set;
         gnss_info.gnss_set_cb = gnss_n50db_set_cb;
+        gnss_info.gnss_agnss_get_eph = NULL;
+        gnss_info.gnss_agnss_inject = NULL;
     } else {
         LOGE("No support : %s", argv[1]);
         return -1;