[Feature][T8TSK-289]merge old platform branch, add meta to public rep

Only Configure: No
Affected branch: MR3.0-Merge-v2.0
Affected module: all lynq
Is it affected on both ZXIC and MTK: only MTK
Self-test: No
Doc Update: No
diff --git a/common_src/lib/liblynq-at-factory/lynq_at_factory.cpp b/common_src/lib/liblynq-at-factory/lynq_at_factory.cpp
index 3f1bfa9..fc4d4ec 100755
--- a/common_src/lib/liblynq-at-factory/lynq_at_factory.cpp
+++ b/common_src/lib/liblynq-at-factory/lynq_at_factory.cpp
@@ -1,8 +1,14 @@
-

-

 #include <string.h>

 #include <stdio.h>

 #include <stdlib.h>

+#include <sys/socket.h>

+#include <sys/time.h>

+#include <error.h>

+#include <string.h>

+#include <netinet/in.h>

+#include <arpa/inet.h>

+#include <net/if.h>

+#include <errno.h>

 #include <log/log.h>

 #include <liblog/lynq_deflog.h>

 #include "include/libat/lynq_at_factory.h"

@@ -30,6 +36,19 @@
     Urc

 };

 

+void lynq_response_ok()

+{

+    char *str = "OK";

+    handle_output(str, strlen(str), Response);

+}

+

+void lynq_response_error(int error_code)

+{

+    char str[32] = {0};

+    sprintf(str, "+CME ERROR: %d", error_code);

+    handle_output(str, strlen(str), Response);

+}

+

 void lynq_handle_adc(char *input)

 {

     FILE *fp;

@@ -60,40 +79,115 @@
     {

         handle_output(flag, strlen(flag), Response);

     }

+    lynq_response_ok();

     pclose(fp);

 }

 

+int set_campare(char dev_buf[][40],char *buf_str[3])

+{

+    FILE *fp;

+    int k = 15;

+    int j;

+    char lynq_usb_buf[256] = {0};

+    char buf[256] = {0};

+    for(j=0;j++;j<3)

+    {

+        sprintf(lynq_usb_buf,"cat /sys/class/leds/led95%d:%s",k++, dev_buf[j]);

+        fp=popen(lynq_usb_buf, "r");

+        fgets(buf, sizeof(buf), fp);

+        if(strcmp(buf,buf_str[j]))

+        {

+            pclose(fp);

+            return -1;

+        }

+        pclose(fp);

+    }

+    return 0;

+}

 void lynq_handle_sink(char *input)

 {

     FILE *fp;

-    char lynq_usb_dev[512] = {0};

-    char lynq_usb_buf[512] = {0};

-    char buf[512] = {0};

-    int sink[3][3] = {{255,0,0},{0,255,0},{0,0,255}};

-    char dev_buf[][40]={{"green:cellular-radio/brightness"},{"green:cellular-quality/brightness"},{"red:system/brightness"}};

-    int i;

-    int j;

-    int k = 15;

+    time_t start,end;

+    char lynq_usb_dev[256] = {0};

+    char lynq[256] = {0};

+    char char_buf[16] = {0};

     char flag_buf[64] = {0};

-    for(i = 0;i < 3;i++){

+    int sink[3][3] = {{255,0,0},{0,255,0},{0,0,255}};

+    char dev_buf[][40] = {{"green:cellular-radio/brightness"},{"green:cellular-quality/brightness"},{"red:system/brightness"}};

+    char *str_buf[3] = {"0","0","0"};

+    int i,j,ret;

+    int state = 0;

+    int k = 15;

+

+    for(i = 0;i < 3;i++)

+    {

         bzero(flag_buf, 64);

-        bzero(lynq_usb_buf, 512);

-        bzero(buf, 512);

         k = 15;

-        for(j = 0;j < 3;j++){

-            bzero(lynq_usb_dev, 512);

-            sprintf(lynq_usb_dev,"echo %d >  /sys/class/leds/led95%d:%s  2>&1", sink[i][j], k++, dev_buf[j]);

-            fp=popen(lynq_usb_dev, "r");

+

+        switch(i)

+        {

+        case 0:

+        {

+            str_buf[0]="255";

+            str_buf[1]="0";

+            str_buf[2]="0";

+            break;

         }

-        usleep(10000);

-        sprintf(lynq_usb_buf,"cat /sys/bus/iio/devices/iio:device1/in_voltage4_input  2>&1");

-        fp=popen(lynq_usb_buf, "r");

-        

-        fgets(buf, sizeof(buf), fp);

-        sprintf(flag_buf, "%s%d%s%s%s", "SINK[", i+1, "]: ", buf, "\n");

-        handle_output(flag_buf, strlen(flag_buf), Response);

+

+        case 1:

+        {

+            str_buf[0]="0";

+            str_buf[1]="255";

+            str_buf[2]="0";

+            break;

+        }

+

+        case 2:

+        {

+            str_buf[0]="0";

+            str_buf[1]="0";

+            str_buf[2]="255";

+            break;

+        }

+        }

+        for(int h=0;h<20;h++)

+        {

+            for(j = 0;j < 3;j++)

+            {

+                bzero(lynq_usb_dev, 256);

+                sprintf(lynq_usb_dev,"echo %d >  /sys/class/leds/led95%d:%s  2>&1", sink[i][j], k++, dev_buf[j]);

+                fp=popen(lynq_usb_dev, "r");

+                pclose(fp);

+            }

+            bzero(char_buf,16);

+            if(set_campare(dev_buf,str_buf))

+            {

+                RLOGD("pre_campare fail %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+                continue;

+            }

+            sprintf(lynq,"cat /sys/bus/iio/devices/iio:device1/in_voltage4_input  2>&1");

+            fp=popen(lynq, "r");

+            fgets(char_buf, sizeof(char_buf), fp);

+

+            if(set_campare(dev_buf,str_buf))

+            {

+                RLOGD("behand_campare fail %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+                continue;

+            }

+            sprintf(flag_buf, "%s%d%s%s%s", "SINK[", i+1, "]: ", char_buf, "\n");

+            handle_output(flag_buf, strlen(flag_buf), Response);

+            state =1;

+            break;

+        }

+        if(state == 0)

+        {

+            sprintf(flag_buf, "%s%d%s%s%s", "SINK[", i+1, "]: ", char_buf, "\n");

+            handle_output(flag_buf, strlen(flag_buf), Response);

+        }

     }

     pclose(fp);

+    lynq_response_ok();

+    return;

 }

 

 void lynq_handle_emmc(char *input)

@@ -104,21 +198,49 @@
     sprintf(emmc_buf, "ls /dev | grep mmcblk0  2>&1");

     fp=popen(emmc_buf, "r");

     if(!fp){

-        char *str = "\n+CME: POPEN ERROR\n";

-        handle_output(str, strlen(str), Response);

+        lynq_response_error(100);

         return;

     }

     while(fgets(buf, sizeof(buf), fp) != NULL){

-        char *str = "+EMMC: OK \n";

-        handle_output(str, strlen(str), Response); 

+        lynq_response_ok();

         pclose(fp);

-        return;   

+        return;

     }

-    char *str = "\033[47;31m+EMMC: ERROR\033[0m\n";

-    handle_output(str, strlen(str), Response);

+    lynq_response_error(100);

     pclose(fp);

 }

 

+static int set_all_gpio_status_and_check(int lynq_gpio_arr[], char status)

+{

+    int m =0;

+    FILE *fp;

+    char lynq_set_gpio_arr[256] = {0};

+    char lynq_get_gpio_state[512] = {0};

+    for(m = 0; m < 85; m++)

+    {

+        bzero(lynq_set_gpio_arr, 256);

+        sprintf(lynq_set_gpio_arr,"echo mode %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[m]);

+        system(lynq_set_gpio_arr);

+        bzero(lynq_set_gpio_arr, 256);

+        sprintf(lynq_set_gpio_arr,"echo out %d %c > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[m], status);

+        system(lynq_set_gpio_arr);

+    }

+

+    bzero(lynq_set_gpio_arr, 256);

+    sprintf(lynq_set_gpio_arr,"cat /sys/devices/platform/10005000.pinctrl/mt_gpio | grep 006");

+    fp=popen(lynq_set_gpio_arr, "r");

+    bzero(lynq_get_gpio_state, 512);

+    fgets(lynq_get_gpio_state,sizeof(lynq_get_gpio_state),fp);

+    pclose(fp);

+    

+    if(lynq_get_gpio_state[7] != status)

+    {

+        return 1;

+    }

+    //usleep(10000);

+    return 0;

+}

+

 void lynq_handle_gpio(char *input)

 {

     FILE *fp;

@@ -128,74 +250,135 @@
     char lynq_show_gpio_state[64] = {0};

     int lynq_gpio_low = 0;

     int lynq_gpio_hig = 0;

-    int i = 0,m = 0;

+    int lynq_gpio_test_env_error = 1;

+    int i = 0,m = 0,j = 0;

+    int need_int = 1;

     int lynq_gpio_beta_state = 1;

-

-    for(m = 0; m < 85; m++)

+    RLOGD("start function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+    

+    for(i=0; i < 85; i++)

     {

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"echo mode %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[m]);

-        system(lynq_set_gpio_arr);

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"echo out %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[m]);

-        system(lynq_set_gpio_arr);

-    }

 

-    for(i = 0; i < 85; i++)

-    {

-        lynq_gpio_low = 0;

-        lynq_gpio_hig = 0;

-

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"echo mode %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

-        system(lynq_set_gpio_arr);

-

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"echo out %d 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

-        system(lynq_set_gpio_arr);

-

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"cat /sys/devices/platform/10005000.pinctrl/mt_gpio | grep 006");

-        fp=popen(lynq_set_gpio_arr, "r");

-        bzero(lynq_get_gpio_state, 512);

-        fgets(lynq_get_gpio_state,sizeof(lynq_get_gpio_state),fp);

-        pclose(fp);

-        if(lynq_get_gpio_state[7] == '1')

+        for(j=0;j<3;j++)

         {

-            lynq_gpio_hig = 1;

-        }

+            if  (j > 0) // reset gpio when retry

+            {

+                need_int = 1;

+            }

 

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"echo out %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

-        system(lynq_set_gpio_arr);

-        

-        bzero(lynq_set_gpio_arr, 256);

-        sprintf(lynq_set_gpio_arr,"cat /sys/devices/platform/10005000.pinctrl/mt_gpio | grep 006");

-        fp=popen(lynq_set_gpio_arr, "r");

-        bzero(lynq_get_gpio_state, 512);

-        fgets(lynq_get_gpio_state,sizeof(lynq_get_gpio_state),fp);

-        pclose(fp);

-        if(lynq_get_gpio_state[7] == '0')

+            if (need_int == 1)

+            {

+                if (set_all_gpio_status_and_check(lynq_gpio_arr, '0') != 0)

+                {

+                    continue;

+                }

+                else

+                {

+                    need_int = 0;

+                }

+                RLOGD("finsh peizhi function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+            }

+

+            lynq_gpio_low = 0;

+            lynq_gpio_hig = 0;

+

+            for(int n=0;n<3;n++)

+            {

+                bzero(lynq_set_gpio_arr, 256);

+                sprintf(lynq_set_gpio_arr,"echo mode %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

+                system(lynq_set_gpio_arr);

+

+                bzero(lynq_set_gpio_arr, 256);

+                sprintf(lynq_set_gpio_arr,"echo out %d 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

+                system(lynq_set_gpio_arr);

+

+

+                bzero(lynq_set_gpio_arr, 256);

+                sprintf(lynq_set_gpio_arr,"cat /sys/devices/platform/10005000.pinctrl/mt_gpio | grep 006");

+                fp=popen(lynq_set_gpio_arr, "r");

+                bzero(lynq_get_gpio_state, 512);

+                fgets(lynq_get_gpio_state,sizeof(lynq_get_gpio_state),fp);

+                pclose(fp);

+                if(lynq_get_gpio_state[7] == '1')

+                {

+                    RLOGD("high function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+                    lynq_gpio_hig = 1;

+                    lynq_gpio_test_env_error = 0;

+                    break;

+                }

+                else

+                {

+                    RLOGD("high function %s line %d input %s num %d\n", __FUNCTION__, __LINE__, input,lynq_gpio_arr[i]);

+                    if(i == 0 && j == 0)

+                    {

+

+                        lynq_gpio_test_env_error = set_all_gpio_status_and_check(lynq_gpio_arr, '1') == 0 ? 0 : 1;

+                    }

+

+                }

+            }

+            if (lynq_gpio_test_env_error == 1)

+                break;

+            bzero(lynq_set_gpio_arr, 256);

+            sprintf(lynq_set_gpio_arr,"echo out %d 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio",(char*)lynq_gpio_arr[i]);

+            system(lynq_set_gpio_arr);

+            

+            bzero(lynq_set_gpio_arr, 256);

+            sprintf(lynq_set_gpio_arr,"cat /sys/devices/platform/10005000.pinctrl/mt_gpio | grep 006");

+            fp=popen(lynq_set_gpio_arr, "r");

+            bzero(lynq_get_gpio_state, 512);

+            fgets(lynq_get_gpio_state,sizeof(lynq_get_gpio_state),fp);

+            pclose(fp);

+            if(lynq_get_gpio_state[7] == '0')

+            {

+                RLOGI("*low function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+                lynq_gpio_low = 1;

+            }

+            else

+            {

+                RLOGD("low function fail %s line %d input %s num %d\n", __FUNCTION__, __LINE__, input,lynq_gpio_arr[i]);

+            }

+            bzero(lynq_show_gpio_state, 64);

+            if((lynq_gpio_low != 1) || (lynq_gpio_hig != 1))

+            {

+                RLOGD("fail function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+            }

+            else

+            {

+                RLOGD("success function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+                sprintf(lynq_show_gpio_state,"gpio%d\n",(char *)lynq_gpio_arr[i]);

+                handle_output(lynq_show_gpio_state, strlen(lynq_show_gpio_state), Response);

+                break; // do not retry when pass

+            }

+        } // for(j=0;j<3;j++)

+        if (lynq_gpio_test_env_error == 1)

         {

-            lynq_gpio_low = 1;

+            lynq_gpio_beta_state = 0;

+            break;

         }

-        bzero(lynq_show_gpio_state, 64);

-        if((lynq_gpio_low != 1) || (lynq_gpio_hig != 1))

+        if (j >= 3 )

         {

             lynq_gpio_beta_state = 0;

             sprintf(lynq_show_gpio_state,"[gpio%d][result]:FAIL \n",(char *)lynq_gpio_arr[i]);

             handle_output(lynq_show_gpio_state, strlen(lynq_show_gpio_state), Response);

         }

-        else

-        {

-            sprintf(lynq_show_gpio_state,"gpio%d\n",(char *)lynq_gpio_arr[i]);

-            handle_output(lynq_show_gpio_state, strlen(lynq_show_gpio_state), Response);

-        }

+

+    } // for(i=0; i < 85; i++)

+

+    if(lynq_gpio_test_env_error == 1)

+    {

+        handle_output("tool error", strlen("tool error"), Response);

     }

+

     if(lynq_gpio_beta_state == 1)

     {

-        sprintf(lynq_show_gpio_state,"[gpio][result]:PASS \n");

-        handle_output(lynq_show_gpio_state, strlen(lynq_show_gpio_state), Response);

+        RLOGD("total success function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+        lynq_response_ok();

+    }

+    else

+    {

+        RLOGD("total fail function %s line %d input %s\n", __FUNCTION__, __LINE__, input);

+        lynq_response_error(100);

     }

 }

 

@@ -210,16 +393,275 @@
     pclose(fp);

     if(lynq_get_gpio_state[6] == '1')

     {

-        char *str = "+PCIE: OK\n";

-        handle_output(str, strlen(str), Response);

+        lynq_response_ok();

     }

     else

     {

-        char *str = "+PCIE: ERROR\n";

-        handle_output(str, strlen(str), Response);

+        lynq_response_error(100);

     }

 }

 

+int receive_data(int fd,char *buf_send,char *buf_recv, int send_len)

+{

+    time_t time_start;

+    time_t time_end;

+    int ret = 0;

+    time_start=time(NULL);

+    for(int recv =0;recv <50;recv++)

+    {

+        bzero(buf_recv, send_len);

+        ret = recvfrom(fd,buf_recv,1024,0,NULL,NULL);

+        if(ret<0)

+        {

+            handle_output("time_out", strlen("time_out"), Response);

+            return -1;

+        }

+        else if (ret != send_len)

+        {

+            continue;

+        }

+

+        if(memcmp(buf_send,buf_recv, send_len))

+        {

+            time_end=time(NULL);

+            if(difftime(time_end,time_start)>2)

+            {

+                handle_output("time_out", strlen("time_out"), Response);

+                break;

+            }

+        }

+        else

+        {

+            return 0;

+        }

+    }

+    handle_output("can't receive correct data", strlen("can't receive correct data"), Response);

+    return -1;

+}

+

+int rsgmii_init()

+{

+    char lynq_set_rgmii_arr[256] = {0};

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth1 | grep \"RUNNING\"");

+    if(system(lynq_set_rgmii_arr))

+    {

+        handle_output("Please checkout network_line", strlen("Please checkout network_line"), Response);

+        return -1;

+    }

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth2 | grep \"RUNNING\"");

+    if(system(lynq_set_rgmii_arr))

+    {

+        handle_output("Please checkout network_line", strlen("Please checkout network_line"), Response);

+        return -1;

+    }

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth1 192.168.11.1");

+    system(lynq_set_rgmii_arr);

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth2 192.168.22.2");

+    system(lynq_set_rgmii_arr);

+

+    

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth1 | grep HWaddr | awk '{print \"ip n add 192.168.11.1 lladdr \"$5\" dev eth2\"}' | sh");

+    system(lynq_set_rgmii_arr);

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth2 | grep HWaddr | awk '{print \"ip n add 192.168.22.2 lladdr \"$5\" dev eth1\"}' | sh");

+    system(lynq_set_rgmii_arr);

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"iptables -t nat -A POSTROUTING -s 192.168.22.2 -d 192.168.11.1 -j SNAT --to-source 192.168.22.44");

+    system(lynq_set_rgmii_arr);

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"iptables -t nat -A POSTROUTING -s 192.168.11.1 -d 192.168.22.2 -j SNAT --to-source 192.168.11.33");

+    system(lynq_set_rgmii_arr);

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth1 | grep \"inet addr\" | grep \"192.168.11.1\"");

+    if(system(lynq_set_rgmii_arr))

+    {

+        return -1;

+    }

+

+    bzero(lynq_set_rgmii_arr, 256);

+    sprintf(lynq_set_rgmii_arr,"ifconfig eth2 | grep \"inet addr\" | grep \"192.168.22.2\"");

+    if(system(lynq_set_rgmii_arr))

+    {

+        return -1;

+    }

+    return 0;

+}

+

+

+int rsgmii_socket_init(struct sockaddr_in* server_addr, const char * eth_name, const char * ip_addr)

+{

+    int ser_socket = -1;

+    struct ifreq ser;

+    memset(&ser,0x00,sizeof(ser));

+    strncpy(ser.ifr_name,eth_name,strlen(eth_name));

+

+    server_addr->sin_family=AF_INET;

+    server_addr->sin_port = htons(100);

+    server_addr->sin_addr.s_addr = inet_addr(ip_addr);

+

+

+    ser_socket = socket(AF_INET,SOCK_DGRAM,0);

+    if (ser_socket<0)

+    {

+        return -1;

+    }

+    

+    struct timeval timeout={1,0};

+    int ret;

+    ret = bind(ser_socket,(struct sockaddr*)server_addr,sizeof(*server_addr));

+    if(ret< 0)

+    {

+        close(ser_socket);

+        return -1;

+    }

+    

+    ret = setsockopt(ser_socket,SOL_SOCKET,SO_BINDTODEVICE,(char *)&ser,sizeof(ser));

+    if(ret< 0)

+    {

+        close(ser_socket);

+        return -1;

+    }

+    ret = setsockopt(ser_socket,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));

+    if(ret< 0)

+    {

+        close(ser_socket);

+        return -1;

+    }

+

+    return ser_socket;

+}

+

+void lynq_handle_rsgmii()

+{

+    

+    int ret;

+    int check_count = 0;

+    int check_ok_count = 0;

+    int ser_socket = -1;

+    int cli_socket = -1;

+    char buf_init[1024];

+    char buf_tran[1024];

+    char buf_recv[1024];

+    char flag[256]={0};

+    struct sockaddr_in ser_addr;

+    struct sockaddr_in cli_addr;

+    time_t start,end;

+    bzero(buf_init,sizeof(buf_init));

+    bzero(buf_tran,sizeof(buf_tran));

+    bzero(buf_recv,sizeof(buf_recv));

+    

+    const char *ser_ip = "192.168.22.2";

+    const char *cli_ip = "192.168.11.1";

+    const char * ser_name = "eth2";

+    const char * cli_name = "eth1";

+    int count = 0;

+    ret = rsgmii_init();

+    if(ret<0)

+    {

+        lynq_response_error(1);

+        return;

+    }

+

+    ser_socket =rsgmii_socket_init(&ser_addr, ser_name, ser_ip);

+    if(ser_socket < 0)

+    {

+        handle_output("init_failed", strlen("init_failed"), Response);

+        lynq_response_error(2);

+        return;

+    }

+

+    cli_socket =rsgmii_socket_init(&cli_addr, cli_name, cli_ip);

+    if(cli_socket < 0)

+    {

+        close(ser_socket);

+        handle_output("init_failed", strlen("init_failed"), Response);

+        lynq_response_error(3);

+        return;

+    }

+    //data content

+    for(int j =0;j<4;j++)

+    {

+        for(int i =0;i<255;i++)

+        {

+            count += sprintf(buf_init + count,"%c",i);

+            if (count >= 1024)

+            {

+                buf_init[1023] = '\0';

+                break;

+            }

+        }

+        

+        if (count >= 1024)

+        {

+            break;

+        }

+    }

+

+    start = time(NULL);

+    for(int i=0;i<128;i++)

+    {

+        check_count++;

+        end = time(NULL);

+        if(difftime(end,start)>10)

+        {

+            break;

+        }

+        ret = sendto(cli_socket,buf_init,sizeof(buf_init),0,(struct sockaddr*)&ser_addr,sizeof(ser_addr));

+        if(ret < 0 )

+        {

+            continue;

+        }

+

+        ret = receive_data(ser_socket,buf_init,buf_tran, sizeof(buf_init));

+        if(ret < 0)

+        {

+            continue;

+        }

+

+        //ser receive data and send back the same of data to cli

+        ret = sendto(ser_socket,buf_tran,sizeof(buf_init),0,(struct sockaddr*)&cli_addr,sizeof(cli_addr));

+        if(ret <0)

+        {

+            continue;

+        }

+

+        ret = receive_data(cli_socket,buf_init,buf_recv, sizeof(buf_init));

+        if(ret < 0)

+        {

+            continue;

+        }

+

+        check_ok_count ++;

+    }

+

+    if(check_ok_count >= 120)

+    {

+        lynq_response_ok();

+    }

+    else

+    {

+        sprintf(flag,"sent %d, success %d\n", check_count, check_ok_count);

+        handle_output(flag, strlen(flag), Response);

+        lynq_response_error(100);

+    }

+

+    close(ser_socket);

+    close(cli_socket);

+    return;

+}

+

 void lynq_handle_rgmii(char *input)

 {

     char *ipv4 = input+6;

@@ -242,8 +684,7 @@
         }

         handle_output(lynq_factory_buf, strlen(lynq_factory_buf), Response);

     }

-    char *str = "OK\n";

-    handle_output(str, strlen(str), Response);

+    lynq_response_ok();

     pclose(fp);

 }

 

@@ -269,8 +710,7 @@
         }

         handle_output(lynq_factory_buf, strlen(lynq_factory_buf), Response);

     }

-    char *str = "OK\n";

-    handle_output(str, strlen(str), Response);

+    lynq_response_ok();

     pclose(fp);

 }

 

@@ -285,8 +725,7 @@
     }

     fgets(buf, sizeof(buf), fp);

     handle_output(buf, strlen(buf), Response);

-    char *str = "OK\n";

-    handle_output(str, strlen(str), Response);

+    lynq_response_ok();

     pclose(fp);

 }

 

@@ -304,15 +743,13 @@
     {

         char *res = "[usb][result],3.0";

         handle_output(res, strlen(res), Response);

-        char *str = "OK\n";

-        handle_output(str, strlen(str), Response);

+        lynq_response_ok();

     }

     else if(!strncmp(lynq_usb_buf,usb2_speed,strlen(usb2_speed)))

     {

         char *res = "[usb][result],2.0";

         handle_output(res, strlen(res), Response);

-        char *str = "OK\n";

-        handle_output(str, strlen(str), Response);

+        lynq_response_ok();

     }

     pclose(fp);

     return 1;

@@ -321,15 +758,16 @@
 

 static Command commands[] = 

 {

-{"adc",lynq_handle_adc},

-{"sink",lynq_handle_sink},

-{"emmc",lynq_handle_emmc},

-{"gpio",lynq_handle_gpio},

-{"pcie",lynq_handle_pcie},

-{"rgmii",lynq_handle_rgmii},

-{"sgmii",lynq_handle_sgmii},

-{"usb",lynq_handle_usb},

-{NULL, NULL}

+    {"adc",lynq_handle_adc},

+    {"sink",lynq_handle_sink},

+    {"emmc",lynq_handle_emmc},

+    {"gpio",lynq_handle_gpio},

+    {"pcie",lynq_handle_pcie},

+    {"rsgmii",lynq_handle_rsgmii},

+    {"rgmii",lynq_handle_rgmii},

+    {"sgmii",lynq_handle_sgmii},

+    {"usb",lynq_handle_usb},

+    {NULL, NULL}

 };

 

 Command* find_command (char *input)

@@ -350,109 +788,6 @@
     return ((Command *)NULL);

 }

 

-/*

-int g_number(const char *p){

-    int cnt = 0;

-    while(*p != '\0'){

-        if(*p == ','){

-            cnt++;

-        }

-        *p++;

-    }

-    return cnt+4;//for count character string

-

-}

-

-void lynqSetArgv(char **argv, char** Point,const char* value)

-{

-    *argv=*Point;

-     sprintf(*argv, "%s", value);    

-     (*Point) += (strlen(value)+1);

-}

-

-int lynqParseUsbCommand(const char* cmd,char *argv[],char test[],char* parser_buf,int maxArgc)

-{

-    char *token;

-    char *str = test;

-    char *string;

-    char *parameter;

-    char* Point=parser_buf;

-    int cnt = g_number(cmd);

-    memcpy(test, cmd, strlen(cmd));

-    test[strlen(cmd)] = '\0';

-    argv[1] = (char *)cmd;

-    if(strstr(cmd,"=?"))

-    {

-        token = strtok(str, "=?");

-        //argv[0] = token;

-        argv[0] = strstr(token, "+")+1; 

-        lynqSetArgv(&(argv[2]),&Point,"1");

-        while (token != NULL)

-        {

-            string = token;

-            token = strtok(NULL, "=?");

-        }

-        parameter = strtok(string, ",");

-        int i = 3;

-        while (parameter != NULL)

-        {

-            argv[i++] = parameter;

-            parameter = strtok(NULL, ",");

-        }

-    }

-    else if(strstr(cmd,"="))

-    {

-        lynqSetArgv(&(argv[2]),&Point,"0");

-        token = strtok(str, "=");

-        //argv[0] = token;

-        if(strstr(token, "+"))

-        {

-            argv[0] = strstr(token, "+")+1;

-            while (token != NULL)

-            {

-                string = token;

-                token = strtok(NULL, "=");

-            }

-            parameter = strtok(string, ",");

-            int i = 3;

-            while (parameter != NULL)

-            {

-                argv[i++] = parameter;

-                parameter = strtok(NULL, ",");

-            }

-        }

-        else

-        {

-            argv[0] = token;

-        }

-    }

-    else if(strstr(cmd,"?"))

-    {

-        lynqSetArgv(&(argv[2]),&Point,"2");

-        token = strtok(str, "?");

-        //argv[0] = token;

-        argv[0] = strstr(token, "+")+1;

-        while (token != NULL)

-        {

-            string = token;

-            token = strtok(NULL, "?");

-        }

-        parameter = strtok(string, ",");

-        int i = 3;

-        while (parameter != NULL)

-        {

-            argv[i++] = parameter;

-            parameter = strtok(NULL, ",");

-        }

-    } 

-    if(cnt > maxArgc)

-        return -1;

-    return cnt;

-}

-*/

-

-

-

 void lynq_at_factory_cb(char *input, int input_max_size)

 {

     if(handle_output != NULL)

diff --git a/common_src/lib/liblynq-at-fota/LICENSE b/common_src/lib/liblynq-at-fota/LICENSE
new file mode 100755
index 0000000..382fc78
--- /dev/null
+++ b/common_src/lib/liblynq-at-fota/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:

+

+This software/firmware and related documentation ("Mobiletek Software") are

+protected under relevant copyright laws. The information contained herein is

+confidential and proprietary to Mobiletek Inc. and/or its licensors. Without

+the prior written permission of Mobiletek inc. and/or its licensors, any

+reproduction, modification, use or disclosure of Mobiletek Software, and

+information contained herein, in whole or in part, shall be strictly

+prohibited.

+

+Mobiletek Inc. (C) 2015. All rights reserved.

+

+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES

+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("Mobiletek SOFTWARE")

+RECEIVED FROM Mobiletek AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER

+ON AN "AS-IS" BASIS ONLY. Mobiletek EXPRESSLY DISCLAIMS ANY AND ALL

+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED

+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR

+NONINFRINGEMENT. NEITHER DOES Mobiletek PROVIDE ANY WARRANTY WHATSOEVER WITH

+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,

+INCORPORATED IN, OR SUPPLIED WITH THE Mobiletek SOFTWARE, AND RECEIVER AGREES

+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.

+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO

+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN Mobiletek

+SOFTWARE. Mobiletek SHALL ALSO NOT BE RESPONSIBLE FOR ANY Mobiletek SOFTWARE

+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR

+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND Mobiletek'S

+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE Mobiletek SOFTWARE

+RELEASED HEREUNDER WILL BE, AT Mobiletek'S OPTION, TO REVISE OR REPLACE THE

+Mobiletek SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE

+CHARGE PAID BY RECEIVER TO Mobiletek FOR SUCH Mobiletek SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/common_src/lib/liblynq-at-fota/include/libat/lynq_at_fota.h b/common_src/lib/liblynq-at-fota/include/libat/lynq_at_fota.h
new file mode 100755
index 0000000..dd32d26
--- /dev/null
+++ b/common_src/lib/liblynq-at-fota/include/libat/lynq_at_fota.h
@@ -0,0 +1,31 @@
+/*=============================================================================

+#     FileName: lynq_at_fota.h

+#     Desc: about at of fota

+#     Author: jb.qi

+#     Version: V1.0

+#     LastChange: 2023-01-09

+#     History:

+      copyright:Mobiletek

+=============================================================================*/

+#ifndef __LYNQ_FOTA_H__

+#define __LYNQ_FOTA_H__ 1

+#ifdef __cplusplus

+extern "C" {

+#endif

+

+#define LYNQ_E_FTP_LOGIN_FAIL 9002 /*Ftp login fail*/

+#define LYNQ_E_FTP_SEND_FAIL 9003 /*Ftp send log fail*/

+#define LYNQ_E_GET_LOG_FAIL 9004 /*Get log fail*/

+#define LYNQ_E_LOG_CMD_ERROR 9005 /*cmd error*/

+

+typedef void ( *lynq_atsvc_incb )( const char *input,const int length);

+typedef void ( *lynq_atsvc_outcb )(char *output, int out_max_size, int mode);

+lynq_atsvc_incb lynq_register_fota(lynq_atsvc_outcb out_cb);

+

+

+#ifdef __cplusplus

+}

+#endif

+

+#endif //__LYNQ_LOGSEND_TEST_H__

+

diff --git a/common_src/lib/liblynq-at-fota/lynq_at_fota.cpp b/common_src/lib/liblynq-at-fota/lynq_at_fota.cpp
new file mode 100755
index 0000000..148214c
--- /dev/null
+++ b/common_src/lib/liblynq-at-fota/lynq_at_fota.cpp
@@ -0,0 +1,300 @@
+#include <stdio.h>

+#include <string.h>

+#include <stdlib.h>

+#include "include/libat/lynq_at_fota.h"

+#ifdef __cplusplus

+extern "C" {

+#endif

+#include <log/log.h>

+#include "mtk_device_wrap.h"

+#include "include/iot_rock.h"

+

+#define UPDATA_ADDR "/tmp/fota.delta"

+#define READ_BLOCK_SIZE 0x40000

+#define FLASH_DEV_DELTA       "/dev/mtd41"

+#define LOG_TAG "AT-FOTA"

+

+lynq_atsvc_outcb g_handle_output;

+char str[128];

+char g_buffer[128] = {0};

+int Response = 0;

+int g_lynq_fota_md5_flag = -1;

+char g_put_addr[64];

+char g_put_path[35];

+char g_cmd[128];

+

+void *deal_download()

+{

+    int ret;

+    RLOGD("start deal_download !!!\n");

+    ret = system(g_cmd);

+    RLOGD("ret:%d \n", ret);

+    if(ret != 0)

+    {

+         strcpy(str, "+FOTA: fota download fail\n");

+         g_handle_output(str, strlen(str), Response);

+         return NULL;

+    }

+    else

+    {

+         strcpy(str, "+FOTA: fota download success\n");

+         g_handle_output(str, strlen(str), Response);

+    }

+    return NULL;

+}

+

+

+int lynq_download_package(char (*string)[35])

+{

+    int ret = 0;

+    int str_num = -1;

+    pthread_t tid;

+

+    RLOGD("function %s start\n", __FUNCTION__);

+    for(int i = 0; i < 9; i++)

+    {

+        if(string[i] == NULL)

+        {

+            strcpy(str, "+FOTA: download data null\n");

+            g_handle_output(str, strlen(str), Response);

+            return 1;

+        }

+    }

+

+    if(strlen(string[9]) == 0)

+    {

+        ret = chdir("/tmp/");

+        if( 0 != ret)

+        {

+             RLOGD("/tmp/ is error\n");

+             strcpy(str, "+FOTA: the tmp is error\n");

+             g_handle_output(str, strlen(str), Response);

+             return ret;

+        }

+        strcpy(g_put_path, "/tmp/");

+    }

+    else

+    {

+        ret = chdir(string[9]);

+        if( 0 != ret)

+        {

+             RLOGD("%s is error directory \n", string[9]);

+             strcpy(str, "+FOTA: NO such directory\n");

+             g_handle_output(str, strlen(str), Response);

+             return ret;

+        }

+        strcpy(g_put_path, string[9]);

+    }

+

+    sprintf(g_cmd,"wget ftp://%s:%s@%s:%s%s%s",string[2],string[3],string[0],string[1],string[7],string[8]);

+    RLOGD("g_cmd:%s\n", g_cmd);

+    str_num = strlen(g_put_path);

+

+    if(g_put_path[str_num - 1] == '/')

+    {

+        sprintf(g_put_addr,"%s%s", g_put_path, string[8]);

+    }

+    else

+    {

+        sprintf(g_put_addr,"%s/%s", g_put_path, string[8]);

+    }

+    RLOGD("g_put_addr: %s\n", g_put_addr);

+    if(lynq_fota_set_addr_value(g_put_addr,strlen(g_put_addr)))

+    {

+         strcpy(str, "+FOTA: set fota addr fail\n");

+         g_handle_output(str, strlen(str), Response);

+    }

+

+    pthread_create(&tid,NULL,deal_download,NULL);

+    pthread_detach(tid);

+

+    return ret;

+}

+

+/*

+ * @brief Differential subcontracting MD5 check

+ *

+ * @param string:MD5 value,Subcontracting address,Refer to the fota documentation

+ */

+

+int lynq_md5_package(char (*string)[35])

+{

+    char input_md5_data[64] = {0};

+    RLOGD("function %s start\n", __FUNCTION__);

+    for(int i = 0; i < 2; i++)

+    {

+        if(string[i] == NULL)

+        {

+            strcpy(str, "+FOTA: md5 value null\n");

+            g_handle_output(str, strlen(str), Response);

+            return 1;

+        }

+    }

+

+    sprintf(input_md5_data,"%s",string[0]);

+    RLOGD("input_md5_data: %s\n", string[0]);

+    g_lynq_fota_md5_flag = lynq_md5_file_verfy(g_put_addr, input_md5_data);

+    if(g_lynq_fota_md5_flag != 0)

+    {

+        strcpy(str, "+FOTA: md5 fail\n");

+        g_handle_output(str, strlen(str), Response);

+        return 1;

+    }

+    return 0;

+}

+

+/**

+ * @brief fota

+ * 

+ * @param void

+ */

+int lynq_fota_try(void)

+{

+    RLOGD("function %s start\n", __FUNCTION__);

+    if(g_lynq_fota_md5_flag == 0) //upgrade success ,device reboot ,lynq_fota_md5_flag no need to reset

+    {

+        if(0 != lynq_rock_main(1))

+        {

+            g_lynq_fota_md5_flag = -1;

+            strcpy(str, "+FOTA: update fail\n");

+            g_handle_output(str, strlen(str), Response);

+            return 1;

+        }

+    }

+    else

+    {

+        strcpy(str, "+FOTA: md5 verify fail\n");

+        g_handle_output(str, strlen(str), Response);

+        return 1;

+    }

+    

+    return 0;

+}

+

+void lynq_at_fota(char (*argv)[35])

+{

+    int result;

+    RLOGD("function %s start\n", __FUNCTION__);

+    RLOGD("buffer: %s",g_buffer);

+    if(!(strcmp(argv[0], "AT+FOTA?")))

+    {

+        if(strlen(g_buffer) == 0)

+        {

+            strcpy(str, "+FOTA: OK\n");

+        }

+        else

+        {

+            sprintf(str, "+FOTA: %s\n",g_buffer);

+            

+        }

+        g_handle_output(str, strlen(str), Response);

+        return ;

+    }

+    else if(!(strcmp(argv[0], "AT+FOTA=?")))

+    {

+        strcpy(str, "+FOTA:(0-2),""\n");

+        g_handle_output(str, strlen(str), Response);

+        return ;

+

+    }

+    if(!(strcmp(argv[0], "AT+FOTA=0")) || !(strcmp(argv[0], "AT+LYNQFOTA=download")))

+    {

+        RLOGD("argv[0]: %s\n", argv[0]);

+        if(!(strcmp(argv[1], "ftp")))

+        {

+            result = lynq_download_package(&argv[2]);

+            if(result != 0)

+            {

+                strcpy(str, "+FOTA: DOWNLOAD FAIL\n");

+            }

+            else

+            {

+                strcpy(str, "+FOTA: DOWNLOAD START\n");

+            }

+        }

+        else

+        {

+            strcpy(str, "+FOTA: NO FTP DOWNLOAD\n");

+        }

+    }

+

+    else if(!(strcmp(argv[0], "AT+FOTA=1")) || !(strcmp(argv[0], "AT+LYNQFOTA=md5")))

+    {

+        RLOGD("argv[0]: %s\n", argv[0]);

+        result = lynq_md5_package(&argv[1]);

+        if(result != 0)

+        {

+            strcpy(str, "+FOTA: MD5 FAIL\n");

+        }

+        else

+        {

+            strcpy(str, "+FOTA: MD5 SUCCESS\n");

+        }

+    }

+    else if(!(strcmp(argv[0], "AT+FOTA=2")) || !(strcmp(argv[0], "AT+LYNQFOTA=upgrade")))

+    {

+        RLOGD("argv[0]: %s\n", argv[0]);

+        result = lynq_fota_try();

+        if(result == 0)

+        {

+            strcpy(str, "+FOTA: UPDATE SUCCESS\n");

+        }

+        else

+        {

+            strcpy(str, "+FOTA: UPDATE FAIL\n");

+        }

+    }

+    else

+    {

+        strcpy(str, "+CME: ERROR: 100\n");

+

+    }

+    g_handle_output(str, strlen(str), Response);

+    

+}

+

+void lynq_at_fota_cb(char *input, int input_max_size)

+{

+    char arry[20][35]={};

+    char *p = NULL;

+    int i = 0;

+    

+    if(input[8] == '0')

+    {

+        strcpy(g_buffer, input);

+    }

+    if(g_handle_output != NULL)

+    {

+        RLOGD("function %s start,input: %s \n", __FUNCTION__, input);

+        if(input != NULL)

+        {

+            while(( p = strsep(&input,",")) != NULL)

+            {

+                strcpy(arry[i],p);

+                i++;

+            }  

+            lynq_at_fota(arry);

+        }

+    }

+    

+}

+

+

+lynq_atsvc_incb lynq_register_fota(lynq_atsvc_outcb out_cb)

+{

+    if(out_cb != NULL)

+    {

+        g_handle_output = out_cb;

+        RLOGD("function %s start\n", __FUNCTION__);

+        return lynq_at_fota_cb;

+    }

+}

+

+

+#ifdef __cplusplus

+}

+#endif

+

+

+

+

diff --git a/common_src/lib/liblynq-at-fota/makefile b/common_src/lib/liblynq-at-fota/makefile
new file mode 100755
index 0000000..5ca6274
--- /dev/null
+++ b/common_src/lib/liblynq-at-fota/makefile
@@ -0,0 +1,87 @@
+

+SHELL = /bin/sh

+RM = rm -f

+

+LOCAL_CFLAGS := -Wall \

+                -std=gnu++14 \

+                -g -Os \

+                -flto \

+                -DRIL_SHLIB \

+                -DATCI_PARSE \

+                -fPIC \

+                -DKEEP_ALIVE \

+                -DECALL_SUPPORT \

+                -fpermissive \

+

+$(warning ################# lynq at factory demo ROOT: $(ROOT),includedir:$(includedir))

+

+ifeq ($(strip $(MOBILETEK_FOTA_CFG)), PLATFORM)

+    LOCAL_CFLAGS += -DMOBILETEK_FOTA_CFG

+endif

+

+ifeq ($(strip $(MOBILETEK_FOTA_CFG)), ZK)

+    LOCAL_CFLAGS += -DZK_FOTA_CFG

+endif

+

+

+LOCAL_PATH   = .

+

+LOCAL_C_INCLUDES = \

+  -I. \

+  -I$(LOCAL_PATH)/include/libat \

+  -I$(ROOT)$(includedir)/logger \

+  -I$(ROOT)$(includedir)/liblog \

+  -I$(ROOT)$(includedir)/vendor-ril \

+  -I$(ROOT)$(includedir)/ftp \

+  

+

+

+LOCAL_LIBS := \

+    -L. \

+    -ldl \

+    -lstdc++ \

+    -llog \

+    -lcutils \

+    -lutils \

+    -lbinder \

+    -lpthread \

+    -llynq-log \

+    -llynq-fota \

+    -llynq-protcl \

+

+

+SOURCES = $(wildcard *.cpp)

+

+EXECUTABLE = liblynq-at-fota.so

+

+OBJECTS=$(SOURCES:.cpp=.o)

+

+.PHONY: build clean install pack_rootfs

+

+all: build

+$(EXECUTABLE): $(OBJECTS)

+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@

+

+%.o : %.cpp

+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<

+

+build:  $(EXECUTABLE)

+	$(warning ########## build $(EXECUTABLE)  ##########)

+

+install:

+	mkdir -p $(ROOT)$(base_libdir)/

+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/

+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk

+

+pack_rootfs:

+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/

+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/

+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)

+	mkdir -p $(PACK_TO)$(base_libdir)/

+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/

+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)

+	

+.PHONY: clean

+clean:

+	$(RM) $(OBJECTS) $(EXECUTABLE)

+	-find . -name "*.o" -delete

diff --git a/common_src/lib/liblynq-call/lynq_call.cpp b/common_src/lib/liblynq-call/lynq_call.cpp
index ebdfa2a..8e80462 100755
--- a/common_src/lib/liblynq-call/lynq_call.cpp
+++ b/common_src/lib/liblynq-call/lynq_call.cpp
@@ -391,9 +391,10 @@
     pthread_cond_signal(&call_state_change_cond);

     pthread_mutex_unlock(&call_state_change_mutex);

 }

-void send_call_state_change()

+void send_call_state_change(int callid)

 {

     LYINFLOG("send call state change");

+    s_CallId = callid;

     pthread_mutex_lock(&s_call_state_change_mutex);

     pthread_cond_signal(&s_call_state_change_cond);

     pthread_mutex_unlock(&s_call_state_change_mutex);

@@ -423,16 +424,17 @@
 #endif

     pthread_mutex_lock(&s_notice_get_call_list_mutex);

     pthread_cleanup_push(cleanup_call_list_mutex, NULL); // thread cleanup handler

+    int tmp_call_id;

     while(s_call_list_loop)

     {

         update=0;       

         pthread_cond_wait(&s_notice_get_call_list_cond, &s_notice_get_call_list_mutex);

-        LYDBGLOG("triggerGetCallList event!!!");

+        LYINFLOG("triggerGetCallList event %p!!!", pthread_self());

         memset(call_list,0,sizeof(call_list));

         ret = lynq_get_current_call_list(call_list);

         if(ret != RESULT_OK)

         {

-            LYDBGLOG("get current call list failure!!!");          

+            LYERRLOG("get current call list failure!!!");

             continue;

         }

         LYINFLOG("++++++++++++++triggerGetCallList++++++++++++++");

@@ -463,8 +465,10 @@
                 {

                     LYINFLOG("MT/MO hungup,then clean call info local idx is %d id is %d",i, s_call_lists[i].call_id);

                     //update_end_state(i);//lei modify for:update end state for this call

+                    tmp_call_id = s_call_lists[i].call_id;

                     cleanCallList(i);

-                    send_call_state_change();//means mt/mo call is end

+                    //Release the end handle

+                    send_call_state_change(tmp_call_id);//means mt/mo call is end

                     //cleanCallList(i);

                 }

             } //fix bug API-54

@@ -511,8 +515,7 @@
                 {

                     n = addAddr(call_list[i].addr,call_list[i].call_id);

                     updateCallList(&s_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

-                    s_CallId = call_list[i].call_id;

-                    send_call_state_change();

+                    send_call_state_change(call_list[i].call_id);

                 }

                 else if(s_call_lists[n].call_state == call_list[i].call_state)

                 {

@@ -524,7 +527,7 @@
                         **fix bug API-54

                         */

                         LYINFLOG("resend incoming call signal");

-                        send_call_state_change();

+                        send_call_state_change(call_list[i].call_id);

                     }

                 }

                 else 

@@ -532,7 +535,7 @@
                     LYINFLOG("state changed from %d to %d",s_call_lists[n].call_state,call_list[i].call_state);

                     

                     updateCallList(&s_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);//update mt call

-                    send_call_state_change();

+                    send_call_state_change(call_list[i].call_id);

                 }                            

             }

             else

@@ -547,12 +550,11 @@
                         {

                             LYINFLOG("add a call id");

                             update=1;//for send sigal

-                            s_CallId = call_list[i].call_id;

                         }

                         LYINFLOG("local idx %d updated, original call id is %d origial addr is %s original state is %d",n,s_call_lists[n].call_id,s_call_lists[n].addr,s_call_lists[n].call_state);                    

                         updateCallList(&s_call_lists[n],call_list[i].call_id,call_list[i].call_state,call_list[i].toa,call_list[i].direction);

                         call_end = 1;

-                        send_call_state_change();//means mo call is success

+                        send_call_state_change(call_list[i].call_id);//means mo call is success

                         break;

                     }                    

                 }

@@ -600,10 +602,11 @@
 

 void lynqNoticeGetModuleCallList()

 {

+    LYINFLOG("RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED send start");

     pthread_mutex_lock(&s_notice_get_call_list_mutex);

     pthread_cond_signal(&s_notice_get_call_list_cond);

     pthread_mutex_unlock(&s_notice_get_call_list_mutex);

-    

+    LYINFLOG("RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED send end");

 }

 

 #if 0

@@ -897,14 +900,17 @@
     LYINFLOG("wait Call state Change");

     int ret = 0;

     int sec = 0;

-    int usec = 0;

+    int ms  = 0;

     struct timeval now;

     struct timespec timeout;

     gettimeofday(&now,NULL);

     sec = mtime/1000;

-    usec = mtime%1000;

+    ms  = mtime%1000;

     timeout.tv_sec = now.tv_sec+sec;

-    timeout.tv_nsec = now.tv_usec*1000+usec*1000000;

+    unsigned long long ns;

+    ns = now.tv_usec*1000ull + ms*1000000ull;

+    timeout.tv_sec += ns/1000000000;

+    timeout.tv_nsec = ns % 1000000000;

     pthread_mutex_lock(&call_state_change_mutex);

     ret = pthread_cond_timedwait(&call_state_change_cond,&call_state_change_mutex,&timeout);

     pthread_mutex_unlock(&call_state_change_mutex);

@@ -1010,7 +1016,7 @@
         s_module_isDial = 0;      

         LYERRLOG("lynq_call timeout:wait Call state fail!!! clear local idx %d",lynq_call_id);

         cleanCallList(lynq_call_id);

-        send_call_state_change();

+        send_call_state_change(lynq_call_id);

         return LYNQ_E_TIME_OUT;

     }

     s_module_isDial = 0;

@@ -1024,7 +1030,7 @@
     {   

         LYERRLOG("lynq_call dial addr %s fail, invalid id",addr);

         cleanCallList(lynq_call_id);

-        send_call_state_change();

+        send_call_state_change(lynq_call_id);

         return LYNQ_E_INVALID_ID_ANONALY;

     }        

 }

@@ -1065,16 +1071,17 @@
     if(ret!=0)

     {

         return ret; 

-    }     

+    }

     delete p; 

 

-    int  lynq_call_id=find_call_id_with_call_id(call_id);

+    int lynq_call_id=find_call_id_with_call_id(call_id);

     if(lynq_call_id!=INVALID_ID)

     {

+        //lei  modify for API-857

         cleanCallList(lynq_call_id);

-    }        

-    

-    return RESULT_OK;     

+        send_call_state_change(call_id);

+    }

+    return RESULT_OK;

 }

 int lynq_call_hungup_all()

 {

@@ -1144,6 +1151,11 @@
         LYERRLOG("handle is NULL");

         return LYNQ_E_PARAMETER_ANONALY;

     }

+    if((*handle) <= 0)

+    {

+        LYINFLOG("lynq_get_current_call_state input error %d\n ", *handle);

+        return LYNQ_E_INVALID_ID_ANONALY;

+    }

     LYINFLOG("lynq_get_current_call_state %d\n ", *handle);

     lynq_call_id = find_call_id_with_call_id(*handle);

     if(lynq_call_id==INVALID_ID)

diff --git a/common_src/lib/liblynq-media/include/liblynq-media/lynq_medial.h b/common_src/lib/liblynq-media/include/liblynq-media/lynq_medial.h
index 1777bd6..28f18af 100755
--- a/common_src/lib/liblynq-media/include/liblynq-media/lynq_medial.h
+++ b/common_src/lib/liblynq-media/include/liblynq-media/lynq_medial.h
@@ -28,7 +28,16 @@
 int lynq_set_spk_volume(const int volume);
 int lynq_get_mic_volume(int* volume);
 int lynq_set_mic_volume(const int volume);
+int lynq_get_pa_volume(int* volume);
+int lynq_set_pa_volume(const int volume);
 
+/*dongyu@2023.6.27 Add Tone sound play, stop and status acquisition interface start*/
+int lynq_set_audtone(double high_freq, double low_freq, double duration, \
+                int stop_interval, int num_repetitions);
+int lynq_get_audtone(double* high_freq, double* low_freq, double* duration, \
+                int* stop_interval, int* num_repetitions);
+void lynq_stop_audtone();
+/*dongyu@2023.6.27 Add Tone sound play, stop and status acquisition interface end*/
 int lynq_media_play_audio(const char *path);
 void lynq_media_stop_audio();
 #endif  //__LYNQ_MEDIA_H__
diff --git a/common_src/lib/liblynq-media/liblynq-media/media_control.c b/common_src/lib/liblynq-media/liblynq-media/media_control.c
index 69c0d22..20e9a8a 100755
--- a/common_src/lib/liblynq-media/liblynq-media/media_control.c
+++ b/common_src/lib/liblynq-media/liblynq-media/media_control.c
@@ -6,6 +6,26 @@
 #include <pthread.h>

 #include <cutils/properties.h>

 //#include "modem_afe_ctrl.h"

+#include <fcntl.h>

+#include <linux/i2c-dev.h>

+#include <sys/ioctl.h>

+#include <unistd.h>

+#include <stdint.h>

+#include <math.h>

+#include <unistd.h>

+#include <pthread.h>

+#define AUDIO_PATH get_customer_tone_path()

+#define SAMPLE_RATE get_customer_tone_sample_rate()

+typedef struct {

+    size_t size;

+    unsigned short* data;

+    double high_freq;

+    double low_freq;

+    double duration;

+    int stop_interval;

+    int num_repetitions;

+} wav_t;

+wav_t g_current_tone = {0};

 #include <log/log.h>

 #include "liblynq-codec/lynq_codec.h"

 #define LOG_TAG "MEDIA_API"

@@ -29,7 +49,7 @@
 static const int MIC_VOLUME_LEVEL_7 = 63;

 

 typedef void *MEDIA_HANDLE;

-static MEDIA_HANDLE g_media_handle=NULL;

+volatile static MEDIA_HANDLE g_media_handle=NULL;

 

 typedef struct {

   MEDIA_HANDLE handle;

@@ -257,6 +277,202 @@
     return 0;

 }

 

+/*dongyu@2023.6.27 Add Tone sound play, stop and status acquisition interface start*/

+static int is_current_media_playing()

+{

+    if (g_media_handle == NULL)

+    {

+        RLOGD("is_current_media_playing g_media_handle is NULL\n");

+        return 0;

+    }

+

+    MEDIA_PARAM_T *param = (MEDIA_PARAM_T *)g_media_handle;

+

+    if (g_media_handle != param->handle)

+    {

+        RLOGD("invalid handle: %p \n", g_media_handle);

+    }

+

+    if (param->gst_cur_state == GST_STATE_PLAYING)

+    {

+        RLOGE("Error: already in playback state\n");

+        return 1;

+    }

+

+    return 0;

+}

+

+static int lynq_generate_wav(double high_freq, double low_freq, double duration, wav_t* wav)

+{

+    int num_repeats = 10;

+    int num_samples = (int)(SAMPLE_RATE * duration);

+    wav->size = num_samples * sizeof(int16_t);

+    wav->data = (int16_t*)malloc(wav->size);

+    if(wav->data == NULL)

+    {

+        RLOGE("Memory allocation failed\n");

+        return -1;

+    }

+    for (int i = 0; i < num_samples; i++)

+    {

+        double t = (double)i / SAMPLE_RATE;

+        double signal1 = 0.0;

+        double signal2 = 0.0;

+        for (int j = 0; j < num_repeats; j++)

+	{

+            double f = (j % 2 == 0) ? high_freq : low_freq;

+            signal1 += sin(2.0 * M_PI * f * t);

+            f = (j % 2 == 0) ? low_freq : high_freq;

+            signal2 += sin(2.0 * M_PI * f * t);

+        }

+        double signal = (signal1 + signal2) / 2;

+        wav->data[i] = (int16_t)(32767.0 * signal / num_repeats);

+        if (i % (int)(SAMPLE_RATE * 50) == 0)

+	{

+            num_repeats = (num_repeats == 1) ? 2 : 1;

+        }

+    }

+    return 0;

+}

+

+int lynq_set_audtone(double high_freq, double low_freq, double duration, \

+                int stop_interval, int num_repetitions)

+{

+    if(high_freq<100 || high_freq>4000 || low_freq<100 || low_freq>4000 || \

+            duration<0 || duration>60000 || \

+            stop_interval<0 || stop_interval>60000 || \

+            num_repetitions<1 || num_repetitions>300)

+    {

+        RLOGE("Frequency range is 100Hz~4KHz, duration range is 0~60000ms, "

+            "stop_interval range is 0~60000ms, num_repetitions range is 1~300\n");

+        return -1;

+    }

+    RLOGE("SET: high_freq=%.2f, low_freq=%.2f, duration=%.2f, "

+            "stop_interval=%d, num_repetitions=%d\n", high_freq, \

+            low_freq, duration, stop_interval, num_repetitions);

+

+    //Checks if the aplay exists before entering the thread

+    if(is_current_media_playing() != 0)

+    {

+        RLOGE("There is currently media playing\n");

+        return 1;

+    }

+

+    wav_t wav = {0};

+    if(lynq_generate_wav(high_freq, low_freq, duration / 1000.0, &wav) != 0)

+    {

+        RLOGE("Failed to generate wav\n");

+        free(wav.data);

+        return -1;

+    }

+

+    wav_t stop_wav = {0};

+    if(lynq_generate_wav(0, 0, stop_interval / 1000.0, &stop_wav) != 0)

+    {

+        RLOGE("Failed to generate top wav\n");

+        free(wav.data);

+        free(stop_wav.data);

+        return -1;

+    }

+

+    FILE* file = fopen(AUDIO_PATH, "wb");

+    if(file == NULL)

+    {

+        RLOGE("Failed to open file\n");

+        free(wav.data);

+        free(stop_wav.data);

+        return -1;

+    }

+    fwrite("RIFF", 1, 4, file);

+    int chunk_size = 36 + num_repetitions * (wav.size + stop_wav.size);

+    fwrite(&chunk_size, 4, 1, file);

+    fwrite("WAVE", 1, 4, file);

+    fwrite("fmt ", 1, 4, file);

+    int subchunk1_size = 16;

+    fwrite(&subchunk1_size, 4, 1, file);

+    unsigned short audio_format = 1;

+    fwrite(&audio_format, 2, 1, file);

+    unsigned short num_channels = 1;

+    fwrite(&num_channels, 2, 1, file);

+    int sample_rate = SAMPLE_RATE;

+    fwrite(&sample_rate, 4, 1, file);

+    int byte_rate = SAMPLE_RATE * 2;

+    fwrite(&byte_rate, 4, 1, file);

+    unsigned short block_align = 2;

+    fwrite(&block_align, 2, 1, file);

+    unsigned short bits_per_sample = 16;

+    fwrite(&bits_per_sample, 2, 1, file);

+     fwrite("data", 1, 4, file);

+    int subchunk2_size = num_repetitions * (wav.size + stop_wav.size);

+    fwrite(&subchunk2_size, 4, 1, file);

+

+    for (int i = 0; i < num_repetitions; i++)

+    {

+        fwrite(wav.data, 1, wav.size, file);

+        fwrite(stop_wav.data, 1, stop_wav.size, file);

+    }

+

+    fclose(file);

+    free(wav.data);

+    free(stop_wav.data);

+

+    g_current_tone.high_freq = high_freq;

+    g_current_tone.low_freq = low_freq;

+    g_current_tone.duration = duration;

+    g_current_tone.stop_interval = stop_interval;

+    g_current_tone.num_repetitions = num_repetitions;

+    g_current_tone.size = wav.size;

+    g_current_tone.data = wav.data;

+

+    if(lynq_media_play_audio(AUDIO_PATH) != 0)

+    {

+        RLOGE("Failed to play WAV fileln");

+        return -1;

+    }

+

+    printf("lynq_set_audtone is playing audio !\n");

+

+    return 0;

+}

+

+int lynq_get_audtone(double* high_freq, double* low_freq, double* duration, \

+               int* stop_interval, int* num_repetitions)

+{

+    if(high_freq == NULL || low_freq == NULL || duration == NULL || \

+		    stop_interval == NULL || num_repetitions == NULL){

+        RLOGE("lynq_get_audtone Pointers are NULL, returning -1\n");

+        return -1;

+    }

+

+    *high_freq = g_current_tone.high_freq;

+    *low_freq = g_current_tone.low_freq;

+    *duration = g_current_tone.duration;

+    *stop_interval = g_current_tone.stop_interval;

+    *num_repetitions = g_current_tone.num_repetitions;

+

+    return 0;

+}

+

+void lynq_stop_audtone()

+{

+    lynq_media_stop_audio();

+    RLOGD("lynq_stop_audtone stop audio playback\n");

+}

+

+/*dongyu@2023.6.27 Add Tone sound play, stop and status acquisition interface end*/

+/*dongyu@2023.6.13 Add ZK set the PA's volume gain level start*/

+int lynq_set_pa_volume(const int volume)

+{

+    return customer_set_pa_volume(volume);

+}

+

+

+int lynq_get_pa_volume(int* volume)

+{

+    return customer_get_pa_volume(volume);

+}

+

+/*dongyu@2023.6.13 Add ZK set the PA's volume gain level end*/

 static int media_stop_full(MEDIA_PARAM_T *param)

 {

   GMainLoop *loop = param->loop;

@@ -274,9 +490,10 @@
   g_main_loop_unref (loop);

   

   free(param);

+  set_codec(LYNQ_MEDIA, CODEC_CLOSE); //hqing add for Geely demand on 11/07/2022, stop audio, close codec

   param = NULL;

   g_media_handle=NULL;

-  set_codec(LYNQ_MEDIA, CODEC_CLOSE); //hqing add for Geely demand on 11/07/2022, stop audio, close codec

+  RLOGI("media_stop_full Thread exit\n");

   return 0;

 

 }

@@ -377,7 +594,7 @@
             return 1;

          }

          cnt++;

-         sleep(1);

+         usleep(100000);

       }

   } while (1);  

   RLOGD ("lynq_media_play_audio end, handle is %p\n",handle);

@@ -399,6 +616,18 @@
     g_main_loop_quit (param->loop);

     pthread_join(param->thread, NULL);

     RLOGD ("lynq_media_stop_audio end\n");

+

+    for (int i = 0; i < 50; i++)

+    {

+        if (g_media_handle == NULL)

+	{

+            RLOGD("Exit media_stop_full\n");

+	    return;

+        }

+        usleep(100000);

+        RLOGD("lynq_media_stop_audio loop %d times\n", i);

+    }

+

     return;

 }

 

diff --git a/common_src/lib/liblynq-qser-adc/LICENSE b/common_src/lib/liblynq-qser-adc/LICENSE
new file mode 100755
index 0000000..605b7ea
--- /dev/null
+++ b/common_src/lib/liblynq-qser-adc/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MobileTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MobileTek Inc. and/or its licensors. Without
+the prior written permission of MobileTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MobileTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MobileTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MobileTek SOFTWARE")
+RECEIVED FROM MobileTek AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MobileTek EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MobileTek PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MobileTek SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MobileTek
+SOFTWARE. MobileTek SHALL ALSO NOT BE RESPONSIBLE FOR ANY MobileTek SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MobileTek'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MobileTek SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MobileTek'S OPTION, TO REVISE OR REPLACE THE
+MobileTek SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MobileTek FOR SUCH MobileTek SOFTWARE AT ISSUE.
diff --git a/common_src/lib/liblynq-qser-adc/include/liblynq-qser-adc.h b/common_src/lib/liblynq-qser-adc/include/liblynq-qser-adc.h
new file mode 100755
index 0000000..55fb090
--- /dev/null
+++ b/common_src/lib/liblynq-qser-adc/include/liblynq-qser-adc.h
@@ -0,0 +1,29 @@
+/*============================================================================= 

+#     FileName: lynq_qser_adc_show.h

+#     Desc: about adc show for user

+#     Author: cz.li

+#     Version: V1.0

+#     LastChange: 2023-05-31 

+#     History:

+      copyright:Mobiletek

+=============================================================================*/

+#ifndef LYNQLIB_QSER_ADC_SHOW_H

+#define LYNQLIB_QSER_ADC_SHOW__H 1

+#ifdef __cplusplus

+extern "C" {

+#endif

+typedef enum ADC_CHANNEL_ENUM

+{

+    QADC_NONE = 0,

+    ADC0 =1,

+    ADC1 =2,

+    ADC2 =3,

+    QADC_END

+}ADC_CHANNEL_E;

+

+int qser_adc_show(ADC_CHANNEL_E qadc);

+

+#ifdef __cplusplus

+}

+#endif

+#endif

diff --git a/common_src/lib/liblynq-qser-adc/liblynq_qser_adc.cpp b/common_src/lib/liblynq-qser-adc/liblynq_qser_adc.cpp
new file mode 100755
index 0000000..98f037f
--- /dev/null
+++ b/common_src/lib/liblynq-qser-adc/liblynq_qser_adc.cpp
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <liblog/lynq_deflog.h>
+#include "include/liblynq-qser-adc.h"
+#define USER_LOG_TAG "LIBLYNQ_QSER_ADC"
+#undef LOG_TAG
+#define LOG_TAG "LIBLYNQ_QSER_ADC"
+int qser_adc_show(ADC_CHANNEL_E qadc)
+{
+    int adc_value;
+    char cmd[1024];
+    char cmd_ret[1024];
+    FILE *fp;
+    switch(qadc)
+    {
+    case QADC_NONE:
+    {
+        LYERRLOG("function %s line %d\n", __FUNCTION__, __LINE__);
+        return 0;
+    }
+    case ADC0:
+    {
+        LYDBGLOG("function %s line %d\n", __FUNCTION__, __LINE__);
+        sprintf(cmd,"cat /sys/bus/iio/devices/iio:device1/in_voltage0_input");
+        break;
+    }
+    case ADC1:
+    {
+        LYDBGLOG("function %s line %d\n", __FUNCTION__, __LINE__);
+        sprintf(cmd,"cat /sys/bus/iio/devices/iio:device1/in_voltage1_input");
+        break;
+    }
+    case ADC2:
+    {
+        LYDBGLOG("function %s line %d\n", __FUNCTION__, __LINE__);
+        sprintf(cmd,"cat /sys/bus/iio/devices/iio:device1/in_voltage2_input");
+        break;
+    }
+    default:
+    {
+        LYERRLOG("input error\n");
+        return -1;
+    }
+    }
+    if((fp = popen(cmd,"r")) == NULL)
+    {
+        LYERRLOG("popen error!");
+        return -1;
+    }
+    if((fread(cmd_ret,sizeof(cmd_ret),1,fp))<0)
+    {
+        LYERRLOG("fread fail!");
+        fclose(fp);
+        return -1;
+    }
+    fclose(fp);
+
+    adc_value = atoi(cmd_ret);
+    if (adc_value < 0 || adc_value > 12000)
+    {
+        LYERRLOG("bad adc value %s!", cmd_ret);
+        return -1;
+    }
+
+    return adc_value;
+}
diff --git a/common_src/lib/liblynq-qser-adc/makefile b/common_src/lib/liblynq-qser-adc/makefile
new file mode 100755
index 0000000..0ef16a1
--- /dev/null
+++ b/common_src/lib/liblynq-qser-adc/makefile
@@ -0,0 +1,70 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -DRIL_SHLIB \
+                -DATCI_PARSE \
+                -fPIC \
+                -DKEEP_ALIVE \
+                -DECALL_SUPPORT \
+                -fpermissive \
+
+
+
+$(warning ################# lynq data demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/libcall \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/vendor-ril \
+  -I$(ROOT)$(includedir)/lynq_shm \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -ldl \
+    -lstdc++ \
+    -llog \
+    -lcutils \
+    -lutils \
+    -lbinder \
+    -lpthread \
+    -llynq-log \
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-adc.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete
diff --git a/common_src/lib/liblynq-qser-data/LICENSE b/common_src/lib/liblynq-qser-data/LICENSE
new file mode 100755
index 0000000..8aaabff
--- /dev/null
+++ b/common_src/lib/liblynq-qser-data/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("Mobiletek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to Mobiletek Inc. and/or its licensors. Without
+the prior written permission of Mobiletek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of Mobiletek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+Mobiletek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-data/include/lynq-qser-data.h b/common_src/lib/liblynq-qser-data/include/lynq-qser-data.h
new file mode 100755
index 0000000..3485b72
--- /dev/null
+++ b/common_src/lib/liblynq-qser-data/include/lynq-qser-data.h
@@ -0,0 +1,268 @@
+#ifndef __LYNQ_QSER_DATA_H__
+#define __LYNQ_QSER_DATA_H__
+
+#include <stdbool.h>
+#include <netinet/in.h>
+
+typedef enum {
+	QSER_DATA_CALL_ERROR_NONE = 0,
+	QSER_DATA_CALL_ERROR_INVALID_PARAMS,
+} qser_data_call_error_e;
+
+typedef enum {
+	QSER_DATA_CALL_DISCONNECTED = 0,            /*!< call is disconnected */
+	QSER_DATA_CALL_CONNECTED,                   /*!< call is connected */
+} qser_data_call_state_e;
+
+typedef enum {
+	QSER_DATA_CALL_TYPE_IPV4 = 0,           /*!< IPv4 call. */
+	QSER_DATA_CALL_TYPE_IPV6,               /*!< IPv6 call. */
+	QSER_DATA_CALL_TYPE_IPV4V6,             /*!< IPv4 and IPv6 call (Only used call start or stop). */
+} qser_data_call_ip_family_e;
+
+typedef enum {
+	QSER_APN_PDP_TYPE_IPV4 = 0,
+	QSER_APN_PDP_TYPE_PPP,
+	QSER_APN_PDP_TYPE_IPV6,
+	QSER_APN_PDP_TYPE_IPV4V6,
+} qser_apn_pdp_type_e;
+
+typedef enum {
+	QSER_APN_AUTH_PROTO_DEFAULT = 0,
+	QSER_APN_AUTH_PROTO_NONE,
+	QSER_APN_AUTH_PROTO_PAP,
+	QSER_APN_AUTH_PROTO_CHAP,
+	QSER_APN_AUTH_PROTO_PAP_CHAP,
+} qser_apn_auth_proto_e;
+
+#define QSER_APN_MAX_LIST 8
+#define QSER_APN_NAME_SIZE 150
+#define QSER_APN_USERNAME_SIZE 127
+#define QSER_APN_PASSWORD_SIZE 127
+
+struct v4_address_status {
+	struct in_addr ip;                    /*!< Public IPv4 address. */
+	struct in_addr gateway;               /*!< Public IPv4 gateway. */
+	struct in_addr pri_dns;               /*!< Primary Domain Name Service IP address. */
+	struct in_addr sec_dns;               /*!< Secondary Domain Name Service IP address. */
+};
+
+struct v6_address_status {
+	struct in6_addr ip;                   /*!< Public IPv6 address. */
+	struct in6_addr gateway;              /*!< Public IPv6 gateway. */
+	struct in6_addr pri_dns;              /*!< Primary Domain Name Service IPv6 address. */
+	struct in6_addr sec_dns;              /*!< Secondary Domain Name Service IPv6 address. */
+};
+
+typedef struct {
+	char profile_idx;                               /*!< UMTS/CMDA profile ID. */
+	char name[16];                                  /*!< Interface Name. */
+	qser_data_call_ip_family_e ip_family;             /*!< IP version. */
+	qser_data_call_state_e state;                     /*!< The dial status. */
+	qser_data_call_error_e err;                       /*!< The Reason code after data call disconnected. */
+	union {
+		struct v4_address_status v4;            /*!< IPv4 information. */
+		struct v6_address_status v6;            /*!< IPv6 information. */
+	};
+} qser_data_call_state_s;
+
+/*
+ *!< Client callback function used to post event indications.
+ */
+typedef void (*qser_data_call_evt_cb_t)(qser_data_call_state_s *state);
+
+typedef struct {
+	char profile_idx;                        /*!< UMTS/CMDA profile ID. */
+	bool reconnect;                          /*!< Whether to re-dial after disconnecting the network. */
+	qser_data_call_ip_family_e ip_family;      /*!< IP version. */
+	char cdma_username[QSER_APN_USERNAME_SIZE];     /*!< Username used during data network authentication. */
+	char cdma_password[QSER_APN_PASSWORD_SIZE];     /*!< Password to be used during data network authentication. */
+} qser_data_call_s;
+
+struct pkt_stats {
+	unsigned long pkts_tx;              /*!< Number of packets transmitted. */
+	unsigned long pkts_rx;              /*!< Number of packets received. */
+	long long bytes_tx;                 /*!< Number of bytes transmitted. */
+	long long bytes_rx;                 /*!< Number of bytes received. */
+	unsigned long pkts_dropped_tx;      /*!< Number of transmit packets dropped. */
+	unsigned long pkts_dropped_rx;      /*!< Number of receive packets dropped. */
+};
+
+struct v4_info {
+	char name[16];                          /*!< Interface Name. */
+	qser_data_call_state_e state;             /*!< The dial status. */
+	bool reconnect;                         /*!< re-dial flag. */
+	struct v4_address_status addr;          /*!< IPv4 IP Address information. */
+	struct pkt_stats stats;                 /*!< IPv4 statics */
+};
+
+struct v6_info {
+	char name[16];                          /*!< Interface Name. */
+	qser_data_call_state_e state;             /*!< The dial status. */
+	bool reconnect;                         /*!< re-dial flag. */
+	struct v6_address_status addr;          /*!< IPv6 IP Address information. */
+	struct pkt_stats stats;                 /*!< IPv6 statics */
+};
+
+typedef struct {
+	char profile_idx;                        /*!< UMTS/CDMA profile ID. */
+	qser_data_call_ip_family_e ip_family;      /*!< IP version. */
+	struct v4_info v4;                       /*!< IPv4 information */
+	struct v6_info v6;                       /*!< IPv6 information */
+} qser_data_call_info_s;
+
+typedef struct {
+	unsigned char profile_idx;              /*!< UMTS/CDMA profile ID. */
+	qser_apn_pdp_type_e pdp_type;             /*!< Packet Data Protocol (PDP) type specifies the type of data payload
+	                                             exchanged over the airlink when the packet data session is
+	                                             established with this profile. */ 
+	qser_apn_auth_proto_e auth_proto;         /*!< Authentication Protocol. */
+	char apn_name[QSER_APN_NAME_SIZE];        /*!< A string parameter that is a logical name used to select the GGSN
+	                                             and external packet data network. */ 
+	char username[QSER_APN_USERNAME_SIZE];    /*!< Username used during data network authentication. */
+	char password[QSER_APN_PASSWORD_SIZE];    /*!< Password to be used during data network authentication. */
+    char apn_type[QSER_APN_NAME_SIZE];
+} qser_apn_info_s;
+
+typedef struct {
+	qser_apn_pdp_type_e pdp_type;             /*!< Packet Data Protocol (PDP) type specifies the type of data payload
+						  exchanged over the airlink when the packet data session is
+						  established with this profile. */ 
+	qser_apn_auth_proto_e auth_proto;         /*!< Authentication Protocol. */
+	char apn_name[QSER_APN_NAME_SIZE];        /*!< A string parameter that is a logical name used to select the GGSN
+						  and external packet data network. */ 
+	char username[QSER_APN_USERNAME_SIZE];    /*!< Username used during data network authentication. */
+	char password[QSER_APN_PASSWORD_SIZE];    /*!< Password to be used during data network authentication. */
+    char apn_type[QSER_APN_NAME_SIZE];
+} qser_apn_add_s;
+
+typedef struct {
+	int cnt;
+	qser_apn_info_s apn[QSER_APN_MAX_LIST];
+} qser_apn_info_list_s;
+
+
+/**
+ * Initialization data call module, and callback function registered.
+ *
+ * @param [in] evt_cb           callback fucntion
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_data_call_init(qser_data_call_evt_cb_t evt_cb);
+
+/**
+ * Destroy data call module, and unregister callback funciton
+ *
+ * @param 
+ *   None
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern void qser_data_call_destroy(void);
+
+/**
+ * Starts a data call. If profile index is zero, it will call CDMA profile.
+ *
+ * @param [in] data_call        The data call parameters
+ * @param [out] error           Error code returned by data call 
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_data_call_start(qser_data_call_s *data_call, qser_data_call_error_e *err);
+
+/**
+ * Stop a data call.
+ *
+ * @param [in] profile_idx      UMTS/CDMA profile ID
+ * @param [in] ip_family        IP Version
+ * @param [out] error           Error code returned by data call 
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_data_call_stop(char profile_idx, qser_data_call_ip_family_e ip_family, qser_data_call_error_e *err);
+
+/**
+ * Get a data call information.
+ *
+ * @param [in] profile_idx      UMTS/CDMA profile ID
+ * @param [in] ip_family        IP Version
+ * @param [out] info            The Data Call information
+ * @param [out] error           Error code returned by data call 
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_data_call_info_get(char profile_idx,
+				 qser_data_call_ip_family_e ip_family,
+				 qser_data_call_info_s *info,
+				 qser_data_call_error_e *err);
+
+/**
+ * Changes the settings in a configured profile. 
+ *
+ * @param [in] apn      the profile information.
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned, such apn not exist.
+ * 
+ */
+extern int qser_apn_set(qser_apn_info_s *apn);
+
+/**
+ * Retrieves the settings from a configured profile.
+ *
+ * @param [in] profile_idx        UMTS/CDMA profile ID
+ * @param [out] apn               the profile information.
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_apn_get(unsigned char profile_idx, qser_apn_info_s *apn);
+
+/**
+ * Retrieves the settings from a configured profile.
+ *
+ * @param [in] apn               the profile information.
+ * @param [out] profile_idx        UMTS/CDMA profile ID
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_apn_add(qser_apn_add_s *apn, unsigned char *profile_idx);
+
+/**
+ * Delete a configured profile.
+ *
+ * @param [in] profile_idx        UMTS/CDMA profile ID
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_apn_del(unsigned char profile_idx);
+
+/**
+ * Retrieves the settings from a configured profile list.
+ *
+ * @param [out] apn_list          the profile list information.
+ *
+ * @return 
+ *   On success, 0 is returned.  On error, -1 is returned.
+ * 
+ */
+extern int qser_apn_get_list(qser_apn_info_list_s *apn_list);
+
+#endif
+
diff --git a/common_src/lib/liblynq-qser-data/lynq-qser-data.cpp b/common_src/lib/liblynq-qser-data/lynq-qser-data.cpp
new file mode 100755
index 0000000..cfffa79
--- /dev/null
+++ b/common_src/lib/liblynq-qser-data/lynq-qser-data.cpp
@@ -0,0 +1,836 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <log/log.h>
+#include <libdata/lynq_data.h>
+#include <liblog/lynq_deflog.h>
+#include <pthread.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include "lynq-qser-data.h"
+
+#define USER_LOG_TAG "LYNQ_QSER_DATA"
+
+#define RESULT_OK (0)
+#define RESULT_ERROR (-1)
+
+static pthread_t s_cb_tid = -1;
+static int s_qser_data_cb_thread_status = 0;
+static pthread_mutex_t s_qser_data_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t s_qser_data_cb_cond = PTHREAD_COND_INITIALIZER;
+
+#define data_xml_path "/data/lynq_qser_data_apn.xml"
+
+static qser_data_call_evt_cb_t s_data_call_cb = NULL;
+const int apndb_offset = 683;
+
+void lynq_ipv4_aton_urc(lynq_data_call_response_v11_t *libdata,qser_data_call_state_s *data_res)
+{
+    inet_aton(libdata->addresses,&(data_res->v4.ip));
+    inet_aton(libdata->gateways,&(data_res->v4.gateway));
+    inet_aton(libdata->dnses,&(data_res->v4.pri_dns));
+    inet_aton(libdata->dnses,&(data_res->v4.sec_dns));
+    return ;
+}
+
+void lynq_ipv6_inet_pton_urc(lynq_data_call_response_v11_t *libdata,qser_data_call_state_s *data_res)
+{
+    inet_pton(AF_INET6,libdata->addresses,&(data_res->v6.ip));
+    inet_pton(AF_INET6,libdata->gateways,&(data_res->v6.gateway));
+    inet_pton(AF_INET6,libdata->dnses,&(data_res->v6.pri_dns));
+    inet_pton(AF_INET6,libdata->dnses,&(data_res->v6.sec_dns));
+    return ;
+}
+
+void lynq_ipv4_aton_getinfo(lynq_data_call_response_v11_t *libdata,qser_data_call_info_s *data_res)
+{
+    inet_aton(libdata->addresses,&(data_res->v4.addr.ip));
+    inet_aton(libdata->gateways,&(data_res->v4.addr.gateway));
+    inet_aton(libdata->dnses,&(data_res->v4.addr.pri_dns));
+    inet_aton(libdata->dnses,&(data_res->v4.addr.sec_dns));
+    data_res->v4.stats.pkts_tx = 0;
+    data_res->v4.stats.pkts_rx = 0;
+    data_res->v4.stats.bytes_tx = 0;
+    data_res->v4.stats.bytes_rx = 0;
+    data_res->v4.stats.pkts_dropped_tx = 0;
+    data_res->v4.stats.pkts_dropped_rx = 0;
+    return ;
+}
+
+void lynq_ipv6_inet_pton_getinfo(lynq_data_call_response_v11_t *libdata,qser_data_call_info_s *data_res)
+{
+    inet_pton(AF_INET6,libdata->addresses,&(data_res->v6.addr.ip));
+    inet_pton(AF_INET6,libdata->gateways,&(data_res->v6.addr.gateway));
+    inet_pton(AF_INET6,libdata->dnses,&(data_res->v6.addr.pri_dns));
+    inet_pton(AF_INET6,libdata->dnses,&(data_res->v6.addr.sec_dns));
+    data_res->v6.stats.pkts_tx = 0;
+    data_res->v6.stats.pkts_rx = 0;
+    data_res->v6.stats.bytes_tx = 0;
+    data_res->v6.stats.bytes_rx = 0;
+    data_res->v6.stats.pkts_dropped_tx = 0;
+    data_res->v6.stats.pkts_dropped_rx = 0;
+    return ;
+}
+
+void datacall_ipv4_status_judge(int state,qser_data_call_info_s *data_res)
+{
+    if (state != 0)
+    {
+        data_res->v4.state = QSER_DATA_CALL_CONNECTED;
+        data_res->v4.reconnect = 1;
+    }
+    else
+    {
+        data_res->v4.state = QSER_DATA_CALL_DISCONNECTED;
+        data_res->v4.reconnect = 0;
+    }
+    return ;
+}
+
+void datacall_ipv6_status_judge(int state,qser_data_call_info_s *data_res)
+{
+    if (state != 0)
+    {
+        data_res->v6.state = QSER_DATA_CALL_CONNECTED;
+        data_res->v6.reconnect = 1;
+    }
+    else
+    {
+        data_res->v6.state = QSER_DATA_CALL_DISCONNECTED;
+        data_res->v6.reconnect = 0;
+    }
+    return ;
+}
+
+
+int apn_xml_add(qser_apn_add_s *apn,unsigned char *apn_num)
+{
+    int node_num = 0;
+    char temp_buff[12];
+    xmlDocPtr pdoc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr tmp_node = NULL;
+    xmlNodePtr sum_node = NULL;
+    pdoc = xmlReadFile(data_xml_path ,"UTF-8",XML_PARSE_RECOVER);
+    if(NULL == pdoc)
+    {
+        LYERRLOG("open xml file error");
+        goto FAILED;
+    }
+    
+    node = xmlDocGetRootElement(pdoc);
+    if (NULL == node)
+    {
+        LYERRLOG("xmlDocGetRootElement() error");
+        goto FAILED;
+    }
+    sum_node = node->xmlChildrenNode;
+    sum_node = sum_node->next;
+    while (sum_node != NULL)
+    {
+        if (xmlGetProp(sum_node, "profile_idx") == NULL)  //Null Node
+        {
+            sum_node = sum_node->next;
+            continue;
+        }
+        node_num++;
+        sum_node = sum_node->next;
+    }
+    tmp_node = xmlNewNode(NULL,BAD_CAST"apn");
+    *apn_num = node_num;
+    LYERRLOG("apn_num%d ",node_num);
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",*apn_num);
+    xmlNewProp(tmp_node,BAD_CAST"profile_idx",(xmlChar *)temp_buff);
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",apn->pdp_type);
+    xmlNewProp(tmp_node,BAD_CAST"pdp_type",(xmlChar *)temp_buff);
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",apn->auth_proto);
+    xmlNewProp(tmp_node,BAD_CAST"auth_proto",(xmlChar *)temp_buff);
+    xmlNewProp(tmp_node,BAD_CAST"apn_name",(xmlChar *)apn->apn_name);
+    xmlNewProp(tmp_node,BAD_CAST"username",(xmlChar *)apn->username);
+    xmlNewProp(tmp_node,BAD_CAST"password",(xmlChar *)apn->password);
+    xmlNewProp(tmp_node,BAD_CAST"apn_type",(xmlChar *)apn->apn_type);
+    xmlAddChild(node,tmp_node);
+    xmlSaveFormatFileEnc(data_xml_path, pdoc, "UTF-8", 1);
+    xmlFreeDoc(pdoc);
+    return RESULT_OK;
+    
+    FAILED:
+    if (pdoc)
+    {
+        xmlFreeDoc(pdoc);
+    }
+    return RESULT_ERROR;
+}
+
+int apn_xml_delete(unsigned char profile_idx)
+{
+    int node_num = 0;
+    char temp_buff[12];
+    xmlDocPtr pdoc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr modify_node = NULL;
+    pdoc = xmlReadFile(data_xml_path ,"UTF-8",XML_PARSE_RECOVER);
+    if(NULL == pdoc)
+    {
+        LYERRLOG("open xml file error");
+        goto FAILED;
+    }
+    
+    node = xmlDocGetRootElement(pdoc);
+    if (NULL == node)
+    {
+        LYERRLOG("xmlDocGetRootElement() error");
+        goto FAILED;
+    }
+    modify_node = node->xmlChildrenNode;
+    modify_node = modify_node->next;
+    for (node_num=0 ;node_num<(int)profile_idx ; node_num++)
+    {
+        if (xmlGetProp(modify_node, "profile_idx") == NULL)  //Null Node
+        {
+            modify_node = modify_node->next;
+            node_num--;
+            continue;
+        }
+        modify_node = modify_node->next;
+    }
+    xmlUnlinkNode(modify_node);
+    xmlFreeNode(modify_node);
+    modify_node = NULL;
+    node_num = 0;
+    modify_node = node->xmlChildrenNode;
+    modify_node = modify_node->next;
+    while (modify_node != NULL)
+    {
+        if (xmlGetProp(modify_node, "profile_idx") == NULL)  //Null Node
+        {
+            modify_node = modify_node->next;
+            continue;
+        }
+        bzero(temp_buff,12);
+        snprintf(temp_buff,sizeof(temp_buff),"%d",node_num);
+        xmlSetProp(modify_node,BAD_CAST"profile_idx",(xmlChar *)temp_buff);
+        modify_node = modify_node->next;
+        node_num++;
+    }
+    xmlSaveFormatFileEnc(data_xml_path, pdoc, "UTF-8", 1);
+    xmlFreeDoc(pdoc);
+    return RESULT_OK;
+
+    FAILED:
+    if (pdoc)
+    {
+        xmlFreeDoc(pdoc);
+    }
+    return RESULT_ERROR;
+}
+
+int apn_xml_modify(qser_apn_info_s *apn)
+{
+    int node_num = 0;
+    char temp_buff[12];
+    xmlDocPtr pdoc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr modify_node = NULL;
+    pdoc = xmlReadFile(data_xml_path ,"UTF-8",XML_PARSE_RECOVER);
+    if(NULL == pdoc)
+    {
+        LYERRLOG("open xml file error");
+        goto FAILED;
+    }
+    
+    node = xmlDocGetRootElement(pdoc);
+    if (NULL == node)
+    {
+        LYERRLOG("xmlDocGetRootElement() error");
+        goto FAILED;
+    }
+    modify_node = node->xmlChildrenNode;
+    modify_node = modify_node->next;
+    for (node_num=0; node_num<(int)apn->profile_idx;node_num++)
+    {
+        if (xmlGetProp(modify_node, "profile_idx") == NULL)  //Null Node
+        {
+            modify_node = modify_node->next;
+            node_num--;
+            continue;
+        }
+        modify_node = modify_node->next;
+    }
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",node_num);
+    xmlSetProp(modify_node,BAD_CAST"profile_idx",(xmlChar *)temp_buff);
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",apn->pdp_type);
+    xmlSetProp(modify_node,BAD_CAST"pdp_type",(xmlChar *)temp_buff);
+    bzero(temp_buff,12);
+    snprintf(temp_buff,sizeof(temp_buff),"%d",apn->auth_proto);
+    xmlSetProp(modify_node,BAD_CAST"auth_proto",(xmlChar *)temp_buff);
+    xmlSetProp(modify_node,BAD_CAST"apn_name",(xmlChar *)apn->apn_name);
+    xmlSetProp(modify_node,BAD_CAST"username",(xmlChar *)apn->username);
+    xmlSetProp(modify_node,BAD_CAST"password",(xmlChar *)apn->password);
+    xmlSetProp(modify_node,BAD_CAST"apn_type",(xmlChar *)apn->apn_type);
+    xmlSaveFormatFileEnc(data_xml_path, pdoc, "UTF-8", 1);
+    xmlFreeDoc(pdoc);
+    return RESULT_OK;
+
+    FAILED:
+    if (pdoc)
+    {
+        xmlFreeDoc(pdoc);
+    }
+    return RESULT_ERROR;
+}
+
+
+int apn_xml_query(unsigned char profile_idx,qser_apn_info_s *apn)
+{
+    int node_num = 0;
+    xmlDocPtr pdoc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr modify_node = NULL;
+    unsigned char temp = NULL;
+    pdoc = xmlReadFile(data_xml_path ,"UTF-8",XML_PARSE_RECOVER);
+    if(NULL == pdoc)
+    {
+        LYERRLOG("open xml file error");
+        goto FAILED;
+    }
+    
+    node = xmlDocGetRootElement(pdoc);
+    if (NULL == node)
+    {
+        LYERRLOG("xmlDocGetRootElement() error");
+        goto FAILED;
+    }
+    modify_node = node->xmlChildrenNode;
+    modify_node = modify_node->next;
+    for (node_num = 0;node_num<(int)profile_idx;node_num++)
+    {
+        if (xmlGetProp(modify_node, "profile_idx") == NULL)  //Null Node
+        {
+            modify_node = modify_node->next;
+            node_num--;
+            continue;
+        }
+        modify_node = modify_node->next;
+    }
+    apn->profile_idx = (unsigned char)atoi(xmlGetProp(modify_node, "profile_idx"));
+    apn->pdp_type = (qser_apn_pdp_type_e)atoi(xmlGetProp(modify_node, "pdp_type"));
+    apn->auth_proto = (qser_apn_auth_proto_e)atoi(xmlGetProp(modify_node, "auth_proto"));
+    strcpy(apn->apn_name,(char *)xmlGetProp(modify_node, "apn_name"));
+    strcpy(apn->username,(char *)xmlGetProp(modify_node, "username"));
+    strcpy(apn->password,(char *)xmlGetProp(modify_node, "password"));
+    strcpy(apn->apn_type,(char *)xmlGetProp(modify_node, "apn_type"));
+    xmlSaveFormatFileEnc(data_xml_path, pdoc, "UTF-8", 1);
+    xmlFreeDoc(pdoc);
+    return RESULT_OK;
+
+    FAILED:
+    if (pdoc)
+    {
+        xmlFreeDoc(pdoc);
+    }
+    return RESULT_ERROR;
+}
+
+int apn_xml_query_list(qser_apn_info_list_s *apn_list)
+{
+    int node_num = 0;
+    xmlDocPtr pdoc = NULL;
+    xmlNodePtr node = NULL;
+    xmlNodePtr modify_node = NULL;
+    xmlChar *temp_char;
+    char temp[64];
+    pdoc = xmlReadFile(data_xml_path ,"UTF-8",XML_PARSE_RECOVER);
+    if(NULL == pdoc)
+    {
+        LYERRLOG("open xml file error");
+        goto FAILED;
+    }
+    
+    node = xmlDocGetRootElement(pdoc);
+    if (NULL == node)
+    {
+        LYERRLOG("xmlDocGetRootElement() error");
+        goto FAILED;
+    }
+    modify_node = node->xmlChildrenNode;
+    modify_node = modify_node->next;
+    while (modify_node != NULL)
+    {
+        temp_char = xmlGetProp(modify_node, "profile_idx");
+        if (temp_char == NULL) 
+        {
+            modify_node = modify_node->next;
+            continue;
+        }
+        sprintf(temp,"%s",temp_char);
+        apn_list->apn[node_num].profile_idx = (unsigned char)atoi(temp);
+        apn_list->apn[node_num].pdp_type = (qser_apn_pdp_type_e)atoi(xmlGetProp(modify_node, "pdp_type"));
+        apn_list->apn[node_num].auth_proto = (qser_apn_auth_proto_e)atoi(xmlGetProp(modify_node, "auth_proto"));
+        strcpy(apn_list->apn[node_num].apn_name,(char *)xmlGetProp(modify_node, "apn_name"));
+        strcpy(apn_list->apn[node_num].username,(char *)xmlGetProp(modify_node, "username"));
+        strcpy(apn_list->apn[node_num].password,(char *)xmlGetProp(modify_node, "password"));
+        node_num ++;
+        modify_node = modify_node->next;
+    }
+    apn_list->cnt = node_num;
+    xmlSaveFormatFileEnc(data_xml_path, pdoc, "UTF-8", 1);
+    xmlFreeDoc(pdoc);
+    return RESULT_OK;
+
+    FAILED:
+    if (pdoc)
+    {
+        xmlFreeDoc(pdoc);
+    }
+    return RESULT_ERROR;
+}
+
+void judge_pdp_type(qser_apn_pdp_type_e pdp_type,char *out_pdp_type)
+{
+    switch (pdp_type)
+    {
+    case QSER_APN_PDP_TYPE_IPV4:
+        strcpy(out_pdp_type,"IPV4");
+        break;
+    case QSER_APN_PDP_TYPE_PPP:
+        strcpy(out_pdp_type,"PPP");
+        break;
+    case QSER_APN_PDP_TYPE_IPV6:
+        strcpy(out_pdp_type,"IPV6");
+        break;
+    case QSER_APN_PDP_TYPE_IPV4V6:
+        strcpy(out_pdp_type,"IPV4V6");
+        break;
+    default:
+        strcpy(out_pdp_type,"NULL");
+        break;
+    }
+    return;
+}
+void judge_authtype(qser_apn_auth_proto_e auth_proto,char *out_proto)
+{
+    switch (auth_proto)
+    {
+    case QSER_APN_AUTH_PROTO_DEFAULT:
+        strcpy(out_proto,"NULL;authType=0");
+        break;
+    case QSER_APN_AUTH_PROTO_NONE:
+        strcpy(out_proto,"NULL;authType=1");
+        break;
+    case QSER_APN_AUTH_PROTO_PAP:
+        strcpy(out_proto,"NULL;authType=2");
+        break;
+    case QSER_APN_AUTH_PROTO_CHAP:
+        strcpy(out_proto,"NULL;authtype=3");
+        break;
+    case QSER_APN_AUTH_PROTO_PAP_CHAP:
+        strcpy(out_proto,"NULL;authtype=4");
+        break;
+    default:
+        strcpy(out_proto,"NULL;authType=NULL");
+        break;
+    }
+    return ;
+}
+
+int data_call_handle_get(const char profile_idx,int *handle)
+{
+    int num = LYNQ_APN_CHANNEL_MAX;
+    int table_num = 0;
+    lynq_apn_info **apn_table = NULL;
+    qser_apn_info_s apn;
+    apn_table = (lynq_apn_info **)malloc(sizeof(lynq_apn_info *)*LYNQ_APN_CHANNEL_MAX);
+    if (NULL == apn_table)
+    {
+        LYERRLOG("malloc apn_table fail ");
+        return RESULT_ERROR;
+    }
+    for(int i =0;i<10;i++)
+    {
+        apn_table[i] = (lynq_apn_info*)malloc(sizeof(lynq_apn_info));
+        if (apn_table[i]==NULL)
+        {
+            for (int n=0;n<i;n++)
+            {
+                free(apn_table[n]);
+            }
+            return RESULT_ERROR;
+        }
+        memset(apn_table[i],0,sizeof(lynq_apn_info));
+    }
+    lynq_get_apn_table(&table_num,apn_table);
+    memset(&apn,0,sizeof(qser_apn_info_s));
+    apn_xml_query(profile_idx,&apn);
+    for (int j = 0;j < table_num;j++)
+    {
+        if (strcmp(apn.apn_type,apn_table[j]->apnType) == 0)
+        {
+            *handle = apn_table[j]->index;
+            LYINFLOG("apn_table->index:%d,handle:%d ",apn_table[j]->index,*handle);
+            break;
+        }
+    }
+
+    for (int i = 0; i < LYNQ_APN_CHANNEL_MAX; i++) 
+    {
+        if (apn_table[i]!=NULL)
+        {   
+            free(apn_table[i]);
+            apn_table[i]=NULL;
+        }
+    }
+    free(apn_table);
+    apn_table=NULL;
+    LYINFLOG("data_call_handle_get end");
+    return RESULT_OK;
+}
+
+void *thread_wait_cb_status(void)
+{
+    int handle = -1;
+    lynq_data_call_response_v11_t data_urc_info;
+    qser_data_call_state_s data_cb_state;
+    while (s_qser_data_cb_thread_status)
+    {
+        lynq_wait_data_call_state_change(&handle);
+        lynq_get_data_call_list(&handle,&data_urc_info);
+        /*compare paramter*/
+        data_cb_state.profile_idx = (char)handle;
+
+        memcpy(data_cb_state.name,data_urc_info.ifname,strlen(data_urc_info.ifname)+1);
+        if (!strcmp(data_urc_info.type,"IPV4"))
+        {
+            data_cb_state.ip_family = QSER_DATA_CALL_TYPE_IPV4;
+        }
+        else if (!strcmp(data_urc_info.type,"IPV6"))
+        {
+            data_cb_state.ip_family = QSER_DATA_CALL_TYPE_IPV6;
+        }
+        else if (strcmp(data_urc_info.type,"IPV4V6"))
+        {
+            data_cb_state.ip_family = QSER_DATA_CALL_TYPE_IPV4V6;
+        }
+        else
+        {
+            LYERRLOG("unknow data call type");
+            continue;
+        }
+
+        if (data_urc_info.status != 0)
+        {
+            data_cb_state.state = QSER_DATA_CALL_CONNECTED;
+        }
+        else
+        {
+            data_cb_state.state = QSER_DATA_CALL_DISCONNECTED;
+        }
+        if (data_cb_state.ip_family == QSER_DATA_CALL_TYPE_IPV4)
+        {
+            lynq_ipv4_aton_urc(&data_urc_info,&data_cb_state);
+        }
+        else if (data_cb_state.ip_family == QSER_DATA_CALL_TYPE_IPV6)
+        {
+            lynq_ipv6_inet_pton_urc(&data_urc_info,&data_cb_state);
+        }
+        else if (data_cb_state.ip_family == QSER_DATA_CALL_TYPE_IPV4V6)
+        {
+            lynq_ipv6_inet_pton_urc(&data_urc_info,&data_cb_state);
+        }
+        else
+        {
+            LYERRLOG("unknow ip_family");
+            continue;
+        }
+        if (s_data_call_cb != NULL)
+        {
+         s_data_call_cb(&data_cb_state);
+        }
+    }
+    return NULL;
+}
+
+int qser_cb_pthread_create()
+{
+    int ret;
+    s_qser_data_cb_thread_status = 1;
+    ret = pthread_create(&s_cb_tid,NULL,thread_wait_cb_status,NULL);
+    if (ret < 0)
+    {
+        LYERRLOG("pthread create fail");
+        s_qser_data_cb_thread_status = 0;
+        return RESULT_ERROR;
+    }
+    return RESULT_OK;
+}
+
+void qser_cb_pthread_cancel()
+{
+    int ret;
+    s_qser_data_cb_thread_status = 0;
+    if (s_cb_tid != -1)
+    {
+        ret = pthread_cancel(s_cb_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+        ret = pthread_join(s_cb_tid,NULL);
+        LYDBGLOG("pthread join ret = %d",ret);
+        s_cb_tid = -1;
+    }
+    return;
+}
+
+int qser_data_call_init(qser_data_call_evt_cb_t evt_cb)
+{   
+    int ret = 0;
+    int utoken = 0;
+    if (NULL == evt_cb)
+    {
+        LYERRLOG("init incoming paramters error");
+        return RESULT_ERROR;
+    }
+    s_data_call_cb = evt_cb;
+    qser_cb_pthread_create();
+    ret = lynq_init_data(utoken);
+    if (ret != RESULT_OK)
+    {
+        qser_cb_pthread_cancel();
+        s_data_call_cb = NULL;
+        return RESULT_ERROR;
+    }
+    return RESULT_OK;
+}
+
+void qser_data_call_destroy(void)
+{
+    qser_cb_pthread_cancel();
+    lynq_deinit_data();
+    s_data_call_cb = NULL;
+    return ;
+}
+
+int qser_data_call_start(qser_data_call_s *data_call, qser_data_call_error_e *err)
+{
+    int ret = -1;
+    int handle = 0;
+    if (NULL == data_call || NULL == err)
+    {
+        LYERRLOG("call start incoming paramters error");
+        return ret;
+    }
+    if (data_call->profile_idx == 0)
+    {
+        ret = lynq_setup_data_call(&handle);
+    }
+    else
+    {
+        char pdptype[16];
+        qser_apn_info_s apn_info;
+        qser_apn_get(data_call->profile_idx,&apn_info);
+        judge_pdp_type(apn_info.pdp_type,pdptype);
+        ret = lynq_setup_data_call_sp(&handle,apn_info.apn_name,apn_info.apn_type,apn_info.username,apn_info.password,NULL,pdptype,pdptype);
+    }
+    if (ret < 0)
+    {
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+    }
+    return ret;
+}
+
+int qser_data_call_stop(char profile_idx, qser_data_call_ip_family_e ip_family, qser_data_call_error_e *err)
+{
+    int ret = 0;
+    int handle = -1;
+
+    if (NULL == err)
+    {
+        LYERRLOG("call stop incoming paramters error");
+        return ret;
+    }
+    data_call_handle_get(profile_idx,&handle);
+    ret = lynq_deactive_data_call(&handle);
+    if (ret < 0)
+    {
+        *err = QSER_DATA_CALL_ERROR_INVALID_PARAMS;
+    }
+    return RESULT_OK;
+}
+int qser_data_call_info_get(char profile_idx,qser_data_call_ip_family_e ip_family,qser_data_call_info_s *info,qser_data_call_error_e *err)
+{
+    int ret = 0;
+    int handle = -1;
+    lynq_data_call_response_v11_t data_call_info;
+    data_call_handle_get(profile_idx,&handle);
+    ret = lynq_get_data_call_list(&handle,&data_call_info);
+    if (ret == 0)
+    {
+        info->profile_idx = profile_idx;
+        info->ip_family = ip_family;
+        if (strcmp(data_call_info.type,"IPV4"))
+        {
+            strcpy(info->v4.name,data_call_info.ifname);
+            datacall_ipv4_status_judge(data_call_info.status,info);
+            LYINFLOG("[IPV4]addresses:%s,gateways:%s,dnses:%s",data_call_info.addresses,data_call_info.gateways,data_call_info.dnses);
+            lynq_ipv4_aton_getinfo(&data_call_info,info);
+        }
+        else if (strcmp(data_call_info.type,"IPV6"))
+        {
+            strcpy(info->v6.name,data_call_info.ifname);
+
+            datacall_ipv6_status_judge(data_call_info.status,info);
+            LYINFLOG("[IPV6]addresses:%s,gateways:%s,dnses:%s",data_call_info.addresses,data_call_info.gateways,data_call_info.dnses);
+            lynq_ipv6_inet_pton_getinfo(&data_call_info,info);
+        }
+        else if (strcmp(data_call_info.type,"IPV4V6"))
+        {
+            strcpy(info->v4.name,data_call_info.ifname);
+            datacall_ipv4_status_judge(data_call_info.status,info);
+            LYINFLOG("[IPV4V6]addresses:%s,gateways:%s,dnses:%s",data_call_info.addresses,data_call_info.gateways,data_call_info.dnses);
+            lynq_ipv4_aton_getinfo(&data_call_info,info);
+            strcpy(info->v6.name,data_call_info.ifname);
+            datacall_ipv6_status_judge(data_call_info.status,info);
+            LYINFLOG("[IPV4V6]addresses:%s,gateways:%s,dnses:%s",data_call_info.addresses,data_call_info.gateways,data_call_info.dnses);
+            lynq_ipv6_inet_pton_getinfo(&data_call_info,info);
+        }
+        else
+        {
+            LYERRLOG("useless qser_data_call_ip_family_e");
+        }
+    }
+    return ret;
+}
+int qser_apn_set(qser_apn_info_s *apn)
+{
+    int ret = 0;
+    if (NULL == apn)
+    {
+        LYERRLOG("apn set incoming paramters error");
+        return RESULT_ERROR;
+    }
+    ret = apn_xml_modify(apn);
+    if (ret < 0)
+    {
+        LYERRLOG("apn_xml_modify error");
+        return ret;
+    }
+    int apn_id = 0;
+    char tmp_id[12];
+    char *outinfo = NULL;
+    char normalprotocol[16];
+    char authtype[32];
+    outinfo = (char *)malloc(sizeof(char)*512);
+    bzero(tmp_id,12);
+    bzero(outinfo,512);
+    apn_id = apn->profile_idx + apndb_offset;
+    snprintf(tmp_id,sizeof(tmp_id),"%d",apn_id);
+    judge_pdp_type(apn->pdp_type,normalprotocol);
+    judge_authtype(apn->auth_proto,authtype);
+    lynq_modify_apn_db(3,tmp_id,NULL,NULL,apn->apn_name,apn->apn_type,apn->username,apn->password,normalprotocol,normalprotocol,authtype,outinfo);
+    LYINFLOG("[output]:%s",outinfo);
+    free(outinfo);
+    outinfo = NULL;
+    return RESULT_OK;
+}
+
+int qser_apn_get(unsigned char profile_idx, qser_apn_info_s *apn)
+{
+    if (profile_idx < 0 || profile_idx > 24 || NULL == apn)
+    {
+        LYERRLOG("apn get incoming paramters error");
+        return RESULT_ERROR;
+    }
+    int ret = 0;
+    ret = apn_xml_query(profile_idx,apn);
+    if (ret < 0)
+    {
+        LYERRLOG("apn_xml_query error");
+        return ret;
+    }
+    return ret;
+}
+
+int qser_apn_add(qser_apn_add_s *apn, unsigned char *profile_idx)
+{
+    int ret = 0;
+    if (NULL == apn || NULL == profile_idx)
+    {
+        LYERRLOG("apn add incoming paramters error");
+        return RESULT_ERROR;
+    }
+    ret = apn_xml_add(apn,profile_idx);
+    if (ret < 0)
+    {
+        LYERRLOG("apn_xml_add error");
+        return ret;
+    }
+    int apn_id = 0;
+    char tmp_id[12];
+    char *outinfo = NULL;
+    char normalprotocol[16];
+    char authtype[32];
+    outinfo = (char *)malloc(sizeof(char)*512);
+    bzero(tmp_id,12);
+    bzero(outinfo,512);
+    snprintf(tmp_id,sizeof(tmp_id),"%d",apn_id);
+    judge_pdp_type(apn->pdp_type,normalprotocol);
+    judge_authtype(apn->auth_proto,authtype);
+    lynq_modify_apn_db(0,tmp_id,NULL,NULL,apn->apn_name,apn->apn_type,apn->username,apn->password,normalprotocol,normalprotocol,authtype,outinfo);
+    LYINFLOG("[output]:%s",outinfo);
+    free(outinfo);
+    outinfo = NULL;
+    return RESULT_OK;
+}
+
+int qser_apn_del(unsigned char profile_idx)
+{
+    if (profile_idx < 0 || profile_idx > 24)
+    {
+        LYERRLOG("apn del incoming paramters error");
+        return RESULT_OK;
+    }
+    int ret = 0;
+    ret = apn_xml_delete(profile_idx);
+    if (ret < 0)
+    {
+        LYERRLOG("apn_xml_delete error");
+        return ret;
+    }
+    int apn_id = 0;
+    char tmp_id[12];
+    char *outinfo = NULL;
+    outinfo = (char *)malloc(sizeof(char)*512);
+    bzero(tmp_id,12);
+    bzero(outinfo,512);
+    apn_id = profile_idx+apndb_offset;
+    snprintf(tmp_id,sizeof(tmp_id),"%d",apn_id);
+    lynq_modify_apn_db(1,tmp_id,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,outinfo);
+    LYINFLOG("[output]:%s",outinfo);
+    free(outinfo);
+    outinfo = NULL;
+    return ret;
+}
+
+int qser_apn_get_list(qser_apn_info_list_s *apn_list)
+{
+    if (NULL == apn_list)
+    {
+        LYERRLOG("apn_list incoming paramters error");
+        return RESULT_ERROR;
+    }
+    int ret = 0;
+    ret = apn_xml_query_list(apn_list);
+    if (ret < 0)
+    {
+        LYERRLOG("apn_xml_query_list error");
+        return ret;
+    }
+    return ret;
+}
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-data/lynq_qser_data_apn.xml b/common_src/lib/liblynq-qser-data/lynq_qser_data_apn.xml
new file mode 100755
index 0000000..590d493
--- /dev/null
+++ b/common_src/lib/liblynq-qser-data/lynq_qser_data_apn.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lynq_qser_data_apn>
+  <apn profile_idx="0" pdp_type="3" auth_proto="0" apn_name="default" username="NULL" password="NULL" apn_type="default"/></lynq_qser_data_apn>
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-data/makefile b/common_src/lib/liblynq-qser-data/makefile
new file mode 100755
index 0000000..17e42d8
--- /dev/null
+++ b/common_src/lib/liblynq-qser-data/makefile
@@ -0,0 +1,67 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -fPIC \
+                -fpermissive \
+
+
+
+$(warning ################# lynq qser sms demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/ \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/libdata \
+  -I$(ROOT)$(includedir)/libxml2 \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -lstdc++ \
+    -lcutils \
+    -lutils \
+    -lpthread \
+    -llynq-log \
+    -llynq-data \
+	-lxml2 \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-data.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sim/LICENSE b/common_src/lib/liblynq-qser-sim/LICENSE
new file mode 100755
index 0000000..8aaabff
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sim/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("Mobiletek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to Mobiletek Inc. and/or its licensors. Without
+the prior written permission of Mobiletek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of Mobiletek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+Mobiletek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sim/include/lynq_qser_sim.h b/common_src/lib/liblynq-qser-sim/include/lynq_qser_sim.h
new file mode 100755
index 0000000..0192db5
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sim/include/lynq_qser_sim.h
@@ -0,0 +1,382 @@
+#ifndef __LYNQ_QSER_SIM__
+#define __LYNQ_QSER_SIM__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define QSER_SIM_IMSI_LEN_MAX     16  /**  Maximum length of IMSI data. */
+#define QSER_SIM_ICCID_LEN_MAX    20  /**  Maximum length of ICCID data. */
+
+typedef enum 
+{
+    E_QSER_SUCCESS                        = 0,    /**<  Success. */
+    E_QSER_ERROR_BADPARM                  = 4,    /**<  Bad parameter. */
+}E_QSER_ERROR_CODE_T;
+
+typedef uint32_t sim_client_handle_type;
+
+typedef enum 
+{
+    QSER_SIM_SLOT_ID_1          = 0xB01,    /**< Identify card in slot 1.  */
+    QSER_SIM_SLOT_ID_2          = 0xB02,    /**< Identify card in slot 2.  */
+}QSER_SIM_SLOT_ID_TYPE_T;
+
+typedef enum 
+{
+    QSER_SIM_APP_TYPE_UNKNOWN   = 0xB00,    /**<  Unknown application type  */
+    QSER_SIM_APP_TYPE_3GPP      = 0xB01,    /**< Identify the SIM/USIM application on the card.  */
+    QSER_SIM_APP_TYPE_3GPP2     = 0xB02,    /**< Identify the RUIM/CSIM application on the card.  */
+    QSER_SIM_APP_TYPE_ISIM      = 0xB03,    /**< Identify the ISIM application on the card.  */
+}QSER_SIM_APP_TYPE_T;
+
+typedef struct 
+{
+    QSER_SIM_SLOT_ID_TYPE_T     e_slot_id;  /**< Indicates the slot to be used. */
+    QSER_SIM_APP_TYPE_T         e_app;      /**< Indicates the type of the application. */
+}QSER_SIM_APP_ID_INFO_T;  /* Type */
+
+#define QSER_SIM_PIN_LEN_MAX  8   /**  Maximum length of PIN data. */
+
+typedef enum 
+{
+    QSER_SIM_PIN_ID_1 = 0xB01,  /**< Level 1 user verification.  */
+    QSER_SIM_PIN_ID_2 = 0xB02,  /**< Level 2 user verification.  */
+}QSER_SIM_PIN_ID_TYPE_T;
+
+typedef struct 
+{
+    QSER_SIM_APP_ID_INFO_T        app_info;                           /**< Application identification information. */
+    QSER_SIM_PIN_ID_TYPE_T  pin_id;                             /**< PIN ID. */
+    uint32_t                    pin_value_len;                      /**< Must be set to the number of elements in pin_value. */
+    char                        pin_value[QSER_SIM_PIN_LEN_MAX];  /*  Value of the PIN */
+}QSER_SIM_VERIFY_PIN_INFO_T;
+
+/** Changes the PIN value of an application. The application must pass both the 
+    new and the old values of the PIN to complete the operation.     
+    The same PIN can be used by multiple sessions (i.e., the PIN is shared
+    between GSM and RUIM in an ICC card). The PIN is automatically verified
+    for all the sessions when the command is executed. */
+typedef struct 
+{
+    QSER_SIM_APP_ID_INFO_T        app_info;                               /**< Application identification information. */
+    QSER_SIM_PIN_ID_TYPE_T  pin_id;                                 /**< PIN ID. */
+    uint32_t                    old_pin_value_len;                      /**< Must be set to the number of elements in old_pin_value. */
+    char                        old_pin_value[QSER_SIM_PIN_LEN_MAX];  /**< Value of the old PIN as a sequence of ASCII characters. */
+    uint32_t                    new_pin_value_len;                      /**< Must be set to the number of elements in new_pin_value. */
+    char                        new_pin_value[QSER_SIM_PIN_LEN_MAX];  /**< Value of the new PIN as a sequence of ASCII characters. */
+}QSER_SIM_CHANGE_PIN_INFO_T;
+
+/** Unblocks a blocked PIN using the PUK code. The client must pass PUK1 to unblock PIN1 or PUK2 to unblock PIN2.
+    The same PIN can be used by multiple sessions (i.e., the PIN is shared between GSM and RUIM in an ICC card). 
+    The PIN is automatically verified for all the sessions when the command is executed. */
+typedef struct 
+{
+    QSER_SIM_APP_ID_INFO_T        app_info;                               /**< Application identification information. */
+    QSER_SIM_PIN_ID_TYPE_T  pin_id;                                 /**< PIN ID. */
+    uint32_t                    puk_value_len;                          /**< Must be set to the number of elements in puk_value. */
+    char                        puk_value[QSER_SIM_PIN_LEN_MAX];      /**< Value of the PUK as a sequence of ASCII characters. */
+    uint32_t                    new_pin_value_len;                      /**< Must be set to the number of elements in new_pin_value. */
+    char                        new_pin_value[QSER_SIM_PIN_LEN_MAX];  /**< Value of the new PIN as a sequence of ASCII characters. */
+}QSER_SIM_UNBLOCK_PIN_INFO_T;
+
+/** Enables the PIN on an application. */
+typedef  QSER_SIM_VERIFY_PIN_INFO_T QSER_SIM_ENABLE_PIN_INFO_T; //Same 
+
+/** Disables the PIN of an application, */
+typedef  QSER_SIM_VERIFY_PIN_INFO_T QSER_SIM_DISABLE_PIN_INFO_T; //Same 
+
+
+typedef enum 
+{
+    QSER_SIM_PERSO_FEATURE_TYPE_UNKNOWN                 = 0xB00, /**<  Unknown personalization feature.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP_NETWORK            = 0xB01, /**<  Featurization based on 3GPP MCC and MNC.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP_NETWORK_SUBSET     = 0xB02, /**<  Featurization based on 3GPP MCC, MNC, and IMSI digits 6 and 7.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP_SERVICE_PROVIDER   = 0xB03, /**<  Featurization based on 3GPP MCC, MNC, and GID1.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP_CORPORATE          = 0xB04, /**<  Featurization based on 3GPP MCC, MNC, GID1, and GID2.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP_SIM                = 0xB05, /**<  Featurization based on the 3GPP IMSI.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP2_NETWORK_TYPE_1    = 0xB06, /**<  Featurization based on 3GPP2 MCC and MNC.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP2_NETWORK_TYPE_2    = 0xB07, /**<  Featurization based on 3GPP2 IRM code.  */
+    QSER_SIM_PERSO_FEATURE_TYPE_3GPP2_RUIM              = 0xB08, /**<  Featurization based on 3GPP2 IMSI_M.  */
+}QSER_SIM_PERSO_FEATURE_TYPE_T;
+
+typedef enum 
+{
+    QSER_SIM_CARD_STATE_UNKNOWN                     = 0xB01,    /**< Card state unknown. */
+    QSER_SIM_CARD_STATE_ABSENT                      = 0xB02,    /**< Card is absent. */
+    QSER_SIM_CARD_STATE_PRESENT                     = 0xB03,    /**< Card is present. */
+    QSER_SIM_CARD_STATE_ERROR_UNKNOWN               = 0xB04,    /**< Unknown error state. */
+    QSER_SIM_CARD_STATE_ERROR_POWER_DOWN            = 0xB05,    /**< Power down. */
+    QSER_SIM_CARD_STATE_ERROR_POLL_ERROR            = 0xB06,    /**< Poll error. */
+    QSER_SIM_CARD_STATE_ERROR_NO_ATR_RECEIVED       = 0xB07,    /**<  Failed to receive an answer to reset.  */
+    QSER_SIM_CARD_STATE_ERROR_VOLT_MISMATCH         = 0xB08,    /**< Voltage mismatch. */
+    QSER_SIM_CARD_STATE_ERROR_PARITY_ERROR          = 0xB09,    /**< Parity error. */
+    QSER_SIM_CARD_STATE_ERROR_SIM_TECHNICAL_PROBLEMS= 0xB0A,    /**< Card returned technical problems. */
+}QSER_SIM_CARD_STATE_TYPE_T;  /**< Card state. */
+
+typedef enum 
+{
+    QSER_SIM_CARD_TYPE_UNKNOWN  = 0xB00,    /**<  Unidentified card type.  */
+    QSER_SIM_CARD_TYPE_ICC      = 0xB01,    /**<  Card of SIM or RUIM type.  */
+    QSER_SIM_CARD_TYPE_UICC     = 0xB02,    /**<  Card of USIM or CSIM type.  */
+}QSER_SIM_CARD_TYPE_T;
+
+typedef enum 
+{
+    QSER_SIM_PROV_STATE_NONE    = 0xB00,    /**<  Nonprovisioning.  */
+    QSER_SIM_PROV_STATE_PRI     = 0xB01,    /**<  Primary provisioning subscription.  */
+    QSER_SIM_PROV_STATE_SEC     = 0xB02,    /**<  Secondary provisioning subscription.  */
+}QSER_SIM_SUBSCRIPTION_TYPE_T;
+
+typedef enum 
+{
+    QSER_SIM_APP_STATE_UNKNOWN                  = 0xB00,    /**< Application state unknown. */
+    QSER_SIM_APP_STATE_DETECTED                 = 0xB01,    /**<  Detected state.  */
+    QSER_SIM_APP_STATE_PIN1_REQ                 = 0xB02,    /**<  PIN1 required.  */
+    QSER_SIM_APP_STATE_PUK1_REQ                 = 0xB03,    /**<  PUK1 required.  */
+    QSER_SIM_APP_STATE_INITALIZATING            = 0xB04,    /**<  Initializing.  */
+    QSER_SIM_APP_STATE_PERSO_CK_REQ             = 0xB05,    /**<  Personalization control key required.  */
+    QSER_SIM_APP_STATE_PERSO_PUK_REQ            = 0xB06,    /**<  Personalization unblock key required.  */
+    QSER_SIM_APP_STATE_PERSO_PERMANENTLY_BLOCKED= 0xB07,    /**<  Personalization is permanently blocked.  */
+    QSER_SIM_APP_STATE_PIN1_PERM_BLOCKED        = 0xB08,    /**<  PIN1 is permanently blocked.  */
+    QSER_SIM_APP_STATE_ILLEGAL                  = 0xB09,    /**<  Illegal application state.  */
+    QSER_SIM_APP_STATE_READY                    = 0xB0A,    /**<  Application ready state.  @newpage */
+}QSER_SIM_APP_STATE_TYPE_T;
+
+typedef enum 
+{
+    QSER_SIM_PIN_STATE_UNKNOWN                  = 0xB01,    /**< Unknown PIN state. */
+    QSER_SIM_PIN_STATE_ENABLED_NOT_VERIFIED     = 0xB02,    /**<  PIN required, but has not been verified.  */
+    QSER_SIM_PIN_STATE_ENABLED_VERIFIED         = 0xB03,    /**<  PIN required and has been verified.  */
+    QSER_SIM_PIN_STATE_DISABLED                 = 0xB04,    /**<  PIN not required.  */
+    QSER_SIM_PIN_STATE_BLOCKED                  = 0xB05,    /**<  PIN verification has failed too many times and is blocked. Recoverable through PUK verification.  */
+    QSER_SIM_PIN_STATE_PERMANENTLY_BLOCKED      = 0xB06,    /**<  PUK verification has failed too many times and is not recoverable.  */
+}QSER_SIM_PIN_STATE_TYPE_T;
+
+typedef struct 
+{
+    QSER_SIM_SUBSCRIPTION_TYPE_T      subscription;           /**<   Type of subscription (i.e., primary, secondary, etc.). */
+    QSER_SIM_APP_STATE_TYPE_T         app_state;              /**<   Current state of the application. */
+    QSER_SIM_PERSO_FEATURE_TYPE_T   perso_feature;          /**<   Current personalization state and feature enabled. */
+    uint8_t                             perso_retries;          /**<   Number of personalization retries. */
+    uint8_t                             perso_unblock_retries;  /**<   Number of personalization unblock retries. */
+    QSER_SIM_PIN_STATE_TYPE_T         pin1_state;             /**<   Current PIN 1 state. */
+    uint8_t                             pin1_num_retries;       /**<   Number of PIN 1 retries. */
+    uint8_t                             puk1_num_retries;       /**<   Number of PUK 1 retries. */
+    QSER_SIM_PIN_STATE_TYPE_T         pin2_state;             /**<   Current PIN 2 state. */
+    uint8_t                             pin2_num_retries;       /**<   Number of PIN 2 retries. */
+    uint8_t                             puk2_num_retries;       /**<   Number of PUK 2 retries. */
+}QSER_SIM_CARD_APP_INFO_T;
+
+typedef struct 
+{
+    QSER_SIM_CARD_APP_INFO_T          app_3gpp;               /**<   Stores 3GPP application information. */
+    QSER_SIM_CARD_APP_INFO_T          app_3gpp2;              /**<   Stores 3GPP2 application information. */
+    QSER_SIM_CARD_APP_INFO_T          app_isim;               /**<   Stores ISIM application information. */
+}QSER_SIM_CARD_ALL_APP_INFO_T;
+
+typedef struct 
+{
+    QSER_SIM_CARD_STATE_TYPE_T      e_card_state;/**<   Current card and card error state. */
+    QSER_SIM_CARD_TYPE_T            e_card_type; /**<   Card type. */
+    QSER_SIM_CARD_ALL_APP_INFO_T      card_app_info; /**<   Stores all relevant application information. */
+}QSER_SIM_CARD_STATUS_INFO_T;
+
+int qser_sim_client_init(sim_client_handle_type  *ph_sim);
+
+int qser_sim_client_deinit(sim_client_handle_type h_sim);
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_getimsi
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to retrieve the IMSI (for 3GPP)
+    or IMSI_M (for 3GPP2) from the SIM in ASCII form
+
+    @return
+    void
+*/
+/*=========================================================================*/
+int qser_sim_getimsi(
+    sim_client_handle_type          h_sim,
+    QSER_SIM_APP_ID_INFO_T            *pt_info,   ///< [IN] The SIM identifier info.
+    char                            *imsi,      ///< [OUT] IMSI buffer
+    size_t                          imsiLen     ///< [IN] IMSI buffer length
+);
+
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_geticcid
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to retrieve the ICCID from
+    SIM in ASCII form
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_geticcid
+(
+    sim_client_handle_type          h_sim,
+    QSER_SIM_SLOT_ID_TYPE_T     simId,     ///< [IN] The SIM identifier.
+    char                            *iccid,    ///< [OUT] ICCID
+    size_t                          iccidLen   ///< [IN] ICCID buffer length
+);
+
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_getphonenumber
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to retrieve the device phone
+    number from MSISDN (for 3GPP) or MDN (for 3GPP2) from the SIM in
+    ASCII form
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_getphonenumber
+(
+    sim_client_handle_type          h_sim,
+    QSER_SIM_APP_ID_INFO_T            *pt_info,   ///< [IN] The SIM identifier.
+    char                            *phone_num, ///< [OUT] phone number
+    size_t                          phoneLen    ///< [IN] phone number buffer length
+);
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_verifypin
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to verify either PIN1 or PIN2
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_verifypin
+(
+    sim_client_handle_type      h_sim,
+    QSER_SIM_VERIFY_PIN_INFO_T    *pt_info   ///< [IN] Verify PIN infor
+);
+
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_changepin
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to change the value of
+    either PIN1 or PIN2
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_changepin
+(
+    sim_client_handle_type      h_sim,
+    QSER_SIM_CHANGE_PIN_INFO_T    *pt_info   ///< [IN] Change PIN infor
+);
+
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_unblockpin
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to unblock a PIN1 or PIN2 that
+    has been blocked
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_unblockpin
+(
+    sim_client_handle_type      h_sim,
+    QSER_SIM_UNBLOCK_PIN_INFO_T   *pt_info   ///< [IN] Unblock PIN infor
+);
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_enablepin
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to enable PIN1 or PIN2
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_enablepin
+(
+    sim_client_handle_type      h_sim,
+    QSER_SIM_ENABLE_PIN_INFO_T    *pt_info   ///< [IN] Enable PIN infor
+);
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_disablepin
+
+===========================================================================*/
+/*
+    @brief
+    Function sends a command to the modem to disable PIN1 or PIN2
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_disablepin
+(
+    sim_client_handle_type      h_sim,
+    QSER_SIM_DISABLE_PIN_INFO_T   *pt_info   ///< [IN] Disable PIN infor
+);
+
+
+/*===========================================================================
+
+  FUNCTION:  qser_sim_getcardstatus
+
+===========================================================================*/
+/*
+    @brief
+    Function retrieves the server cached card status informations and
+    sends the information to the client
+
+    @return
+    int
+*/
+/*=========================================================================*/
+int qser_sim_getcardstatus
+(
+    sim_client_handle_type          h_sim,
+    QSER_SIM_SLOT_ID_TYPE_T     simId,     ///< [IN] The SIM identifier.
+    QSER_SIM_CARD_STATUS_INFO_T   *pt_info   ///< [OUT] Cart status infor output
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sim/lynq_qser_sim.cpp b/common_src/lib/liblynq-qser-sim/lynq_qser_sim.cpp
new file mode 100755
index 0000000..6416d9e
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sim/lynq_qser_sim.cpp
@@ -0,0 +1,183 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <string.h>
+#include <unistd.h>
+#include <log/log.h>
+#include <include/lynq_sim.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <liblog/lynq_deflog.h>
+#include "lynq_qser_sim.h"
+
+#define USER_LOG_TAG "LYNQ_QSER_SIM"
+
+sim_client_handle_type h_sim = 0;
+
+int qser_sim_client_init(sim_client_handle_type  *ph_sim)
+{
+    if(NULL == ph_sim)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    *ph_sim = (sim_client_handle_type)getpid();
+    //*ph_sim = (sim_client_handle_type)53234323;
+    h_sim = *ph_sim;
+    return lynq_sim_init(*ph_sim);
+}
+
+int qser_sim_client_deinit(sim_client_handle_type h_sim)
+{
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_sim_deinit();
+}
+
+int qser_sim_getimsi(sim_client_handle_type h_sim, QSER_SIM_APP_ID_INFO_T *pt_info, char *imsi, size_t imsiLen)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(NULL == imsi)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_get_imsi(imsi);
+}
+
+int qser_sim_geticcid(sim_client_handle_type h_sim, QSER_SIM_SLOT_ID_TYPE_T simId, char *iccid, size_t iccidLen)
+{
+    if(NULL == iccid)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_get_iccid(iccid);
+}
+
+int qser_sim_getphonenumber(sim_client_handle_type h_sim, QSER_SIM_APP_ID_INFO_T *pt_info,  char *phone_num, size_t phoneLen)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(NULL == phone_num)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_query_phone_number(phone_num);
+}
+
+int qser_sim_verifypin(sim_client_handle_type h_sim, QSER_SIM_VERIFY_PIN_INFO_T *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_verify_pin(pt_info->pin_value);
+}
+
+int qser_sim_changepin(sim_client_handle_type h_sim,QSER_SIM_CHANGE_PIN_INFO_T *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_change_pin(pt_info->old_pin_value, pt_info->new_pin_value);
+}
+
+int qser_sim_unblockpin(sim_client_handle_type h_sim, QSER_SIM_UNBLOCK_PIN_INFO_T *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_unlock_pin(pt_info->puk_value, pt_info->new_pin_value);
+}
+
+int qser_sim_enablepin(sim_client_handle_type h_sim, QSER_SIM_ENABLE_PIN_INFO_T *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_enable_pin(pt_info->pin_value);
+}
+
+int qser_sim_disablepin(sim_client_handle_type h_sim, QSER_SIM_DISABLE_PIN_INFO_T *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_disable_pin(pt_info->pin_value);
+}
+
+int qser_sim_getcardstatus(sim_client_handle_type h_sim,QSER_SIM_SLOT_ID_TYPE_T simId, QSER_SIM_CARD_STATUS_INFO_T   *pt_info)
+{
+    if(NULL == pt_info)
+    {
+        LYERRLOG("input  error\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    if(h_sim == 0)
+    {
+        LYERRLOG("not init\n");
+        return E_QSER_ERROR_BADPARM;
+    }
+    return lynq_get_sim_status((int*)&pt_info->e_card_state);
+}
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sim/makefile b/common_src/lib/liblynq-qser-sim/makefile
new file mode 100755
index 0000000..cafc77c
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sim/makefile
@@ -0,0 +1,65 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -fPIC \
+                -DECALL_SUPPORT \
+                -fpermissive \
+
+
+
+$(warning ################# lynq qser sms demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/ \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+
+LOCAL_LIBS := \
+    -L. \
+    -ldl \
+    -lstdc++ \
+    -lcutils \
+    -lutils \
+    -lpthread \
+    -llynq-log \
+    -llynq-sim \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-sim.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sms/LICENSE b/common_src/lib/liblynq-qser-sms/LICENSE
new file mode 100755
index 0000000..8aaabff
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sms/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("Mobiletek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to Mobiletek Inc. and/or its licensors. Without
+the prior written permission of Mobiletek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of Mobiletek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+Mobiletek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sms/include/lynq_qser_sms.h b/common_src/lib/liblynq-qser-sms/include/lynq_qser_sms.h
new file mode 100755
index 0000000..5f0f0c3
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sms/include/lynq_qser_sms.h
@@ -0,0 +1,241 @@
+#ifndef LYNQ_QSER_SMS_H
+#define LYNQ_QSER_SMS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+
+#define MIN_MSM_PARAM_NUM 4
+#define MIN_IMS_MSM_PARAM_NUM 6
+#define MIN_WRITMSM_PARAM_NUM 5
+#define MSG_MAX_LEN 1024
+#define TELEPHONNUM_LEN 64
+#define STORAGSMS_MAX_SIZE 128
+#define SMSC_MAX_LEN 22
+#define SMS_NUM_MAX 255
+
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef uint32_t sms_client_handle_type;
+
+/**  Maximum length of an SMS. */
+#define QSER_SMS_MAX_MT_MSG_LENGTH    1440
+
+/**  Maximum string length. */
+#define QSER_SMS_MAX_ADDR_LENGTH      252
+
+/**  Maximum string length. */
+#define QSER_SMS_MAX_SCA_TYPLENGTH 3
+
+typedef enum   
+{    
+    QSER_SMS_7BIT        = 0,
+    QSER_SMS_8BIT     = 1,
+    QSER_SMS_UCS2            = 2,
+    //<2017/12/28-QCM9XOL00004C001-P01-Vicent.Gao, <[SMS] Segment 1==> CharSet to Alpha implementation.>
+    QSER_SMS_IRA             = 3,
+    //>2017/12/28-QCM9XOL00004C001-P01-Vicent.Gao
+
+}QSER_SMS_T;   
+
+typedef enum   
+{    
+    QSER_SMS_MO               = 0,    ///< SMS mobile terminated message.  
+    QSER_SMS_MT               = 1,    ///< SMS mobile originated message. 
+    QSER_SMS_BROADCAST_MT      = 2     ///< SMS Cell Broadcast message.   
+}QSER_SMS_TYPT; 
+
+typedef enum 
+{
+    QSER_SMS_STORAGTYPNONE      = -1,   /**<  Message no need to store. */
+    QSER_SMS_STORAGTYPUIM       = 0,    /**<  Message store to UIM. */
+    QSER_SMS_STORAGTYPNV        = 1,    /**<  Message store to NV. */
+    QSER_SMS_STORAGTYPDB     = 2,    /**<  Message store to NV. */
+}QSER_SMS_STORAGTYPT;
+
+typedef enum 
+{
+    QSER_SMS_MESSAGMODUNKNOWN   = -1,   /**<  Message type CDMA */
+    QSER_SMS_MESSAGMODCDMA      = 0,    /**<  Message type CDMA */
+    QSER_SMS_MESSAGMODGW        = 1,    /**<  Message type GW. */
+}QSER_SMS_MODTYPT;
+
+typedef struct 
+ {
+    uint8_t total_segments;     /**<     The number of long  short message*/
+    uint8_t seg_number;         /**<     Current number.*/
+	uint8_t referencnumber;   /**< referencnumber.*/
+}QSER_sms_user_data_head_t; 
+
+typedef struct
+{
+    /* If sms is stored, it won't parse, you need read it by yourself */
+    QSER_SMS_STORAGTYPT storage;                          ///specify where stored this msg
+    
+    QSER_SMS_T       format;
+    QSER_SMS_TYPT         type;
+    char                    src_addr[QSER_SMS_MAX_ADDR_LENGTH]; ///Telephone number string.  
+    int                     sms_data_len;
+    char                    sms_data[QSER_SMS_MAX_MT_MSG_LENGTH];   ///SMS content, data format depends on format
+    char                    timestamp[21];                      ///Message time stamp (in text mode). string format: "yy/MM/dd,hh:mm:ss+/-TimeZone" 
+    uint8_t                 user_data_head_valid;               //indicate whether long sms. TRUE-long sms; FALSE-short message;
+    QSER_sms_user_data_head_t  user_data_head;                    //long sms user data head info.
+    QSER_SMS_MODTYPT    mode;                             ///specify where stored this msg cdma or gw area
+    uint32_t                storage_index;                      ///storage index, -1 means not store
+} QSER_sms_info_t;
+     
+typedef struct
+{
+    QSER_SMS_STORAGTYPT storage;
+    QSER_SMS_MODTYPT    mode;
+    uint32_t                storage_idx;
+} QSER_sms_storage_info_t;
+
+typedef enum 
+{
+    QSER_SMS_UNKNOWN            = -1, 
+    QSER_SMS_DISCARD            = 0x00, /*  Incoming messages for this route are discarded by the WMS service without 
+                                            notifying QMI_WMS clients */
+    QSER_SMS_STORAND_NOTIFY   = 0x01, /*  Incoming messages for this route are stored to the specified device 
+                                            memory, and new message notifications */
+    QSER_SMS_TRANSFER_ONLY      = 0x02, /*  Incoming messages for this route are transferred to the client, and the
+                                            client is expected to send ACK to the network */
+    QSER_SMS_TRANSFER_AND_ACK   = 0x03, /*  Incoming messages for this route are transferred to the client, and ACK is
+                                            sent to the network */
+}QSER_SMS_RECEPTION_ACTION_TYPT;
+
+#define QSER_WMS_MESSAGLENGTH_MAX 255
+
+typedef enum 
+ {
+    QSER_WMS_MESSAGCDMA            = 0x00,     //- 0x00 -- MESSAGCDMA -- CDMA \n 
+    QSER_WMS_MESSAGGW_PP           = 0x06,     //- 0x06 -- MESSAGGW_PP -- GW_PP
+}QSER_WMS_MESSAGTYPE;
+
+
+typedef struct
+ {
+  QSER_WMS_MESSAGTYPE format;
+  uint32_t raw_messaglen;                             /**< Must be set to # of elements in raw_message */
+  uint8_t raw_message[QSER_WMS_MESSAGLENGTH_MAX];       /**< Raw message data*/
+}QSER_wms_send_raw_message_data_t; 
+
+typedef enum
+{
+  QSER_WMS_TL_CAUSCODADDR_VACANT                        = 0x00, 
+  QSER_WMS_TL_CAUSCODADDR_TRANSLATION_FAILURE           = 0x01, 
+  QSER_WMS_TL_CAUSCODNETWORK_RESOURCSHORTAGE          = 0x02, 
+  QSER_WMS_TL_CAUSCODNETWORK_FAILURE                    = 0x03, 
+  QSER_WMS_TL_CAUSCODINVALID_TELESERVICID             = 0x04, 
+  QSER_WMS_TL_CAUSCODNETWORK_OTHER                      = 0x05, 
+  QSER_WMS_TL_CAUSCODNO_PAGRESPONSE                   = 0x20, 
+  QSER_WMS_TL_CAUSCODDEST_BUSY                          = 0x21, 
+  QSER_WMS_TL_CAUSCODNO_ACK                             = 0x22, 
+  QSER_WMS_TL_CAUSCODDEST_RESOURCSHORTAGE             = 0x23, 
+  QSER_WMS_TL_CAUSCODSMS_DELIVERY_POSTPONED             = 0x24, 
+  QSER_WMS_TL_CAUSCODDEST_OUT_OF_SERV                   = 0x25, 
+  QSER_WMS_TL_CAUSCODDEST_NOT_AT_ADDR                   = 0x26, 
+  QSER_WMS_TL_CAUSCODDEST_OTHER                         = 0x27, 
+  QSER_WMS_TL_CAUSCODRADIO_IF_RESOURCSHORTAGE         = 0x40, 
+  QSER_WMS_TL_CAUSCODRADIO_IF_INCOMPATABILITY           = 0x41, 
+  QSER_WMS_TL_CAUSCODRADIO_IF_OTHER                     = 0x42, 
+  QSER_WMS_TL_CAUSCODENCODING                           = 0x60, 
+  QSER_WMS_TL_CAUSCODSMS_ORIG_DENIED                    = 0x61, 
+  QSER_WMS_TL_CAUSCODSMS_TERM_DENIED                    = 0x62, 
+  QSER_WMS_TL_CAUSCODSUPP_SERV_NOT_SUPP                 = 0x63, 
+  QSER_WMS_TL_CAUSCODSMS_NOT_SUPP                       = 0x64, 
+  QSER_WMS_TL_CAUSCODMISSING_EXPECTED_PARAM             = 0x65, 
+  QSER_WMS_TL_CAUSCODMISSING_MAND_PARAM                 = 0x66, 
+  QSER_WMS_TL_CAUSCODUNRECOGNIZED_PARAM_VAL             = 0x67, 
+  QSER_WMS_TL_CAUSCODUNEXPECTED_PARAM_VAL               = 0x68, 
+  QSER_WMS_TL_CAUSCODUSER_DATA_SIZERR                 = 0x69, 
+  QSER_WMS_TL_CAUSCODGENERAL_OTHER                      = 0x6A, 
+}QSER_WMS_TL_CAUSCODTYPE;
+
+
+
+typedef struct
+ {
+  uint16_t                              messagid;            /*  Message ID */
+  uint8_t                               causcodvalid;      /**< Must be set to true if causcode is being passed */
+  QSER_WMS_TL_CAUSCODTYPE           causcode;  
+}QSER_wms_raw_send_resp_t;
+
+typedef struct 
+ {
+  char service_center_addr[QSER_SMS_MAX_ADDR_LENGTH + 1];         /**<   Address of the service center.*/
+  uint8_t service_center_addr_typvalid;
+  char service_center_addr_type[QSER_SMS_MAX_SCA_TYPLENGTH + 1];    /**<   129 if the SMSC address does not start with a "+" characte;
+                                                                           145 if the SMSC address starts with a "+" character*/
+}QSER_sms_service_center_cfg_t;
+
+typedef QSER_sms_info_t       QSER_SMS_Msg_t; 
+typedef QSER_sms_info_t*      QSER_SMS_MsgRef; 
+
+/* Callback function registered to qser_sms_addrxmsghandler, msgRef contains the detail msg infor */
+typedef void (*QSER_SMS_RxMsgHandlerFunc_t)(QSER_SMS_MsgRef msgRef, void* contextPtr);
+
+/* Init SMS module and return h_sms, this should be called before any othe ones */
+int qser_sms_client_init(sms_client_handle_type  *ph_sms);
+
+/* Add callback function, if any new msg arrived, it will notify app */
+int qser_sms_addrxmsghandler(QSER_SMS_RxMsgHandlerFunc_t handlerPtr, void* contextPtr);
+
+/* Send sms, you just need to fill format/src_addr/sms_data_len/sms_data,
+   if format is UCS2, the data should be Unicode-BE format.
+*/
+int qser_sms_send_sms(sms_client_handle_type h_sms, QSER_sms_info_t *pt_sms_info);
+
+/* DeInit SMS module and release resource, this should be called in the last one. */
+int qser_sms_client_deinit(sms_client_handle_type h_sms);
+     
+/* Delete the SMS specified in the  pt_sms_storage */
+int qser_sms_deletefromstorage(sms_client_handle_type  h_sms, QSER_sms_storage_info_t  *pt_sms_storage);
+
+/* Send sms PDU.
+*/
+int qser_sms_send_smspdu( sms_client_handle_type     h_sms,
+                         QSER_wms_send_raw_message_data_t *raw_messagdata,
+                         QSER_wms_raw_send_resp_t *rawresp);
+
+
+/* Get sms center address.
+*/
+int qser_sms_getsmscenteraddress( sms_client_handle_type     h_sms,
+                       QSER_sms_service_center_cfg_t *set_sca_cfg);
+
+/* Set sms center address.
+*/
+int qser_sms_setsmscenteraddress( sms_client_handle_type     h_sms,
+                       QSER_sms_service_center_cfg_t *get_sca_cfg);
+
+/*
+Usage 1 (register callback and wait for new sms arrive): 
+1, qser_sms_client_init
+2, qser_sms_addrxmsghandler(pf_cb)
+3, wait for sms arrive, pf_cb will pass the detail sms info to app.
+4, qser_sms_client_deinit
+
+
+Usage 2 (Send sms): 
+1, qser_sms_client_init
+2, qser_sms_addrxmsghandler(pf_cb)
+3, qser_sms_send_sms
+4, qser_sms_client_deinit
+
+
+Usage 3 (store sms): 
+1, qser_sms_client_init
+2, qser_sms_addrxmsghandler(pf_cb)
+3, qser_sms_setroutelist (Notice: class-0 not allowed to store, class-2 must be stored to UIM)
+4, pf_cb will be called when new sms arrived, and tell you where the sms stored
+5, you can call qser_sms_deletefromstorage to delete specified sms, the location can be got from pf_cb.
+6, qser_sms_client_deinit
+*/
+    
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-sms/lynq_qser_sms.cpp b/common_src/lib/liblynq-qser-sms/lynq_qser_sms.cpp
new file mode 100755
index 0000000..5ff13a7
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sms/lynq_qser_sms.cpp
@@ -0,0 +1,195 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <liblog/lynq_deflog.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <libsms/lynq_sms.h>
+#include "lynq_qser_sms.h"
+#define USER_LOG_TAG "LYNQ_QSER_SMS"
+
+QSER_SMS_RxMsgHandlerFunc_t tmp = NULL;
+
+sms_client_handle_type h_sms = 0;
+
+enum{
+    SMS_OK = 0,
+    SMS_FAIL,
+    SMS_PARAM_ERR
+};
+
+void *new_sms_thread_recv(void *p)
+{
+    int handle = -1;
+    int status = -1;
+    int charset = -1;
+    char smsc[1024];
+    int smscLen = -1;
+    int smslen = -1;
+    char message[1024];
+    char teleNum[1024];
+    int numLen = -1;
+    int current = -1;
+    int total = -1;
+    QSER_sms_info_t QSER_sms_info;
+    while (1)
+    {
+        if(!lynq_wait_receive_new_sms(&handle))
+        {
+            if(!lynq_read_sms(handle,&status,&charset,smsc,&smscLen,&smslen,message,teleNum,&numLen,&current,&total))
+            {
+                QSER_sms_info.storage_index = handle;
+                QSER_sms_info.format = (QSER_SMS_T)charset;
+                memcpy(QSER_sms_info.sms_data, message, smslen);
+                QSER_sms_info.sms_data[smslen] = '\0';
+                QSER_sms_info.sms_data_len = smslen;
+                if(total > 1)
+                {
+                    QSER_sms_info.user_data_head_valid = 1;
+                }
+                else
+                {
+                    QSER_sms_info.user_data_head_valid = 0;
+                }
+                tmp(&QSER_sms_info, &h_sms);
+            }
+            else
+            {
+                LYDBGLOG("lynq_read_sms error\n");
+            }
+        }
+        else
+        {
+            LYDBGLOG("lynq_wait_receive_new_sms error\n");
+            break;
+        }
+    }
+    return NULL;
+}
+
+int qser_sms_client_init(sms_client_handle_type  *ph_sms)
+{
+    if(NULL == ph_sms)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    *ph_sms = (sms_client_handle_type)getpid();
+    h_sms = *ph_sms;
+    return lynq_sms_init(*ph_sms);
+}
+
+int qser_sms_client_deinit(sms_client_handle_type h_sms)
+{
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    return lynq_sms_deinit();
+}
+
+int qser_sms_send_sms(sms_client_handle_type h_sms, QSER_sms_info_t *pt_sms_info)
+{
+    if(NULL == pt_sms_info)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    return lynq_send_sms(pt_sms_info->src_addr, pt_sms_info->type, pt_sms_info->sms_data, pt_sms_info->sms_data_len);
+}
+
+int qser_sms_addrxmsghandler(QSER_SMS_RxMsgHandlerFunc_t handlerPtr, void* contextPtr)
+{
+    if(NULL == handlerPtr)
+    {
+        return SMS_PARAM_ERR;
+    }
+    if(NULL == contextPtr)
+    {
+        return SMS_PARAM_ERR;
+    }
+    tmp = handlerPtr;
+    pthread_t lynq_new_sms_tid = -1;
+    int rt = pthread_create(&lynq_new_sms_tid, NULL, new_sms_thread_recv, NULL);
+    if(rt < 0)
+    {
+        LYDBGLOG("qser_sms_addrxmsghandler pthread_create error!!!\n");
+        return -1;
+    }
+    return SMS_OK;
+}
+
+int qser_sms_deletefromstorage(sms_client_handle_type  h_sms, QSER_sms_storage_info_t  *pt_sms_storage)
+{
+    if(NULL == pt_sms_storage)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    return lynq_delete_sms(pt_sms_storage->storage_idx);
+}
+
+int qser_sms_send_smspdu(sms_client_handle_type h_sms, QSER_wms_send_raw_message_data_t *raw_messagdata, QSER_wms_raw_send_resp_t *rawresp)
+{
+    if(NULL == raw_messagdata)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(NULL == rawresp)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    LYERRLOG("not support\n");
+    return 0;
+}
+
+int qser_sms_getsmscenteraddress( sms_client_handle_type h_sms, QSER_sms_service_center_cfg_t *set_sca_cfg)
+{
+    if(NULL == set_sca_cfg)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    return lynq_get_smsc_address(set_sca_cfg->service_center_addr);
+}
+
+int qser_sms_setsmscenteraddress( sms_client_handle_type h_sms, QSER_sms_service_center_cfg_t *get_sca_cfg)
+{
+    if(NULL == get_sca_cfg)
+    {
+        LYERRLOG("input error\n");
+        return SMS_PARAM_ERR;
+    }
+    if(h_sms == 0)
+    {
+        LYERRLOG("not init\n");
+        return SMS_PARAM_ERR;
+    }
+    return lynq_set_smsc_address(get_sca_cfg->service_center_addr);
+}
diff --git a/common_src/lib/liblynq-qser-sms/makefile b/common_src/lib/liblynq-qser-sms/makefile
new file mode 100755
index 0000000..82a52b4
--- /dev/null
+++ b/common_src/lib/liblynq-qser-sms/makefile
@@ -0,0 +1,65 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -fPIC \
+                -fpermissive \
+
+
+
+$(warning ################# lynq qser sms demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/ \
+  -I$(ROOT)$(includedir)/logger \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/libsms \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -lstdc++ \
+    -lcutils \
+    -lutils \
+    -lpthread \
+    -llynq-log \
+    -llynq-sms \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-sms.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete
diff --git a/common_src/lib/liblynq-qser-voice/include/lynq-qser-voice.h b/common_src/lib/liblynq-qser-voice/include/lynq-qser-voice.h
new file mode 100755
index 0000000..528acc0
--- /dev/null
+++ b/common_src/lib/liblynq-qser-voice/include/lynq-qser-voice.h
@@ -0,0 +1,133 @@
+/**
+ *@file     qser_voice.h
+ *@date     2017-11-30
+ *@author   
+ *@brief    
+ */
+
+
+#ifndef __LYNQ_QSER_VOICE_H__
+#define __LYNQ_QSER_VOICE_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum
+{
+    E_QSER_VCALL_EXTERNAL_SLOT_1,
+    E_QSER_VCALL_EXTERNAL_SLOT_2,
+    E_QSER_VCALL_EMBEDDED,
+    E_QSER_VCALL_REMOTE,
+    E_QSER_VCALL_ID_MAX
+}E_QSER_VCALL_ID_T;
+
+typedef enum 
+{
+    E_QSER_VOICE_CALL_STATE_INCOMING      = 0x0000, /**< MT incoming; CC setup. */
+    E_QSER_VOICE_CALL_STATE_DIALING       = 0x0001, /**< Dialing state. */
+    E_QSER_VOICE_CALL_STATE_ALERTING      = 0x0002, /**< MT call waiting; MO alterting. */
+    E_QSER_VOICE_CALL_STATE_ACTIVE        = 0x0003, /**< Call is active. */
+    E_QSER_VOICE_CALL_STATE_HOLDING       = 0x0004, /**< Call is on hold. */
+    E_QSER_VOICE_CALL_STATE_END           = 0x0005, /**< Call is disconnected. */
+    E_QSER_VOICE_CALL_STATE_WAITING       = 0x0006, /**< Call is waiting. */
+}qser_voice_call_state_t;
+
+typedef enum 
+{
+    E_QSER_VOICE_CALL_WAITING_VOICE_ENABLED       = 0, /**<  Voice call waiting enabled. */
+    E_QSER_VOICE_CALL_WAITING_DISABLED            = 1, /**<  Voice call waiting disabled. */
+}E_QSER_VOICE_CALL_WAITING_SERVICE_T;
+
+typedef struct 
+{
+    E_QSER_VOICE_CALL_WAITING_SERVICE_T   waiting_service;
+}qser_voice_call_waiting_service_t;
+
+typedef qser_voice_call_state_t E_QSER_VOICE_CALL_STATE_T;
+
+typedef uint32_t voice_client_handle_type;
+
+/* Callback function registered via QSER_Voice_Call_AddStateHandler;
+   This will be called if any stated changed of call_id
+*/
+typedef void (*QSER_VoiceCall_StateHandlerFunc_t)
+(
+    int                     caLOCAL_C_INCLUDESll_id,
+    char*                   phone_num,
+    E_QSER_VOICE_CALL_STATE_T state,
+    void                    *contextPtr
+);
+
+/* Init voice module and return h_voice, this should be called before any other APIs */
+int qser_voice_call_client_init(voice_client_handle_type  *ph_voice);
+
+/* DeInit voice module and release resources, this should be called at last */
+int qser_voice_call_client_deinit(voice_client_handle_type h_voice);
+
+/* Add callback function, if any call state changed, handlerPtr will be called to notify App */
+int qser_voice_call_addstatehandler(voice_client_handle_type          h_voice,
+                                  QSER_VoiceCall_StateHandlerFunc_t   handlerPtr,
+                                  void*                             contextPtr);
+
+/* Remove callback function, won't receive any notify anymore */
+int qser_voice_call_removestatehandle(voice_client_handle_type       h_voice);
+
+/* Start call and return call_id, this can be used in the later */
+int qser_voice_call_start(voice_client_handle_type    h_voice,
+                        E_QSER_VCALL_ID_T             simId,
+                        char*                       phone_number,   ///< [IN] Destination identifier for the voice
+                        int                         *call_id);       ///< [OUT] call id
+
+/* End call of call_id, which returned by QSER_Voice_Call_Start or callback func register via QSER_Voice_Call_AddStateHandler */
+int qser_voice_call_end(  voice_client_handle_type    h_voice,
+                        int                         call_id);        ///< [IN] call id, return by QSER_Voice_Start
+
+/* Answer the call of call_id, which returned by callback func register via QSER_Voice_Call_AddStateHandler */
+int qser_voice_call_answer(voice_client_handle_type    h_voice,
+                         int                         call_id );
+
+int qser_voice_call_hold( voice_client_handle_type    h_voice);
+
+int qser_voice_call_unhold(voice_client_handle_type    h_voice);
+
+//Set voice call waiting
+int qser_voice_call_setwaiting
+( 
+    int                                 h_voice, 
+    qser_voice_call_waiting_service_t e_service
+);
+
+//Get voice call waiting status
+int qser_voice_call_getwaitingsatus
+(
+    int                                 h_voice, 
+    qser_voice_call_waiting_service_t *pe_service
+);
+
+
+/*
+Usage 1 (register callback and wait for new call in, then answer): 
+1, QSER_Voice_Call_Client_Init
+2, QSER_Voice_Call_AddStateHandler(pf_cb)
+3, wait for new call arrive, pf_cb will pass the call_id to app.
+4, QSER_Voice_Call_Answer(call_id)
+5, QSER_Voice_Call_End
+6, QSER_Voice_Call_Client_Deinit
+
+
+Usage 2 (call out): 
+1, QSER_Voice_Call_Client_Init
+2, QSER_Voice_Call_AddStateHandler(pf_cb)
+3, QSER_Voice_Call_Start
+4, QSER_Voice_Call_End
+5, QSER_Voice_Call_Client_Deinit
+
+
+*/
+    
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __QSER_VOICE_H__
+
diff --git a/common_src/lib/liblynq-qser-voice/lynq-qser-voice.cpp b/common_src/lib/liblynq-qser-voice/lynq-qser-voice.cpp
new file mode 100755
index 0000000..faa1a1b
--- /dev/null
+++ b/common_src/lib/liblynq-qser-voice/lynq-qser-voice.cpp
@@ -0,0 +1,220 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <liblog/lynq_deflog.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <libcall/lynq_call.h>
+
+#include "lynq-qser-voice.h"
+
+#define USER_LOG_TAG "LYNQ_QSER_CALL"
+
+#define RESULT_OK (0)
+#define RESULT_ERROR (-1)
+
+static pthread_t s_lynq_voice_tid = -1;
+static QSER_VoiceCall_StateHandlerFunc_t   s_voice_cb = NULL;
+static int s_voice_thread_status = 0;
+
+ typedef enum {
+     LYNQ_CALL_ACTIVE = 0,
+     LYNQ_CALL_HOLDING = 1,
+     LYNQ_CALL_DIALING = 2,    /* MO call only */
+     LYNQ_CALL_ALERTING = 3,   /* MO call only */
+     LYNQ_CALL_INCOMING = 4,   /* MT call only */
+     LYNQ_CALL_WAITING = 5,    /* MT call only */
+     /*warren add for T800 platform 2022/04/26 start*/
+     LYNQ_CALL_END = 6,         /*CALL END*/
+     /*warren add for T800 platform 2022/04/26 end*/
+}lynq_call_state_t;
+
+
+void *voice_thread_recv(void *context)
+{
+    int handle = 0;
+    int call_state;
+    int toa;
+    int direction;
+    char addr[64];
+    E_QSER_VOICE_CALL_STATE_T voice_state;
+    while (s_voice_thread_status)
+    {
+        lynq_wait_call_state_change(&handle);
+        lynq_get_current_call_state(&handle,&call_state,&toa,&direction,addr);
+        if (call_state == LYNQ_CALL_ACTIVE)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_ACTIVE;
+        }
+        else if(call_state == LYNQ_CALL_HOLDING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_HOLDING;
+        }
+        else if(call_state == LYNQ_CALL_DIALING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_DIALING;
+        }
+        else if(call_state == LYNQ_CALL_ALERTING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_ALERTING;
+        }
+        else if(call_state == LYNQ_CALL_INCOMING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_INCOMING;
+        }
+        else if(call_state == LYNQ_CALL_WAITING)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_WAITING;
+        }
+        else if(call_state == LYNQ_CALL_END)
+        {
+            voice_state = E_QSER_VOICE_CALL_STATE_END;
+        }
+        else
+        {
+            LYERRLOG("unknow call state");
+            continue;
+        }
+        if (s_voice_cb != NULL)
+        {
+            s_voice_cb(handle,addr,voice_state,context);
+        }
+    }
+    return NULL;
+}
+
+int qser_voice_call_client_init(voice_client_handle_type  *ph_voice)
+{   
+    if(NULL == ph_voice)
+    {
+        LYERRLOG("input error");
+        return RESULT_ERROR;
+    }
+    *ph_voice = (voice_client_handle_type)getpid();
+    return lynq_init_call(*ph_voice);
+}
+
+int qser_voice_call_client_deinit(voice_client_handle_type h_voice)
+{
+    if (NULL == h_voice)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_deinit_call();
+}
+
+int qser_voice_call_addstatehandler(voice_client_handle_type          h_voice,
+                                  QSER_VoiceCall_StateHandlerFunc_t   handlerPtr,
+                                  void*                             contextPtr)
+{
+    if(h_voice == 0 || handlerPtr== NULL)
+    {
+        LYERRLOG("input error");
+        return RESULT_ERROR;
+    }
+    if (s_voice_cb != NULL)
+    {
+        LYERRLOG("The existing state handle does not need to be added");
+        return RESULT_ERROR;
+    }
+    s_voice_cb = handlerPtr;
+    s_voice_thread_status = 1;
+    int rt = pthread_create(&s_lynq_voice_tid, NULL, voice_thread_recv, contextPtr);
+    if(rt < 0)
+    {
+        LYDBGLOG("qser_voice_call_addstatehandler pthread_create error!!!\n");
+        s_voice_cb = NULL;
+        s_voice_thread_status = 0;
+        s_lynq_voice_tid = -1;
+        return RESULT_ERROR;
+    }
+    return RESULT_OK;
+}
+
+int qser_voice_call_removestatehandle(voice_client_handle_type h_voice)
+{
+    int ret;
+    if (s_lynq_voice_tid != -1)
+    {
+        ret = pthread_cancel(s_lynq_voice_tid);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+    }
+    if (s_lynq_voice_tid != -1)
+    {
+        ret = pthread_join(s_lynq_voice_tid,NULL);
+        LYDBGLOG("pthread cancel ret = %d",ret);
+        s_lynq_voice_tid = -1;
+    }
+    s_voice_thread_status = 0;
+    s_voice_cb == NULL;
+    return RESULT_OK;
+}
+
+int qser_voice_call_start(voice_client_handle_type    h_voice,
+                        E_QSER_VCALL_ID_T             simId,
+                        char*                       phone_number,
+                        int                         *call_id)
+{
+    if(h_voice == 0 || NULL == phone_number || NULL == call_id)
+    {
+        LYERRLOG("qser_voice_call_start input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call(call_id,phone_number);
+}  
+
+int qser_voice_call_end(voice_client_handle_type h_voice,int call_id)
+{
+    if(h_voice == 0 || call_id <= 0)
+    {
+        LYERRLOG("qser_voice_call_end input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call_hungup(&call_id);
+}
+
+int qser_voice_call_answer(voice_client_handle_type h_voice,int call_id)
+{
+    if(h_voice == 0 || call_id <= 0)
+    {
+        LYERRLOG("qser_voice_call_answer input error");
+        return RESULT_ERROR;
+    }
+    return lynq_call_answer();
+}
+
+int qser_voice_call_getwaitingsatus(int h_voice,qser_voice_call_waiting_service_t *pe_service)
+{
+    LYINFLOG("To be completed");
+    return RESULT_OK;
+}
+
+int qser_voice_call_setwaiting(int h_voice, qser_voice_call_waiting_service_t e_service)
+{
+    LYINFLOG("To be completed");
+    return RESULT_OK;
+}
+
+int qser_voice_call_hold(voice_client_handle_type h_voice)
+{
+    if (h_voice == 0)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_switch_waiting_or_holding_and_active();
+}
+
+int qser_voice_call_unhold(voice_client_handle_type h_voice)
+{
+    if (h_voice == 0)
+    {
+        LYERRLOG("init first");
+        return RESULT_ERROR;
+    }
+    return lynq_switch_waiting_or_holding_and_active();
+}
\ No newline at end of file
diff --git a/common_src/lib/liblynq-qser-voice/makefile b/common_src/lib/liblynq-qser-voice/makefile
new file mode 100755
index 0000000..b5b7d36
--- /dev/null
+++ b/common_src/lib/liblynq-qser-voice/makefile
@@ -0,0 +1,66 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+                -std=gnu++14 \
+                -g -Os \
+                -flto \
+                -fPIC \
+                -fpermissive \
+
+
+
+$(warning ################# lynq qser sms demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH   = .
+
+LOCAL_C_INCLUDES = \
+  -I. \
+  -I$(LOCAL_PATH)/include/ \
+  -I$(LOCAL_PATH)/ \
+  -I$(ROOT)$(includedir)/liblog \
+  -I$(ROOT)$(includedir)/libcall \
+
+
+LOCAL_LIBS := \
+    -L. \
+    -lstdc++ \
+    -lcutils \
+    -lutils \
+    -lbinder \
+    -lpthread \
+    -llynq-log \
+    -llynq-call \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-qser-voice.so
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs 
+all: build
+$(EXECUTABLE): $(OBJECTS)
+	$(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.cpp
+	$(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build:  $(EXECUTABLE)
+	$(warning ########## build $(EXECUTABLE)  ##########)
+install:
+	mkdir -p $(ROOT)$(base_libdir)/
+	install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+	mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+pack_rootfs:
+	mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+	mkdir -p $(PACK_TO)$(base_libdir)/
+	cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+	$(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+	$(RM) $(OBJECTS) $(EXECUTABLE)
+	-find . -name "*.o" -delete