[Feature][T8TSK-139][AT]common at update
Change-Id: Ibe0eca6a324ba5cc8768375a3b1d1f5a830b2f1f
diff --git a/src/lynq/lib/liblynq-at-common/LICENSE b/src/lynq/lib/liblynq-at-common/LICENSE
new file mode 100755
index 0000000..382fc78
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/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/src/lynq/lib/liblynq-at-common/atci_at_util.cpp b/src/lynq/lib/liblynq-at-common/atci_at_util.cpp
new file mode 100755
index 0000000..4c215a7
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/atci_at_util.cpp
@@ -0,0 +1,171 @@
+#include <string.h>
+#include <stdlib.h>
+#include <log/log.h>
+#include "atci_at_util.h"
+
+#undef LOG_TAG
+#define LOG_TAG "AT_COMMON"
+
+int atci_at_skip_space(char **p_cur) {
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ while (**p_cur == ATCI_SPACE) {
+ (*p_cur)++;
+ }
+ return SYS_SUCC;
+}
+int atci_at_hasmore(char **p_cur) {
+ if (*p_cur == NULL || **p_cur == ATCI_END_CHAR) {
+ return SYS_FAIL;
+ }
+ return SYS_SUCC;
+}
+
+int atci_at_to_equal(char **p_cur) {
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ *p_cur = strchr(*p_cur, ATCI_EQUAL);
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ (*p_cur)++;
+ return SYS_SUCC;
+}
+int atci_at_to_colon(char **p_cur) {
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ *p_cur = strchr(*p_cur, ATCI_COLON);
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ (*p_cur)++;
+ return SYS_SUCC;
+}
+int atci_at_skip_next_comma(char **p_cur) {
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ *p_cur = strchr(*p_cur, ATCI_COMMA);
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ (*p_cur)++;
+ return SYS_SUCC;
+}
+int atci_at_get_next_key(char **p_cur, char **p_out) {
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ atci_at_skip_space(p_cur);
+ if (**p_cur == ATCI_DOUBLE_QUOTE) {
+ (*p_cur)++;
+ *p_out = strsep(p_cur, "\"");
+ atci_at_skip_next_comma(p_cur);
+ } else {
+ *p_out = strsep(p_cur, ",");
+ }
+ return SYS_SUCC;
+}
+
+/**
+ * Parses the next integer in the line and places it in *p_out
+ * "uns" is indicate in unsigned or not
+ * returns SYS_SUCC on success
+ * returns SYS_FAIL on fail
+ * updates *p_cur
+ * "base" is the same as the base param in strtol
+ */
+int atci_at_get_nextint_base(char **p_cur, int *p_out, int base, int uns) {
+ char *ret;
+ if (*p_cur == NULL) {
+ return SYS_FAIL;
+ }
+ if (SYS_FAIL == atci_at_get_next_key(p_cur, &ret)) {
+ return SYS_FAIL;
+ } else {
+ long l;
+ char *end;
+ if (uns) {
+ l = strtoul(ret, &end, base);
+ } else {
+ l = strtol(ret, &end, base);
+ }
+ *p_out = (int) l;
+ if (end == ret) {
+ return SYS_FAIL;
+ }
+ }
+ return SYS_SUCC;
+}
+int atci_at_get_nextint(char **p_cur, int *p_out) {
+ return atci_at_get_nextint_base(p_cur, p_out, 10, 0);
+}
+int atci_at_get_nexthexint(char **p_cur, int *p_out) {
+ return atci_at_get_nextint_base(p_cur, p_out, 16, 1);
+}
+int atci_get_cmd_mode(char *line) {
+ int reasult = AT_WRONG_MODE;
+ char *p_cur = NULL;
+ if (NULL == line) {
+ reasult = AT_WRONG_MODE;
+ RLOGD("atci_get_cmd_mode error, input is NULL");
+ return reasult;
+ }
+ p_cur = strchr(line, ATCI_EQUAL);
+ if (NULL == p_cur) {
+ p_cur = strchr(line, ATCI_QUESTION_MARK);
+ if (NULL == p_cur) {
+ reasult = AT_ACTIVE_MODE;
+ } else {
+ reasult = AT_READ_MODE;
+ }
+ } else {
+ p_cur++;
+ atci_at_skip_space(&p_cur);
+ if (ATCI_QUESTION_MARK == *p_cur) {
+ reasult = AT_TEST_MODE;
+ } else {
+ reasult = AT_SET_MODE;
+ }
+ }
+ RLOGD("atci_get_cmd_mode success[%d]", reasult);
+ return reasult;
+}
+
+char* atci_get_cmd_prefix(char *line) {
+ int buf_len;
+ char *prefix;
+ char *end_ptr;
+ if (NULL == line) {
+ RLOGD("input is null");
+ return NULL;
+ }
+ end_ptr = line;
+ while (!ATCI_IS_CAHR(*end_ptr, ATCI_EQUAL)
+ && !ATCI_IS_CAHR(*end_ptr, ATCI_QUESTION_MARK)
+ && !ATCI_IS_CAHR(*end_ptr, ATCI_END_CHAR)
+ && !ATCI_IS_CAHR(*end_ptr, ATCI_CR) && !ATCI_IS_CAHR(*end_ptr, ATCI_LF)) {
+ end_ptr++;
+ }
+ buf_len = end_ptr - line + 1;
+ prefix = (char *) calloc(buf_len, 1);
+ if (prefix) {
+ int i;
+ char *in_ptr = line;
+ char *out_ptr = prefix;
+ for (i = 0; i < buf_len - 1; i++) {
+ if (!ATCI_IS_CAHR(*in_ptr, ATCI_SPACE)) {
+ *out_ptr = ATCI_UPPER_TO_LOWER(*in_ptr);
+ out_ptr++;
+ }
+ in_ptr++;
+ }
+ *out_ptr = ATCI_END_CHAR;
+ }
+ RLOGD("get cmd prefix [%d][%s]", buf_len, prefix);
+ return prefix;
+}
+
diff --git a/src/lynq/lib/liblynq-at-common/atci_at_util.h b/src/lynq/lib/liblynq-at-common/atci_at_util.h
new file mode 100755
index 0000000..d84fd63
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/atci_at_util.h
@@ -0,0 +1,128 @@
+#ifndef _ATCI_AT_UTIL_H_
+#define _ATCI_AT_UTIL_H_
+
+#define SYS_SUCC 0
+#define SYS_FAIL -1
+
+typedef enum {
+ ATCI_SPACE = ' ',
+ ATCI_EQUAL = '=',
+ ATCI_COMMA = ',',
+ ATCI_SEMICOLON = ';',
+ ATCI_COLON = ':',
+ ATCI_AT = '@',
+ ATCI_HAT = '^',
+ ATCI_MONEY = '$',
+ ATCI_DOUBLE_QUOTE = '"',
+ ATCI_QUESTION_MARK = '?',
+ ATCI_EXCLAMATION_MARK = '!',
+ ATCI_FORWARD_SLASH = '/',
+ ATCI_L_ANGLE_BRACKET = '<',
+ ATCI_R_ANGLE_BRACKET = '>',
+ ATCI_R_BRACKET = ')',
+ ATCI_L_BRACKET = '(',
+ ATCI_L_SQ_BRACKET = '[',
+ ATCI_R_SQ_BRACKET = ']',
+ ATCI_L_CURLY_BRACKET = '{',
+ ATCI_R_CURLY_BRACKET = '}',
+ ATCI_CHAR_STAR = '*',
+ ATCI_CHAR_POUND = '#',
+ ATCI_CHAR_AMPSAND = '&',
+ ATCI_CHAR_PERCENT = '%',
+ ATCI_CHAR_PLUS = '+',
+ ATCI_CHAR_MINUS = '-',
+ ATCI_CHAR_DOT = '.',
+ ATCI_CHAR_ULINE = '_',
+ ATCI_CHAR_TILDE = '~',
+ ATCI_CHAR_REVERSE_SOLIDUS = '\\',
+ ATCI_CHAR_VERTICAL_LINE = '|',
+ ATCI_END_CHAR = '\0',
+ ATCI_CR = '\r',
+ ATCI_LF = '\n',
+ ATCI_CHAR_0 = '0',
+ ATCI_CHAR_1 = '1',
+ ATCI_CHAR_2 = '2',
+ ATCI_CHAR_3 = '3',
+ ATCI_CHAR_4 = '4',
+ ATCI_CHAR_5 = '5',
+ ATCI_CHAR_6 = '6',
+ ATCI_CHAR_7 = '7',
+ ATCI_CHAR_8 = '8',
+ ATCI_CHAR_9 = '9',
+ ATCI_CHAR_A = 'A',
+ ATCI_CHAR_B = 'B',
+ ATCI_CHAR_C = 'C',
+ ATCI_CHAR_D = 'D',
+ ATCI_CHAR_E = 'E',
+ ATCI_CHAR_F = 'F',
+ ATCI_CHAR_G = 'G',
+ ATCI_CHAR_H = 'H',
+ ATCI_CHAR_I = 'I',
+ ATCI_CHAR_J = 'J',
+ ATCI_CHAR_K = 'K',
+ ATCI_CHAR_L = 'L',
+ ATCI_CHAR_M = 'M',
+ ATCI_CHAR_N = 'N',
+ ATCI_CHAR_O = 'O',
+ ATCI_CHAR_P = 'P',
+ ATCI_CHAR_Q = 'Q',
+ ATCI_CHAR_R = 'R',
+ ATCI_CHAR_S = 'S',
+ ATCI_CHAR_T = 'T',
+ ATCI_CHAR_U = 'U',
+ ATCI_CHAR_V = 'V',
+ ATCI_CHAR_W = 'W',
+ ATCI_CHAR_X = 'X',
+ ATCI_CHAR_Y = 'Y',
+ ATCI_CHAR_Z = 'Z',
+ ATCI_CHAR_a = 'a',
+ ATCI_CHAR_b = 'b',
+ ATCI_CHAR_c = 'c',
+ ATCI_CHAR_d = 'd',
+ ATCI_CHAR_e = 'e',
+ ATCI_CHAR_f = 'f',
+ ATCI_CHAR_g = 'g',
+ ATCI_CHAR_h = 'h',
+ ATCI_CHAR_i = 'i',
+ ATCI_CHAR_j = 'j',
+ ATCI_CHAR_k = 'k',
+ ATCI_CHAR_l = 'l',
+ ATCI_CHAR_m = 'm',
+ ATCI_CHAR_n = 'n',
+ ATCI_CHAR_o = 'o',
+ ATCI_CHAR_p = 'p',
+ ATCI_CHAR_q = 'q',
+ ATCI_CHAR_r = 'r',
+ ATCI_CHAR_s = 's',
+ ATCI_CHAR_t = 't',
+ ATCI_CHAR_u = 'u',
+ ATCI_CHAR_v = 'v',
+ ATCI_CHAR_w = 'w',
+ ATCI_CHAR_x = 'x',
+ ATCI_CHAR_y = 'y',
+ ATCI_CHAR_z = 'z',
+} atci_char_enum;
+
+typedef enum {
+ AT_WRONG_MODE, AT_SET_MODE, //Ex: at+eample=xxx
+ AT_READ_MODE, //Ex: at+eample?
+ AT_TEST_MODE, //Ex: at+eample=?
+ AT_ACTIVE_MODE //Ex: at+eample
+} atci_cmd_mode_e;
+
+#define ATCI_LOWER_TO_UPPER(alpha_char) (((alpha_char >= ATCI_CHAR_a)&&(alpha_char <= ATCI_CHAR_z)) ? (alpha_char-32): (alpha_char))
+#define ATCI_UPPER_TO_LOWER(alpha_char) (((alpha_char >= ATCI_CHAR_A)&&(alpha_char <= ATCI_CHAR_Z)) ? (alpha_char+32): (alpha_char))
+#define ATCI_IS_CAHR(input ,alpha_char) ((alpha_char == input)? 1 : 0)
+
+char* atci_get_cmd_prefix(char *line);
+int atci_get_cmd_mode(char *line);
+int atci_at_skip_space(char **p_cur);
+int atci_at_hasmore(char **p_cur);
+int atci_at_to_equal(char **p_cur);
+int atci_at_to_colon(char **p_cur);
+int atci_at_skip_next_comma(char **p_cur);
+int atci_at_get_nextint_base(char **p_cur, int *p_out, int base, int uns);
+int atci_at_get_nextint(char **p_cur, int *p_out);
+int atci_at_get_nexthexint(char **p_cur, int *p_out);
+int atci_at_get_next_key(char **p_cur, char **p_out);
+#endif
diff --git a/src/lynq/lib/liblynq-at-common/include/libat_common/lynq_at_common.h b/src/lynq/lib/liblynq-at-common/include/libat_common/lynq_at_common.h
new file mode 100755
index 0000000..6f68e04
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/include/libat_common/lynq_at_common.h
@@ -0,0 +1,23 @@
+/*=============================================================================
+# FileName: lynq_at_factory.h
+# Desc: about at of factory
+# Author: lei
+# Version: V1.0
+# LastChange: 2022-12-14
+# History:
+ copyright:Mobiletek
+=============================================================================*/
+#ifndef LYNQ_AT_COMMON_H
+#define LYNQ_AT_COMMON_H 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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_at_common(lynq_atsvc_outcb out_cb);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/src/lynq/lib/liblynq-at-common/lynq_at_common.cpp b/src/lynq/lib/liblynq-at-common/lynq_at_common.cpp
new file mode 100755
index 0000000..6afe8cc
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/lynq_at_common.cpp
@@ -0,0 +1,319 @@
+
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <log/log.h>
+#include "include/libat_common/lynq_at_common.h"
+#include "atci_at_util.h"
+
+#undef LOG_TAG
+#define LOG_TAG "AT_COMMON"
+
+int g_mnetcall_mode = 0;
+int g_gtarndis_mode = 0;
+int g_version_mode = 0;
+
+lynq_atsvc_outcb handle_output;
+
+typedef struct
+{
+ char *cmd;
+ void (*func)(char *input,int mode);
+}Command;
+
+enum
+{
+ Response = 0,
+ Urc
+};
+
+void lynq_response_ok()
+{
+ char *str = "\r\nOK\r\n";
+ handle_output(str, strlen(str), Response);
+}
+
+void lynq_response_error()
+{
+ char *str = "\r\n+CME ERROR:100\r\n";
+ handle_output(str, strlen(str), Response);
+}
+
+static int lynq_catrndis_mode(void)
+{
+ FILE *fp;
+ char buf[2];
+ fp = popen("cat /data/rndis.conf","r");
+ fgets(buf,sizeof(buf),fp);
+ if(buf != NULL)
+ {
+ if(buf[0] == '0')
+ {
+ return 0;
+ }
+ if(buf[0] == '1')
+ {
+ return 1;
+ }
+ else
+ {
+ return 2;//not config
+ }
+ }
+ pclose(fp);
+ return;
+}
+
+static void lynq_get_poepn_buf(char *cmd)
+{
+ FILE *fp;
+ char buf[128] = {0};
+ fp = popen(cmd,"r");
+ while(fgets(buf, sizeof(buf), fp) != NULL){}
+ pclose(fp);
+ RLOGD("buf is %s size %d\n", buf, sizeof(buf));
+ handle_output(buf, strlen(buf), Response);
+ return;
+}
+
+void lynq_handle_rndis(char *input,int type)
+{
+ RLOGD("lynq_handle_rndis type %d\n", type);
+ char buf[128] = {0};
+ if(type == AT_SET_MODE)//set
+ {
+ int mode;
+ if (SYS_FAIL == atci_at_to_equal(&input))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if (SYS_FAIL == atci_at_get_nexthexint(&input, &mode))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if(mode == 1)
+ {
+ g_mnetcall_mode = mode;
+ system("connmanctl enable gadget");
+ system("connmanctl tether gadget on");
+ lynq_response_ok();
+ }
+ else if (mode == 0)
+ {
+ g_mnetcall_mode = mode;
+ system("connmanctl disable gadget");
+ lynq_response_ok();
+ }
+ else
+ {
+ lynq_response_error();
+ }
+ }
+ else if(type == AT_TEST_MODE)//list
+ {
+ sprintf(buf,"+MNETCALL:(0-1)");
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if(type == AT_READ_MODE)//get
+ {
+ sprintf(buf,"+MNETCALL:%d", g_mnetcall_mode);
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else
+ {
+ lynq_response_error();
+ }
+ return;
+}
+
+void lynq_handle_rndis_configure(char *input,int type)
+{
+ RLOGD("lynq_handle_rndis_configure type %d\n", type);
+ char buf[128] = {0};
+ if(type == AT_SET_MODE)//set
+ {
+ int mode;
+ if (SYS_FAIL == atci_at_to_equal(&input))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if (SYS_FAIL == atci_at_get_nexthexint(&input, &mode))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if(mode == 1)
+ {
+ g_gtarndis_mode = mode;
+ system("echo \"1\" > /data/rndis.conf");
+ lynq_response_ok();
+ }
+ else if (mode == 0)
+ {
+ g_gtarndis_mode = mode;
+ system("echo \"0\" > /data/rndis.conf");
+ lynq_response_ok();
+ }
+ else
+ {
+ lynq_response_error();
+ }
+ }
+ else if(type == AT_TEST_MODE)//list
+ {
+ sprintf(buf,"+GTARNDIS:(0-1)");
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if(type == AT_READ_MODE)//get
+ {
+ sprintf(buf,"+GTARNDIS:%d", g_gtarndis_mode);
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else
+ {
+ lynq_response_error();
+ }
+ return;
+}
+
+void lynq_handle_version(char *input,int type)
+{
+ RLOGD("lynq_handle_version type %d\n", type);
+ char buf[128] = {0};
+ if(type == AT_SET_MODE)//set
+ {
+ int mode;
+ if (SYS_FAIL == atci_at_to_equal(&input))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if (SYS_FAIL == atci_at_get_nexthexint(&input, &mode))
+ {
+ lynq_response_error();
+ return SYS_FAIL;
+ }
+ if(mode == 1)
+ {
+ g_version_mode = mode;
+ lynq_get_poepn_buf("uci get lynq_uci_ro.lynq_version.LYNQ_SW_INSIDE_VERSION");
+ //handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if (mode == 0)
+ {
+ g_version_mode = mode;
+ lynq_get_poepn_buf("uci get lynq_uci_ro.lynq_version.LYNQ_SW_VERSION");
+ //handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else
+ {
+ lynq_response_error();
+ }
+ }
+ else if(type == AT_TEST_MODE)//list
+ {
+ sprintf(buf,"+CGIR:(0-1)");
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if(type == AT_READ_MODE)//get
+ {
+ sprintf(buf,"+CGIR:%d", g_version_mode);
+ handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if(type == AT_ACTIVE_MODE)//active
+ {
+ if(g_version_mode == 0)
+ {
+ lynq_get_poepn_buf("uci get lynq_uci_ro.lynq_version.LYNQ_SW_VERSION");
+ //handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ else if(g_version_mode == 1)
+ {
+ lynq_get_poepn_buf("uci get lynq_uci_ro.lynq_version.LYNQ_SW_INSIDE_VERSION");
+ //handle_output(buf, strlen(buf), Response);
+ lynq_response_ok();
+ }
+ }
+ return;
+}
+
+static Command commands[] =
+{
+{"at+mnetcall",lynq_handle_rndis},
+{"at+gtarndis",lynq_handle_rndis_configure},
+{"at+cgir",lynq_handle_version},
+{NULL, NULL}
+};
+
+Command* find_command (char *input)
+{
+ RLOGD("function %s line %d input %s\n", __FUNCTION__, __LINE__, input);
+ int i;
+ int ret = -1;
+ for (i = 0; commands[i].cmd; i++)
+ {
+ ret = strcmp(input, commands[i].cmd);
+ if(ret == 0)
+ {
+ RLOGD("function %s line %d find input %s commands[i].cmd %s strlen %d ret %d\n", __FUNCTION__, __LINE__, input, commands[i].cmd, strlen(commands[i].cmd), ret);
+ return (&commands[i]);
+ }
+ }
+ RLOGD("function %s line %d not find ret %d \n", __FUNCTION__, __LINE__, ret);
+ return ((Command *)NULL);
+}
+
+void lynq_at_common_cb(char *input, int input_max_size)
+{
+ if(handle_output != NULL)
+ {
+ RLOGD("function %s line %d input %s\n", __FUNCTION__, __LINE__, input);
+ if(input != NULL)
+ {
+ char *prefix = NULL;
+ prefix = atci_get_cmd_prefix(input);
+ if (NULL == prefix) {
+ RLOGD("atci_cut_cmd_prefix error");
+ return SYS_FAIL;
+ }
+ RLOGD("find prefix [%s]", prefix);
+ Command *cmd = find_command(prefix);
+ if(cmd != NULL)
+ {
+ int cmd_mode = atci_get_cmd_mode(input);
+ RLOGD("function %s line %d\n", __FUNCTION__, __LINE__);
+ (*(cmd->func))(input,cmd_mode);
+ free(prefix);
+ return;
+ }
+ else
+ {
+ RLOGD("not find prefix in list");
+ }
+ free(prefix);
+ }
+ }
+}
+
+lynq_atsvc_incb lynq_register_at_common(lynq_atsvc_outcb out_cb)
+{
+ if(out_cb != NULL)
+ {
+ handle_output = out_cb;
+ RLOGD("function %s line %d\n", __FUNCTION__, __LINE__);
+ return lynq_at_common_cb;
+ }
+}
diff --git a/src/lynq/lib/liblynq-at-common/makefile b/src/lynq/lib/liblynq-at-common/makefile
new file mode 100755
index 0000000..3f9f757
--- /dev/null
+++ b/src/lynq/lib/liblynq-at-common/makefile
@@ -0,0 +1,72 @@
+
+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))
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I$(LOCAL_PATH)/include/libat \
+ -I$(ROOT)$(includedir)/logger \
+ -I$(ROOT)$(includedir)/liblog \
+ -I$(ROOT)$(includedir)/vendor-ril \
+
+
+LOCAL_LIBS := \
+ -L. \
+ -ldl \
+ -lstdc++ \
+ -llog \
+ -lcutils \
+ -lutils \
+ -lbinder \
+ -lpthread \
+
+
+SOURCES = $(wildcard *.cpp)
+
+EXECUTABLE = liblynq-at-common.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/telephonyware/3.0/atcid/atci/src/lynq-private/lynq_atsvc_plugin.xml b/src/telephonyware/3.0/atcid/atci/src/lynq-private/lynq_atsvc_plugin.xml
index 389f4f8..a371624 100755
--- a/src/telephonyware/3.0/atcid/atci/src/lynq-private/lynq_atsvc_plugin.xml
+++ b/src/telephonyware/3.0/atcid/atci/src/lynq-private/lynq_atsvc_plugin.xml
@@ -4,8 +4,16 @@
register="lynq_register_test_data"
cmd="AT+LETEST;AT+LEABC;AT+LEDEF"
/>
- <module name="/lib64/liblynq-gnss.so"
+ <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"
+ />
+ <module name="/lib64/liblynq-at-factory.so"
+ register="lynq_register_at_factory"
+ cmd="AT+LYNQFACTORY"
+ />
</lynq_atsvc_plugin>
\ No newline at end of file