[feature]liblynq-at-extension.so and demo app

Change-Id: I6a66b590774054d29b19352b126de2c24561c43e
diff --git a/framework/lynq-ril-service/src/ril.cpp b/framework/lynq-ril-service/src/ril.cpp
index 3dd15d3..cf3a670 100755
--- a/framework/lynq-ril-service/src/ril.cpp
+++ b/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;