[Feature][ZXW-112][ATCID] add framework of at plugins
Only Configure:No
Affected branch:master
Affected module:atcid
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No
Change-Id: I92d42fef70696655e352aabf9509eddcdb4f14dc
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
index 8d07dc3..29985f1 100755
--- a/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
+++ b/cap/zx297520v3/sources/meta-zxic-custom/conf/distro/vehicle_dc_ref.conf
@@ -269,6 +269,7 @@
lynq-qser-sms-demo \
lynq-qser-data-demo \
lynq-autosuspend \
+ lynq-atcid \
"
zxic_app_open += "${@bb.utils.contains('CONFIG_TEL_API_SUPPORT', 'RIL', 'rild', '', d)}"
diff --git a/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-atcid/lynq-atcid.bb b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-atcid/lynq-atcid.bb
new file mode 100755
index 0000000..fba6060
--- /dev/null
+++ b/cap/zx297520v3/sources/meta-zxic-custom/recipes-lynq/lynq-atcid/lynq-atcid.bb
@@ -0,0 +1,50 @@
+#inherit externalsrc package
+#inherit externalsrc package systemd
+DESCRIPTION = "lynq atcid"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b1e07e8d88e26263e71d3a9e2aa9a2ff"
+DEPENDS += "libxml2 libatreg libsoftap libatutils libnvram libsclog libsofttimer libbinder liblynq-log"
+#inherit workonsrc
+WORKONSRC = "${TOPDIR}/../src/lynq/framework/lynq-atcid"
+FILESEXTRAPATHS_prepend :="${TOPDIR}/../src/lynq/framework/:"
+SRC_URI = " \
+ file://lynq-atcid \
+ "
+
+SRC-DIR = "${S}/../lynq-atcid"
+TARGET_CC_ARCH += "${LDFLAGS}"
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE_${PN} = "lynq_atcid.service"
+FILES_${PN} += "${systemd_unitdir}/system/lynq_atcid.service"
+FILES_${PN} += "${bindir} /data/atsvc"
+#Parameters passed to do_compile()
+
+EXTRA_OEMAKE = "'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 -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -mhard-float"
+ else
+ oe_runmake all -C ${SRC-DIR} ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST}"
+ fi
+}
+
+do_install() {
+ install -d ${D}${bindir}/
+ install -m 0755 ${SRC-DIR}/lynq-atcid ${D}${bindir}/
+ if test "${LYNQ_ATSVC_SUPPORT}" = "yes"; then
+ install -d ${D}/data/atsvc
+ install -m 644 ${WORKONSRC}/lynq_atsvc_plugin.xml ${D}/data/atsvc
+ fi
+
+ if ${@bb.utils.contains('DISTRO_FEATURES','systemd','true','false',d)}; then
+ install -d ${D}${systemd_unitdir}/system/
+ install -m 0644 ${B}/lynq_atcid.service ${D}${systemd_unitdir}/system
+ else
+ install -d ${D}${sysconfdir}/init.d
+ install -m 0755 ${SRC-DIR}/lynq-atcid.sh ${D}${sysconfdir}/init.d/lynq-atcid.sh
+ install -d ${D}${sysconfdir}/rcS.d
+ ln -s ../init.d/lynq-atcid.sh ${D}${sysconfdir}/rcS.d/S83lynq-atcid
+ fi
+}
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/LICENSE b/cap/zx297520v3/src/lynq/framework/lynq-atcid/LICENSE
new file mode 100755
index 0000000..605b7ea
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/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/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq-atcid.sh b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq-atcid.sh
new file mode 100755
index 0000000..ff91ada
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq-atcid.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# Run the daemon
+#
+
+DAEMON="lynq-atcid"
+PIDFILE="/var/run/$DAEMON.pid"
+EXEC="/usr/bin/lynq-atcid"
+EXEC_ARGS=""
+
+
+start() {
+ echo -n "Starting $DAEMON... "
+ start-stop-daemon --no-close -S -b -m -p $PIDFILE -x $EXEC -- $EXEC_ARGS
+ [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+}
+
+stop() {
+ echo -n "Stopping $DAEMON... "
+ start-stop-daemon -K -p $PIDFILE
+ [ $? -eq 0 ] && echo "OK" || echo "ERROR"
+}
+
+restart() {
+ stop
+ start
+}
+
+case "$1" in
+ start|stop|restart)
+ "$1"
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart}"
+ exit 1
+esac
+
+exit $?
+
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atcid.service b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atcid.service
new file mode 100755
index 0000000..5734cd2
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atcid.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=lynq atcid
+After=at_ctl.service
+Requires=at_ctl.service
+
+[Service]
+StandardOutput=kmsg+console
+Type=simple
+RemainAfterExit=no
+ExecStart=/usr/bin/lynq-atcid
+Restart=always
+RestartSec=500ms
+StartLimitInterval=0
+User=root
+Group=root
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.cpp b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.cpp
new file mode 100755
index 0000000..9776c62
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.cpp
@@ -0,0 +1,171 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include "lynq_atsvc_controller.h"
+#include "liblog/lynq_deflog.h"
+
+#define FUNC __FUNCTION__
+#define LINE __LINE__
+
+typedef enum
+{
+ INIT_SUCCESS=0,
+ INIT_PULGIN_FAIL,
+ INIT_SOCKET_FAIL,
+ INIT_THREAD_FAIL
+}init_reuslt_t;
+
+typedef struct
+{
+ xmlChar* name;
+ xmlChar* reg;
+ xmlChar* cmd;
+}plugin_conf_t;
+
+void upper_string(char *org_string)
+{
+ int len = strlen(org_string);
+ for(int i=0;i<len;i++)
+ {
+ if(org_string[i]>=97 && org_string[i]<=122)
+ {
+ org_string[i]=org_string[i]-32;
+ }
+ }
+ return;
+}
+
+int load_pulgin(const char * plugin_conf_path)
+{
+ ALOGD("[%d][%s]load pulgin",LINE,FUNC);
+ int count = 0;
+ char *atcmd = NULL;
+ int atcmd_len = 0;
+ xmlDocPtr pdoc = NULL;
+ xmlNodePtr root = NULL;
+ plugin_conf_t plugin_conf;
+ //memset(plugin_msg_array,0,sizeof(plugin_msg_array));
+ pdoc = xmlReadFile(plugin_conf_path ,"UTF-8",XML_PARSE_RECOVER);
+ if(NULL == pdoc)
+ {
+ ALOGI("[%d][%s]copy file %s" ,LINE,FUNC, plugin_conf_path);
+ system("cp -r /data/atsvc /mnt/userdata/");
+ pdoc = xmlReadFile(plugin_conf_path ,"UTF-8",XML_PARSE_RECOVER);
+ if (NULL == pdoc)
+ {
+ ALOGE("[%d][%s]open file %s" ,LINE,FUNC, plugin_conf_path);
+ return -1;
+ }
+ }
+ root = xmlDocGetRootElement(pdoc);
+ if(NULL == root)
+ {
+ ALOGE("get xmlDocGetRootElement() empty document fail");
+ return -1;
+ }
+ ALOGD("root->name :%s",root->name);
+ root = root->xmlChildrenNode;
+ while (root != NULL)
+ {
+ ALOGD("count is:%d",count);
+ if(PLUGINE_MAX_COUNT <= count)
+ {
+ ALOGW("plugin too many!!!");
+ break;
+ }
+ if ((!xmlStrcmp(root->name, (const xmlChar *)"module")))
+ {
+ ALOGD("find module");
+ plugin_conf.name = xmlGetProp(root, "name");
+ plugin_conf.reg = xmlGetProp(root, "register");
+ plugin_conf.cmd = xmlGetProp(root, "cmd");
+ if((NULL == plugin_conf.name)||(NULL == plugin_conf.reg)||(NULL == plugin_conf.cmd))
+ {
+ ALOGE("get prop fail,name:%s,reg:%s,cmd=%s",plugin_conf.name,plugin_conf.reg,plugin_conf.cmd);
+ root = root->next;
+ continue;
+ }
+ ALOGD("[%d][%s]plugin_conf name:%s,reg:%s,cmd=%s",LINE,FUNC,plugin_conf.name,plugin_conf.reg,plugin_conf.cmd);
+ plugin_msg_array[count].dlHandle_plugin = dlopen(plugin_conf.name, RTLD_NOW);
+ if(NULL == plugin_msg_array[count].dlHandle_plugin)
+ {
+ ALOGE("open lib %s fail",plugin_conf.name);
+ root = root->next;
+ continue;
+ }
+ ALOGD("plugin_msg_array[%d].dlHandle_plugin :%p",count,plugin_msg_array[count].dlHandle_plugin);
+ plugin_msg_array[count].register_module = (lynq_atsvc_incb(*)(lynq_atsvc_outcb out_cb))dlsym(plugin_msg_array[count].dlHandle_plugin, plugin_conf.reg);
+ if(NULL == plugin_msg_array[count].register_module)
+ {
+ ALOGE("open plugin_msg_array[%d].%p fail",count,plugin_msg_array[count].register_module);
+ ALOGE("dlsym failed: %s", dlerror());
+ root = root->next;
+ continue;
+ }
+ plugin_msg_array[count].atsvc_incb = plugin_msg_array[count].register_module(plugin_msg_array[count].plugin_cb);
+ if(NULL == plugin_msg_array[count].atsvc_incb)
+ {
+ ALOGE("call %s fail",plugin_conf.reg);
+ root = root->next;
+ continue;
+ }
+ atcmd_len = strlen(plugin_conf.cmd);
+ atcmd = (char *)malloc(atcmd_len*(sizeof(char)+1));
+ if(NULL == atcmd)
+ {
+ ALOGE("count %d atcmd malloc fail",count);
+ root = root->next;
+ continue;
+ }
+ plugin_msg_array[count].state = 1;
+ memcpy(atcmd,plugin_conf.cmd,atcmd_len);
+ atcmd[atcmd_len] = '\0';
+ //plugin_msg_array[count].atcmd = atcmd;
+ upper_string(atcmd);
+ plugin_msg_array[count].atcmd = atcmd;
+ count++;
+ }
+ root = root->next;
+ }
+ ALOGD("pcurnode->name return");
+ xmlFreeDoc(pdoc);
+ xmlCleanupParser();
+ return 0;
+}
+
+int lynq_atsvc_init(int count,const char * plugin_conf_path)
+{
+ ALOGD("start [%d][%s]",LINE,FUNC);
+ int res = 0;
+ res = load_pulgin(PLUGIN_CONF_PATH);
+ if(0 > res)
+ {
+ for(int i = 0;i < PLUGINE_MAX_COUNT; i++)
+ {
+ if(NULL != plugin_msg_array[i].atcmd)
+ {
+ free(plugin_msg_array[i].atcmd);
+ }
+ }
+ ALOGE("load_pulgin fail,code is %d",res);
+ return INIT_PULGIN_FAIL;
+ }
+ for(int i = 0;i < PLUGINE_MAX_COUNT; i++)
+ {
+ if(NULL != plugin_msg_array[i].atcmd)
+ {
+ ALOGD("atcmd:%s",plugin_msg_array[i].atcmd);
+ }
+ }
+ //todo at liblynq-at-extension
+ /*create thread for reacive ril msg*/
+ /*load pulgin from plugin config*/
+ return 0;
+}
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.h b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.h
new file mode 100755
index 0000000..1db3571
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_controller.h
@@ -0,0 +1,87 @@
+/**********************************************************************************************
+* @file lynq_atsvc_controller.h
+* @brief Control the initialization of lynq at, and dispacthing, etc.
+* @details None
+* @author Hong Liu。
+* @date 2022-11-24
+* @version V1.0
+* @copyright Copyright (c) MobileTek
+***********************************************************************************************/
+
+
+#ifndef LYNQ_ATSVC_COBTROLLER_H
+#define LYNQ_ATSVC_COBTROLLER_H 1
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <pthread.h>
+#define PLUGIN_CONF_PATH "/mnt/userdata/atsvc/lynq_atsvc_plugin.xml"
+#define RIL_SOCKET_NAME "/dev/socket/lynq_atsvc_socket_1"
+#define PLUGINE_MAX_COUNT 16
+
+
+
+/**********************************************************************************************
+* @brief this is a callback function,atsvc will call this function if the at command is this \
+**module command
+* @param input [IN] at command
+* @param length [IN] at command length
+* @return NULL
+************************************************************************************************/
+typedef void ( *lynq_atsvc_incb )(const char *input,const int length);
+
+/**********************************************************************************************
+* @brief this is a callback function,plugin will call this function when the plugin needs to \
+**return the response or urc
+* @param input [IN] response or urc
+* @param length [IN] response or urc length
+* @param type
+** 0:response
+** 1:unsolictedresponse
+* @return NULL
+************************************************************************************************/
+typedef void ( *lynq_atsvc_outcb )(char *output,int out_size,int type);
+
+/**********************************************************************************************
+* @brief this is a register function, atsvc will call this function when a plugin register in atsvc.
+* @param lynq_atsvc_outcb [IN]
+* @return lynq_atsvc_incb
+************************************************************************************************/
+typedef lynq_atsvc_incb (*lynq_register_module)(lynq_atsvc_outcb out_cb);
+
+
+typedef struct
+{
+ lynq_atsvc_incb atsvc_incb;
+ lynq_register_module register_module;
+ void *dlHandle_plugin;
+ char * atcmd;
+ int state;
+ lynq_atsvc_outcb plugin_cb;
+ char * output_buffer;
+}plugin_msg_t;
+
+extern plugin_msg_t plugin_msg_array[PLUGINE_MAX_COUNT];
+extern int has_registe_cmd;
+/**********************************************************************************************
+* @brief initalize lynq atsvc,it will load plugin and create socket process
+* @param plugin_conf_path [IN] plugin config file path
+* @return
+* 0:success
+* 1:load pugin config file fail
+* 2:create socket fail
+* 3:create thread fail
+************************************************************************************************/
+int lynq_atsvc_init(int count,const char * plugin_conf_path);
+int lynq_check_extension_atcmd(char * atcmd);
+int send_msg_to_at_extension(char *atcmd,int size);
+int create_socket(const int domain, const int type, const int protocol,const int port,const char *IP,const char *socket_name,void * addr,int backlog);
+int send_msg(int socket_fd,const struct sockaddr *dest_addr,const char *msg);
+int lynq_dispatch_atcmd(char* atcmd);
+
+
+
+#endif
+
+
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_plugin.xml b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_plugin.xml
new file mode 100755
index 0000000..3cdb250
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/lynq_atsvc_plugin.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lynq_atsvc_plugin >
+ <module name="/lib64/liblynq-test-data.so"
+ register="lynq_register_test_data"
+ cmd="AT+LETEST;AT+LEABC;AT+LEDEF"
+ />
+ <module name="/lib64/liblynq-gnss.so"
+ register="lynq_register_gnss"
+ cmd="AT+CGPS;AT+CGPSNMEA"
+ />
+ <module name="/lib64/liblynq-at-common.so"
+ register="lynq_register_at_common"
+ cmd="AT+MNETCALL;AT+GTARNDIS;AT+CGIR;AT+LGMDS;AT+LRNDISHANDLE"
+ />
+ <module name="/lib64/liblynq-at-factory.so"
+ register="lynq_register_at_factory"
+ cmd="AT+LYNQFACTORY"
+ />
+</lynq_atsvc_plugin>
\ No newline at end of file
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/main.cpp b/cap/zx297520v3/src/lynq/framework/lynq-atcid/main.cpp
new file mode 100755
index 0000000..5bec9af
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/main.cpp
@@ -0,0 +1,41 @@
+/*
+* Copyright (C) 2014 MediaTek Inc.
+*
+* Modification based on code covered by the below mentioned copyright
+* and/or permission notice(s).
+*/
+
+/*
+**
+** Copyright 2006 The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include "zxic_at_func_wrapper.h"
+#include "liblog/lynq_deflog.h"
+
+int main(int argc, char **argv) {
+ ALOGI("atcid started");
+ init_zxic_at_plugin_env();
+
+ while (true) {
+ sleep(5);
+ }
+}
+
+DEFINE_LYNQ_EXE_LOG(LYNQ_ATCID)
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/makefile b/cap/zx297520v3/src/lynq/framework/lynq-atcid/makefile
new file mode 100755
index 0000000..fa4f4ad
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/makefile
@@ -0,0 +1,76 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -std=gnu++14 \
+ -pthread \
+ -g -Os \
+ -flto \
+ -fPIC \
+ -fpermissive \
+
+ifeq ($(strip $(TARGET_PLATFORM)), T106)
+LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1 -DHAVE_ENDIAN_H -DHAVE_PTHREADS -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP -DHAVE_STRLCPY -DHAVE_PRCTL -DHAVE_MEMSET16 -DHAVE_MEMSET32 -DANDROID_SMP=0
+endif
+
+$(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)/libxml2 \
+
+
+LOCAL_LIBS := \
+ -L. \
+ -lstdc++ \
+ -ldl \
+ -lcutils \
+ -lutils \
+ -lpthread \
+ -lxml2 \
+ -latreg \
+ -lsoftap \
+ -latutils \
+ -lnvram \
+ -lsclog \
+ -lsofttimer \
+ -lbinder \
+ -llynq-log \
+
+
+SOURCES = $(wildcard *.c wildcard *.h *.cpp)
+
+EXECUTABLE = lynq-atcid
+
+OBJECTS=$(SOURCES:.cpp=.o)
+
+
+.PHONY: build clean install pack_rootfs
+all: build
+$(EXECUTABLE): $(OBJECTS)
+ $(CXX) $(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/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.cpp b/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.cpp
new file mode 100755
index 0000000..3037e62
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.cpp
@@ -0,0 +1,232 @@
+#include "zxic_at_func_wrapper.h"
+#include <string.h>
+#include <stdio.h>
+#include "lynq_atsvc_controller.h"
+#include "liblog/lynq_deflog.h"
+
+extern "C"
+{
+ typedef void (*ZXIC_AT_CALLBACK_FUNC_PTR) (unsigned char *, unsigned char *);
+
+ extern int reg_at_serv_func(char *at_cmd_prefix, ZXIC_AT_CALLBACK_FUNC_PTR cb);
+ extern int unreg_at_serv_func(char *at_cmd_prefix);
+}
+
+struct callback_entry
+{
+ char at_prefix[64];
+ ZXIC_AT_CALLBACK_FUNC_PTR callback_func;
+ plugin_msg_t *plugin_entry;
+};
+
+const int entry_count = 256;
+static volatile int g_zxic_at_plugin_env_flag = 0;
+static struct callback_entry *g_all_reg_entry[entry_count] = {0};
+static int g_curr_reg_index = 0;
+
+plugin_msg_t plugin_msg_array[PLUGINE_MAX_COUNT] = {0};
+
+template <int n>
+void zxic_at_callback(unsigned char * input, unsigned char * output)
+{
+ char org_cmd[64] = {0};
+ if (input == NULL || output == NULL)
+ {
+ ALOGE("zxic_at_callback invalid params %p-%p \n", input, output);
+ return;
+ }
+ strcpy((char*)output, "\r\n");
+ struct callback_entry *pEntry = g_all_reg_entry[n];
+ strcat(org_cmd, pEntry->at_prefix);
+ strcat(org_cmd, (char *)input);
+ pEntry->plugin_entry->output_buffer = (char*)output;
+ ALOGD("zxic_at_callback org_cmd -- %s \n", org_cmd);
+ pEntry->plugin_entry->atsvc_incb(org_cmd, strlen(org_cmd));
+ pEntry->plugin_entry->output_buffer = NULL;
+ ALOGD("zxic_at_callback output -- %s \n", output);
+ //return 0;
+}
+
+template <int n>
+void reg_callback_function()
+{
+ g_all_reg_entry[n] = new struct callback_entry;
+ g_all_reg_entry[n]->callback_func = &zxic_at_callback<n>;
+ reg_callback_function<n-1>();
+}
+
+template <>
+void reg_callback_function<0>()
+{
+ g_all_reg_entry[0] = new struct callback_entry;
+ g_all_reg_entry[0]->callback_func = &zxic_at_callback<0>;
+}
+
+template <int n>
+void lynq_atsvc_outcb_entity(char *output,int out_size,int type)
+{
+ ALOGD("lynq_atsvc_outcb_entity%d called\n",n);
+ if (plugin_msg_array[n].output_buffer == NULL)
+ {
+ ALOGE("no output buffer");
+ return;
+ }
+ if(NULL == output)
+ {
+ ALOGE("output is null");
+ }
+ int length = 0;
+ length = strlen(output);
+ if(length != out_size)
+ {
+ ALOGW("strlen length != output");
+ }
+ ALOGD("ouput:%s,len:%d",output,out_size);
+
+ //not first line add \r\n
+ if (plugin_msg_array[n].output_buffer[0] != '\0')
+ {
+ strcat(plugin_msg_array[n].output_buffer, "\r\n");
+ }
+
+ strcat(plugin_msg_array[n].output_buffer, output);
+}
+
+template <int n>
+void reg_lynq_atsvc_outcb_entity()
+{
+ plugin_msg_array[n].plugin_cb = &lynq_atsvc_outcb_entity<n>;
+ plugin_msg_array[n].output_buffer = NULL;
+ reg_lynq_atsvc_outcb_entity<n-1>();
+}
+
+template <>
+void reg_lynq_atsvc_outcb_entity<0>()
+{
+ plugin_msg_array[0].plugin_cb = &lynq_atsvc_outcb_entity<0>;
+ plugin_msg_array[0].output_buffer = NULL;
+}
+
+static int lynq_split(char * str, int len, char delimiter, char * results[]) {
+ int ret = 0;
+ char * end = str + len - 1;
+ results[ret++] = str;
+ while(str < end)
+ {
+ if (*str == delimiter)
+ {
+ *str++ = '\0';
+ results[ret++] = str;
+ continue;
+ }
+ str++;
+ }
+ if (*str == delimiter)
+ {
+ *str = '\0';
+ }
+
+ results[ret] = NULL;
+
+ return ret;
+}
+
+static int local_reg_at_serv_func(char *at_cmd_prefix, ZXIC_AT_CALLBACK_FUNC_PTR cb) //@todo to check if registered
+{
+ int ret;
+ ret = reg_at_serv_func(at_cmd_prefix, cb);
+ ALOGD("reg_at_serv_func return:%d", ret);
+ if (ret == 0)
+ {
+ return 0;
+ }
+ unreg_at_serv_func(at_cmd_prefix);
+ return reg_at_serv_func(at_cmd_prefix, cb);
+}
+
+static int local_reg_one_at_cmd(const char* reg_fmt, char*reg_word, char * at_cmd, plugin_msg_t *plugin_entry)
+{
+ struct callback_entry *entry;
+ char reg_cmd[32] = {0};
+ entry = g_all_reg_entry[g_curr_reg_index];
+ snprintf(reg_cmd, sizeof (reg_cmd), reg_fmt, reg_word);
+ snprintf(entry->at_prefix, sizeof (entry->at_prefix), reg_fmt, at_cmd);
+ if (local_reg_at_serv_func(reg_cmd, g_all_reg_entry[g_curr_reg_index]->callback_func) == 0)
+ {
+ entry->plugin_entry = plugin_entry;
+ g_curr_reg_index++;
+ ALOGI("reg_at_serv_func [%s] success\n", reg_cmd);
+ }
+ else
+ {
+ ALOGE("reg_at_serv_func [%s] fail\n", reg_cmd);
+ }
+
+ return 0;
+}
+
+static int reg_at_cmd(char * at_cmd, plugin_msg_t *plugin_entry)
+{
+ int words_count;
+ char *split_words[64] = {0};
+ char cmd[32] = {0};
+
+ strcpy(cmd, at_cmd);
+ words_count = lynq_split(cmd, strlen(cmd), '+', split_words);
+ if (words_count != 2 || strlen(split_words[1]) == 0)
+ {
+ ALOGE("bad format command [%s]", cmd);
+ return -1;
+ }
+
+ ALOGD("reg_at_cmd [%s] begin", at_cmd);
+ local_reg_one_at_cmd("%s", split_words[1], at_cmd, plugin_entry);
+ local_reg_one_at_cmd("%s?", split_words[1], at_cmd, plugin_entry);
+ local_reg_one_at_cmd("%s=", split_words[1], at_cmd, plugin_entry);
+ local_reg_one_at_cmd("%s=?", split_words[1], at_cmd, plugin_entry);
+ ALOGD("reg_at_cmd [%s] end", at_cmd);
+
+ return 0;
+}
+
+static int reg_at_cmds_of_plugin(plugin_msg_t *plugin_entry)
+{
+ int cmds_count, i;
+ char *split_cmds[64] = {0};
+ char *cmd_buffer = new char[strlen(plugin_entry->atcmd)+1];
+ strcpy(cmd_buffer, plugin_entry->atcmd);
+
+ cmds_count = lynq_split(cmd_buffer, strlen(plugin_entry->atcmd), ';', split_cmds);
+
+ ALOGD("reg_at_cmds_of_plugin cmd count %d ,%s", cmds_count, cmd_buffer);
+ for(i=0;i<cmds_count;i++)
+ {
+ reg_at_cmd(split_cmds[i], plugin_entry) ;
+ }
+ delete [] cmd_buffer;
+ return 0;
+}
+
+int init_zxic_at_plugin_env()
+{
+ if (g_zxic_at_plugin_env_flag != 0)
+ return -1;
+ memset(plugin_msg_array,0,sizeof(plugin_msg_array));
+ reg_callback_function<entry_count-1>();
+ reg_lynq_atsvc_outcb_entity<PLUGINE_MAX_COUNT-1>();
+ g_zxic_at_plugin_env_flag = 1;
+
+ lynq_atsvc_init(0,NULL);
+
+ for(int i = 0;i < PLUGINE_MAX_COUNT; i++)
+ {
+ if(NULL != plugin_msg_array[i].atcmd)
+ {
+ ALOGD("atcmd:%s",plugin_msg_array[i].atcmd);
+ reg_at_cmds_of_plugin(&plugin_msg_array[i]);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.h b/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.h
new file mode 100755
index 0000000..fddfbd1
--- /dev/null
+++ b/cap/zx297520v3/src/lynq/framework/lynq-atcid/zxic_at_func_wrapper.h
@@ -0,0 +1,13 @@
+#ifndef ZXIC_AT_FUNC_WRAPPER_H
+#define ZXIC_AT_FUNC_WRAPPER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int init_zxic_at_plugin_env();
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ZXIC_AT_FUNC_WRAPPER_H