[feature]liblynq-at-extension.so and demo app
Change-Id: I6a66b590774054d29b19352b126de2c24561c43e
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/liblynq-at-extension/liblynq-at-extension.bb b/meta/meta-mediatek-mt2735/recipes-lynq/liblynq-at-extension/liblynq-at-extension.bb
new file mode 100755
index 0000000..5a67029
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/liblynq-at-extension/liblynq-at-extension.bb
@@ -0,0 +1,49 @@
+inherit externalsrc package
+
+DESCRIPTION = "lynq at extension"
+LICENSE = "MediaTekProprietary"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "platform-libs liblynq-log"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/lynq/lib/liblynq-at-extension"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+ 'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+ 'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+FILES_${PN} = "${base_libdir}/*.so \
+ ${base_bindir}\
+ ${base_sbindir} \
+ /etc/dbus-1/system.d/"
+FILES_${PN}-dev = "/test \
+ ${includedir}"
+FILES_${PN}-doc = "/doc"
+FILES_${PN}-dbg ="${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+ if [ "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa53hf-neon-fp-armv8" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mfpu=neon-vfpv4 -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE -mhard-float -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53 -mtune=cortex-a53"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ fi
+}
+
+do_install() {
+ oe_runmake install ROOT=${D}
+ if [ -d "${WORKONSRC}" ] ; then
+ install -d ${D}${includedir}
+ cp -af ${S}/include/lib_at/ ${D}${includedir}/lib_at
+ fi
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/lynq-at-extension/lynq-at-extension.bb b/meta/meta-mediatek-mt2735/recipes-lynq/lynq-at-extension/lynq-at-extension.bb
new file mode 100755
index 0000000..e7990e5
--- /dev/null
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/lynq-at-extension/lynq-at-extension.bb
@@ -0,0 +1,30 @@
+inherit externalsrc package
+
+DESCRIPTION = "function test"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+DEPENDS += "platform-libs liblynq-at-extension"
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/lynq/packages/apps/lynq-at-extension/src"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+ 'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+ 'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+ if test "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" || test "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4"; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
+ fi
+}
+
+do_install() {
+ install -d ${D}${bindir}/
+ install -m 0755 ${S}/lynq-at-extension ${D}${bindir}/
+ install -d ${D}${includedir}
+}
diff --git a/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb b/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
index 9cff7d0..1dfc739 100755
--- a/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
+++ b/meta/meta-mediatek-mt2735/recipes-lynq/packagegroups/packagegroup-lync-mt2735.bb
@@ -18,6 +18,7 @@
liblynq-driver \
liblynq-network \
liblynq-sim \
+ liblynq-at-extension \
lynq-dev-test \
liblynq-tele-ril \
lynq-media-test \
@@ -27,6 +28,7 @@
lynq-factory-test \
lynq-function-test \
lynq-low-power \
+ lynq-at-extension \
liblynq-logdata-handle \
logrotate \
lynq-default \
diff --git a/src/lynq/framework/lynq-ril-service/src/ril.cpp b/src/lynq/framework/lynq-ril-service/src/ril.cpp
index 3dd15d3..cf3a670 100755
--- a/src/lynq/framework/lynq-ril-service/src/ril.cpp
+++ b/src/lynq/framework/lynq-ril-service/src/ril.cpp
@@ -153,8 +153,13 @@
/*Warren add for t800 RIL service 2021_12_10 start*/
#define LYNQ_SOCKET_ENVNT_FD_MAX 100
#define LYNQ_SERVICE_PORT 8088
+#define LYNQ_AT_SERVICE_PORT 8087
#define LYNQ_BRODCAST_PORT 8086
#define LYNQ_SOCKET_BUFFER (1024*8+sizeof(int)*3+10)
+/*lei add*/
+#define LYNQ_AT_SOCKET_BUFFER 1024
+#define MAX_AT_CMD 50
+/*lei add*/
//int LYNQ_RIL_respSocket(Parcel &p,RIL_Token t);
//int LYNQ_RIL_urcBroadcast(Parcel &p);
@@ -163,6 +168,12 @@
/*Warren add for t800 RIL service 2021_12_10 end*/
+/*lei add*/
+char buffer_at[LYNQ_AT_SOCKET_BUFFER] = {0};
+/*For at extension to receive at buffer*/
+char *at_buf_ext[MAX_AT_CMD];
+int sockfd = 0;
+/*lei add*/
#if RILC_LOG
static char printBuf[PRINTBUF_SIZE];
static char tempPrintBuf[PRINTBUF_SIZE];
@@ -6050,8 +6061,184 @@
return 0;
}
+/**
+ * @brief check at input in at_buffer
+ * @param buf type:in at port input
+ * @return int
+ */
+static int lynq_inside_at_buffer(char *buf)
+{
+ for(int i = 0; i < MAX_AT_CMD; i++)
+ {
+ if(at_buf_ext[i] == NULL)
+ {
+ break;
+ }
+ else
+ {
+ if(!strcmp(at_buf_ext[i], buf))
+ {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * @brief send input to client
+ * @param buffer type:in buffer from at port
+ * @param len_buf type:in strlen(buffer)
+ * @param client type:in sockaddr client
+ * @return int
+ */
+static int lynq_send_info(char *buffer, int len_buf, struct sockaddr* client)
+{
+ socklen_t len = sizeof(*client);
+ int sent = sendto(sockfd,buffer,len_buf,0,client,len);
+ if( sent < 0 )
+ {
+ RLOGE("lynq_send_info send fail (sent=%d, sendFD=%d, dataSize=%d)",
+ sent,sockfd, len);
+ return sent;
+ }
+ return 0;
+}
+
+/**
+ * @brief Fetch data from a one-dimensional array into a two-dimensional array
+ *
+ * @param cmd type:in buffer from client
+ * @param argv type:in two-dimensional array
+ * @param cnt type:in Two dimensional array subscript
+ * @return int
+ */
+static int lynq_parse_at_cmd(char *cmd, char *argv[], int cnt)
+{
+ if(NULL == cmd || NULL == argv)
+ {
+ return -1;
+ }
+ if(cnt > MAX_AT_CMD)
+ {
+ return -1;
+ }
+ const char s[2] = ";";
+ char *token;
+ int argc = cnt;
+ token = strtok(cmd, s);
+ while( token != NULL ) {
+ argv[argc++] = token;
+ token = strtok(NULL, s);
+ }
+ return 0;
+}
+
+/**
+ * @brief count at cmd amount
+ *
+ * @param type:in buffer
+ * @return int
+ */
+static int lynq_count_at(char *buffer)
+{
+ char *p = buffer;
+ int count = 0;
+ while(*p != '\0')
+ {
+ if(*p == ';')
+ {
+ count++;
+ }
+ *p++;
+ }
+ return count+1;
+}
+
+/**
+ * @brief receive registion and display on at port
+ * @param parm type:in
+ * @return void*
+ */
+void *receive_at(void *parm)
+{
+ RLOGE("receive_at thread start\n");
+ struct sockaddr* cli = (struct sockaddr*)parm;
+ socklen_t len;
+ int recv = 0;
+ char display[1024] = {0};
+ /*For at extension to receive at buffer*/
+ int count_recv = 0;
+ int count_at_cmd = 0;
+ len = sizeof(*cli);
+ while(1)
+ {
+ if(count_recv == 0)
+ {
+ RLOGE("receive third at cmd\n");
+ recv = recvfrom(sockfd, buffer_at, LYNQ_AT_SOCKET_BUFFER, 0, cli, &len);
+ if(recv < 0)
+ {
+ RLOGE("recv fail\n");
+ continue;
+ }
+ RLOGE("recvfrom from client\n");
+ /*parse buffer for at command*/
+ count_at_cmd = lynq_count_at(buffer_at);
+ if(count_at_cmd > MAX_AT_CMD)
+ {
+ RLOGE("too many at cmd\n");
+ continue;;
+ }
+ lynq_parse_at_cmd(buffer_at, at_buf_ext, 0);
+ }
+ else
+ {
+ RLOGE("display output on at port\n");
+ bzero(display, 1024);
+ recv = recvfrom(sockfd, display, LYNQ_AT_SOCKET_BUFFER, 0, cli, &len);
+ if(recv < 0)
+ {
+ RLOGE("recv fail\n");
+ continue;
+ }
+ /*display on at port*/
+ else
+ {
+ strcat(display, "\n");
+ int n = write(ttyGS3_fd,display,strlen(display));
+ if(n<0)
+ {
+ RLOGE("lynq resp write error");
+ }
+ }
+ }
+ count_recv++;
+ }
+ return NULL;
+}
+
void startUsbLoop(void)
{
+ /*lei add*/
+ //Create a network communication object
+ struct sockaddr_in addr_serv;
+ struct sockaddr_in addr_clie;
+ //Creating a Socket object
+ sockfd=socket(AF_INET,SOCK_DGRAM,0);
+ memset(&addr_serv, 0, sizeof(addr_serv));
+ addr_serv.sin_family =AF_INET;
+ addr_serv.sin_port =htons(LYNQ_AT_SERVICE_PORT);
+ addr_serv.sin_addr.s_addr=htonl(INADDR_ANY);
+ bind(sockfd,(struct sockaddr*)&addr_serv,sizeof(addr_serv));
+ //receive registion and display on at port
+ pthread_t thid;
+ if(pthread_create(&thid, NULL, receive_at, (struct sockaddr*)&addr_clie) != 0) {
+ RLOGE("thread creation failed\n");
+ exit(1);
+ }
+ RLOGE("thread creation\n");
+ /*lei add*/
int nread=-1;
int n = -1;
int routeId = -1;
@@ -6070,7 +6257,7 @@
perror("--test--");
kill(0, SIGKILL);
}
- printf("[%s]open %s successfully!!!\n",__FUNCTION__,ttyname(ttyGS3_fd));
+ RLOGD("[%s]open %s successfully!!!\n",__FUNCTION__,ttyname(ttyGS3_fd));
while(1)
{
bzero(buffer, 1024);
@@ -6096,97 +6283,108 @@
buffer[i] = buffer[i]-32;
}
}
- printf("buffer is %s\n",buffer);
- argc = lynqParseUsbCommand(buffer,argv,tempbuf,buf_parser,MAX_ARGS);
- if(argc<0)
- {
- bzero(eBuf, 1024);
- sprintf(eBuf,"LYNQ:%s not support!!!\n",buffer);
- int n = write(ttyGS3_fd,eBuf,strlen(eBuf));
- if(n<0)
- {
- perror("lynq resp write:");
- }
- printf("n = %d\n",n);
- continue;
- }
- usb_at_transfer_t *atCmd = lynqFindId(argv[0]);
- if(atCmd==NULL)
+ RLOGD("buffer is %s\n",buffer);
+ /*lei add*/
+ /*check third cmd in buffer*/
+ if(lynq_inside_at_buffer(buffer))
{
- RLOGD("LYNQ send ATCMD:%s!!!",argv[1]);
- lynqSendAt(argc,argv,1010);
- continue;
+ lynq_send_info(buffer, nread, (struct sockaddr*)&addr_clie);
}
- if(!((1<<atoi(argv[2])) & (atCmd->support)))
+ /*lei add*/
+ else
{
- RLOGD("LYNQ %s not support!!!",atCmd->cmdName);
- int n = write(ttyGS3_fd,"\n+CME ERROR: 100\n",strlen("\n+CME ERROR: 100\n"));
+ argc = lynqParseUsbCommand(buffer,argv,tempbuf,buf_parser,MAX_ARGS);
+ if(argc<0)
+ {
+ bzero(eBuf, 1024);
+ sprintf(eBuf,"LYNQ:%s not support!!!\n",buffer);
+ int n = write(ttyGS3_fd,eBuf,strlen(eBuf));
if(n<0)
{
perror("lynq resp write:");
}
+ RLOGD("n = %d\n",n);
continue;
- }
- routeId = routeCmd(atCmd->cmdId);
- //routeId = routeCmd(atcmd->cmdId);
- //routeId = LYNQ_GOTO_AT;
- switch(routeId)
- {
- case LYNQ_GOTO_AT:
+ }
+ usb_at_transfer_t *atCmd = lynqFindId(argv[0]);
+ if(atCmd==NULL)
{
+ RLOGD("LYNQ send ATCMD:%s!!!",argv[1]);
lynqSendAt(argc,argv,1010);
- break;
+ continue;
}
- case LYNQ_GOTO_TELE_REQ:
+ if(!((1<<atoi(argv[2])) & (atCmd->support)))
{
- usb_cmd_t *atCmdEvn = lynqFindUsbEvent(argv[0]);
- if(!atCmdEvn)
+ RLOGD("LYNQ %s not support!!!",atCmd->cmdName);
+ int n = write(ttyGS3_fd,"\n+CME ERROR: 100\n",strlen("\n+CME ERROR: 100\n"));
+ if(n<0)
{
- RLOGD("can not find at cmd event!!!");
- continue;
+ perror("lynq resp write:");
}
- atCmdEvn->fun(argc,argv,atCmdEvn->rilRequest,1011);
- break;
+ continue;
}
- case LYNQ_GOTO_USER_REQ:
+ routeId = routeCmd(atCmd->cmdId);
+ //routeId = routeCmd(atcmd->cmdId);
+ //routeId = LYNQ_GOTO_AT;
+ switch(routeId)
{
- usb_cmd_t *atCmdEvn = lynqFindUsbEvent(argv[0]);
- if(!atCmdEvn)
+ case LYNQ_GOTO_AT:
{
- RLOGD("can not find at cmd event!!!");
- continue;
+ lynqSendAt(argc,argv,1010);
+ break;
}
- atCmdEvn->ufun(argc,argv,1012);
- break;
+ case LYNQ_GOTO_TELE_REQ:
+ {
+ usb_cmd_t *atCmdEvn = lynqFindUsbEvent(argv[0]);
+ if(!atCmdEvn)
+ {
+ RLOGD("can not find at cmd event!!!");
+ continue;
+ }
+ atCmdEvn->fun(argc,argv,atCmdEvn->rilRequest,1011);
+ break;
+ }
+ case LYNQ_GOTO_USER_REQ:
+ {
+ usb_cmd_t *atCmdEvn = lynqFindUsbEvent(argv[0]);
+ if(!atCmdEvn)
+ {
+ RLOGD("can not find at cmd event!!!");
+ continue;
+ }
+ atCmdEvn->ufun(argc,argv,1012);
+ break;
+ }
+ case LYNQ_GOTO_LINFO_REQ:
+ {
+ lynqInfo(argv);
+ break;
+ }
+ // case LYNQ_GOTO_PLAT_REQ:
+ // {
+ // lynq_deal_with_log_at(&argv[3]);
+ // break;
+ // }
+ case LYNQ_GOTO_RNDIS_REQ:
+ {
+ lynq_get_rndis_data(buffer);
+ break;
+ }
+ case LYNQ_GOTO_FACTORY:
+ {
+ lynq_get_factory_data(argc,argv);
+ break;
+ }
+ // case LYNQ_GOTO_FOTA:
+ // {
+ // lynq_atfota_test(argv);
+ // break;
+ // }
+ default:
+ break;
}
- case LYNQ_GOTO_LINFO_REQ:
- {
- lynqInfo(argv);
- break;
- }
- // case LYNQ_GOTO_PLAT_REQ:
- // {
- // lynq_deal_with_log_at(&argv[3]);
- // break;
- // }
- case LYNQ_GOTO_RNDIS_REQ:
- {
- lynq_get_rndis_data(buffer);
- break;
- }
- case LYNQ_GOTO_FACTORY:
- {
- lynq_get_factory_data(argc,argv);
- break;
- }
- // case LYNQ_GOTO_FOTA:
- // {
- // lynq_atfota_test(argv);
- // break;
- // }
- default:
- break;
}
+
}
}
close(ttyGS3_fd);
@@ -6231,6 +6429,8 @@
return NULL;
}
+
+
const int RspDispFunction(int request,char* arg, RIL_SOCKET_ID socket_id)
{
int waittoken;
diff --git a/src/lynq/lib/liblynq-at-extension/LICENSE b/src/lynq/lib/liblynq-at-extension/LICENSE
new file mode 100755
index 0000000..77f59ed
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-extension/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek 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.
diff --git a/src/lynq/lib/liblynq-at-extension/include/lib_at/lynq_at.h b/src/lynq/lib/liblynq-at-extension/include/lib_at/lynq_at.h
new file mode 100755
index 0000000..1a17fe9
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-extension/include/lib_at/lynq_at.h
@@ -0,0 +1,38 @@
+
+/*=============================================================================
+# FileName: lynq_at.h
+# Desc: about AT_EXTENSION_API
+# Author:lei
+# Version: V1.0
+# LastChange: 2022-03-28
+# History:
+=============================================================================*/
+
+#ifndef __LYNQ_AT__
+#define __LYNQ_AT__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief
+ * @param input type:in
+ * @param output type:out
+ * @param out_max_size type:in
+ */
+typedef void (*LYNQ_AT_CALLBACK)(char input[], char output[], int out_max_size);
+
+/**
+ * @brief Register the AT command to the server and print the function execution finger on the AT port
+ *
+ * @param ext_at type:in at command
+ * @param callback type:in callback
+ * @return int
+ */
+int lynq_reg_third_at(const char *ext_at, LYNQ_AT_CALLBACK callback);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/src/lynq/lib/liblynq-at-extension/lynq_at.cpp b/src/lynq/lib/liblynq-at-extension/lynq_at.cpp
new file mode 100755
index 0000000..7440c99
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-extension/lynq_at.cpp
@@ -0,0 +1,88 @@
+#include<sys/types.h>
+#include<sys/socket.h>
+#include<unistd.h>
+#include<arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <log/log.h>
+#include "liblog/lynq_deflog.h"
+#include "include/lib_at/lynq_at.h"
+
+#define LYNQ_AT_SERVICE_PORT 8087
+#define OUT_MAX_SIZE 1024
+#define USER_LOG_TAG "LYNQ_AT"
+
+int sockfd = 0;
+char *output = NULL;
+struct sockaddr_in addr_serv;
+socklen_t len;
+
+/**
+ * @brief type:in send third at cmd to service
+ * @param ext_at type:in input at cmd
+ * @param callback type:in
+ * @return int
+ */
+int lynq_reg_third_at(const char *ext_at, LYNQ_AT_CALLBACK callback)
+{
+ LYDBGLOG("lynq_reg_third_at start\n");
+ sockfd=socket(AF_INET,SOCK_DGRAM,0);
+ memset(&addr_serv, 0, sizeof(addr_serv));
+ addr_serv.sin_family =AF_INET;
+ addr_serv.sin_port =htons(LYNQ_AT_SERVICE_PORT);
+ addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
+ len=sizeof(addr_serv);
+ int len_buf = strlen(ext_at);
+ int send = sendto(sockfd, ext_at, len_buf,0,(struct sockaddr*)&addr_serv,len);
+ if(send < 0)
+ {
+ LYDBGLOG("send fail\n");
+ return -1;
+ }
+ char *input = NULL;
+ output = (char *)malloc(sizeof(char)*OUT_MAX_SIZE);
+ if(NULL == output)
+ {
+ LYDBGLOG("malloc fail\n");
+ return -1;
+ }
+ while (1)
+ {
+ /*receive at cmd*/
+ LYDBGLOG("lynq_reg_third_at receive at cmd\n");
+ char at_cmd[100] = {0};
+ int recv = recvfrom(sockfd,at_cmd,sizeof(at_cmd),0,(struct sockaddr*)&addr_serv,&len);
+ if(recv < 0)
+ {
+ LYDBGLOG("recv fail\n");
+ return -1;
+ }
+ input = at_cmd;
+ callback(input, output, OUT_MAX_SIZE);
+ if(NULL == output)
+ {
+ LYDBGLOG("output = null\n");
+ return -1;
+ }
+ LYDBGLOG("lynq_reg_third_at send output to service\n");
+ int send = sendto(sockfd, output, strlen(output),0,(struct sockaddr*)&addr_serv,len);
+ if(send < 0)
+ {
+ LYDBGLOG("send fail\n");
+ continue;
+ }
+ }
+ if(output != NULL)
+ {
+ free(output);
+ output = NULL;
+ }
+ if(sockfd != 0)
+ {
+ close(sockfd);
+ }
+ return 0;
+}
+
diff --git a/src/lynq/lib/liblynq-at-extension/makefile b/src/lynq/lib/liblynq-at-extension/makefile
new file mode 100755
index 0000000..0a6c2d3
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-extension/makefile
@@ -0,0 +1,67 @@
+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 demo ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I$(LOCAL_PATH)/include/lib_at \
+ -I$(ROOT)$(includedir)/logger \
+ -I$(ROOT)$(includedir)/liblog \
+
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lstdc++ \
+ -llog \
+ -lpthread \
+ -llynq-log \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-at-extension.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/src/lynq/packages/apps/lynq-at-extension/src/main.cpp b/src/lynq/packages/apps/lynq-at-extension/src/main.cpp
new file mode 100755
index 0000000..ea86119
--- /dev/null
+++ b/src/lynq/packages/apps/lynq-at-extension/src/main.cpp
@@ -0,0 +1,45 @@
+
+#include <stdio.h>
+#include <lib_at/lynq_at.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * @brief callback
+ *
+ * @param input type:in
+ * @param output type:out
+ * @param out_max_size type:in
+ */
+void lynq_test_example(char input[], char output[], int out_max_size)
+{
+ if(!strcmp(input, "AT+TEST1"))
+ {
+ memcpy(output, input, strlen(input));
+ }
+ else if(!strcmp(input, "AT+TEST2"))
+ {
+ memcpy(output, input, strlen(input));
+ }
+ else if(!strcmp(input, "AT+TEST3"))
+ {
+ memcpy(output, input, strlen(input));
+ }
+ else if(!strcmp(input, "AT+TEST4"))
+ {
+ memcpy(output, input, strlen(input));
+ }
+ else if(!strcmp(input, "AT+TEST5"))
+ {
+ memcpy(output, input, strlen(input));
+ }
+ return;
+}
+
+int main(void)
+{
+ /*regis third at cmd*/
+ char cmd[64] = "AT+TEST1;AT+TEST2;AT+TEST3;AT+TEST4;AT+TEST5";
+ lynq_reg_third_at(cmd, lynq_test_example);//syn
+ return 0;
+}
diff --git a/src/lynq/packages/apps/lynq-at-extension/src/makefile b/src/lynq/packages/apps/lynq-at-extension/src/makefile
new file mode 100755
index 0000000..1eef0fa
--- /dev/null
+++ b/src/lynq/packages/apps/lynq-at-extension/src/makefile
@@ -0,0 +1,79 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -g -Os \
+ -flto \
+ -DRIL_SHLIB \
+ -DATCI_PARSE \
+ -DKEEP_ALIVE \
+ -D__LINUX_OS__ \
+ -DECALL_SUPPORT
+
+$(warning ################# C2K support: $(RAT_CONFIG_C2K_SUPPORT))
+ifeq ($(strip $(RAT_CONFIG_C2K_SUPPORT)), yes)
+ LOCAL_CFLAGS += -DC2K_SUPPORT
+
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsds)
+ LOCAL_CFLAGS += -DANDROID_SIM_COUNT_2 \
+ -DANDROID_MULTI_SIM \
+ -DMODE_DSDS
+endif
+
+ifeq ($(strip $(MTK_MULTI_SIM_SUPPORT)), dsss)
+ LOCAL_CFLAGS += -DMODE_DSSS
+endif
+
+$(warning ################# TARGET_PLATFORM: $(TARGET_PLATFORM))
+ifeq ($(strip $(TARGET_PLATFORM)), mt2731)
+#$(warning #################add for debug $(ROOT), $(includedir))
+$(warning ################# TARGET_PLATFORM_MT2731)
+ LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2731 \
+ -DMD_93_SUPPORT
+else ifeq ($(strip $(TARGET_PLATFORM)), mt2635)
+$(warning ################# TARGET_PLATFORM_MT2635)
+ LOCAL_CFLAGS += -DTARGET_PLATFORM_MT2635 \
+ -DMD_90_SUPPORT
+endif
+
+
+LOCAL_PATH = .
+#CFLAGS = $(LOCAL_CFLAGS) -std=c99
+#CXXFLAGS = $(LOCAL_CFLAGS) -std=gnu++14
+$(warning ################# ZHOUQUNCHAO ROOT: $(ROOT),includedir:$(includedir),LOCAL_PATH:$(LOCAL_PATH))
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I$(LOCAL_PATH) \
+ -I$(ROOT)$(includedir)/ \
+ -I$(ROOT)$(includedir)/include \
+ -DLIB_GNSS_HAL_DIR='"$(libdir)"'
+
+LOCAL_C_INCLUDES+=$(DNS_FLAGS)
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lstdc++ \
+ -llynq-at-extension \
+
+LOCAL_SRC_FILES_CPP = $(wildcard *.cpp)
+LOCAL_SRC_FILES_C = $(wildcard *.c)
+EXECUTABLE = lynq-at-extension
+
+OBJECTS=$(LOCAL_SRC_FILES_CPP:.cpp=.o) $(LOCAL_SRC_FILES_C:.c=.o)
+all: $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) $(OBJECTS) $(LOCAL_LIBS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o: %.c
+ $(warning ----->build $<)
+ $(CC) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+%.o : %.cpp
+ $(CXX) $(LOCAL_C_INCLUDES) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+.PHONY: clean
+clean:
+ $(RM) $(OBJECTS) $(EXECUTABLE)