Merge "[feature] key infomation output by AT" into SZZT
diff --git a/src/lynq/framework/lynq-atsvc/src/common.cpp b/src/lynq/framework/lynq-atsvc/src/common.cpp
index 277f88b..4409a3f 100755
--- a/src/lynq/framework/lynq-atsvc/src/common.cpp
+++ b/src/lynq/framework/lynq-atsvc/src/common.cpp
@@ -43,6 +43,8 @@
 #undef LOG_TAG
 #define LOG_TAG "DEMO_COMMON"
 
+#define UNKOWN_VALUE  (-1)
+
 /*Warren add for FAW 2021/11/1 start*/
 extern int ttyGS3_fd = -1;
 /*Warren add for FAW 2021/11/1 end*/
@@ -86,7 +88,107 @@
 
 /*Warren add for SZZT 2021/11/14 end*/
 
-static int regCodeToRadioTechnology(int request, int code, int slot);
+/*hq add for key information output start 2022/03/01*/
+extern int lynq_output_LINFO_enable =0;
+
+typedef enum {
+    RADIO_NW_2G = 0,
+    RADIO_NW_3G = 1,
+    RADIO_NW_4G = 2, 
+#ifdef TELEMATIC_5G_SUPPORT
+    RADIO_NW_5G = 3,    
+#endif
+} RIL_RadioNW;
+
+const char * cardStateToString(int cardStatus)
+{
+    switch(cardStatus) {
+        case RIL_CARDSTATE_ABSENT:
+            return "absent";
+        case RIL_CARDSTATE_PRESENT:
+            return "present";        
+        case RIL_CARDSTATE_ERROR:
+            return "error";
+        default:
+            return "unknown";
+    }
+}
+const char * serviceStateToString(int service_state)
+{
+    switch(service_state) {
+        case STATE_IN_SERVICE:
+            return "IN SERVICE";
+        case STATE_OUT_OF_SERVICE:
+            return "OUT OF SERVICE";
+        case STATE_POWER_OFF:
+            return "POWER_OFF";
+        case STATE_EMERGENCY_ONLY:
+            return "EMERGENCY_ONLY";
+        case UNKOWN_VALUE:
+            return "unDefined";
+        default:
+            return "unDefined";
+    }
+}
+const char * RadioNwToString(int radio_nw)
+{
+    switch(radio_nw) {
+        case RADIO_NW_2G:
+            return "2G";
+        case RADIO_NW_3G:
+            return "3G";
+        case RADIO_NW_4G:
+            return "4G";
+#ifdef TELEMATIC_5G_SUPPORT
+        case RADIO_NW_5G:
+            return "5G";
+#endif
+        case UNKOWN_VALUE:          
+            return "unknown";        
+        default:
+            return "unknown";
+    }
+}
+const char * preferredNetworkTypeToString(int preferred_network_type)
+{
+    switch(preferred_network_type) {
+        case PREF_NET_TYPE_GSM_WCDMA      /*0*/     :  return " GSM/WCDMA (WCDMA case PREFerred)";
+        case PREF_NET_TYPE_GSM_ONLY                 :  return " GSM only";
+        case PREF_NET_TYPE_WCDMA                    :  return " WCDMA ";
+        case PREF_NET_TYPE_GSM_WCDMA_AUTO           :  return " GSM/WCDMA (auto mode, according to PRL)";
+        case PREF_NET_TYPE_CDMA_EVDO_AUTO           :  return " CDMA and EvDo (auto mode, according to PRL)";
+        case PREF_NET_TYPE_CDMA_ONLY                :  return " CDMA only";
+        case PREF_NET_TYPE_EVDO_ONLY                :  return " EvDo only";
+        case PREF_NET_TYPE_GSM_WCDMA_CDMA_EVDO_AUTO :  return " GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL)";
+        case PREF_NET_TYPE_LTE_CDMA_EVDO            :  return " LTE, CDMA and EvDo";
+        case PREF_NET_TYPE_LTE_GSM_WCDMA            :  return " LTE, GSM/WCDMA";
+        case PREF_NET_TYPE_LTE_CMDA_EVDO_GSM_WCDMA  :  return " LTE, CDMA, EvDo, GSM/WCDMA";
+        case PREF_NET_TYPE_LTE_ONLY                 :  return " LTE only";
+        case PREF_NET_TYPE_LTE_WCDMA     /*12*/     :  return " LTE/WCDMA";
+        case PREF_NET_TYPE_LTE_GSM       /*30*/     :  return " LTE/GSM";
+        case PREF_NET_TYPE_LTE_TDD_ONLY  /*31*/     :  return " LTE only";
+        case 13:                                       return "TD-SCDMA only"; 
+        case 14:                                       return "TD-SCDMA and WCDMA"; 
+        case 15:                                       return "TD-SCDMA and LTE"; 
+        case 16:                                       return "TD-SCDMA and GSM"; 
+        case 17:                                       return "TD-SCDMA,GSM and LTE"; 
+        case 18:                                       return "TD-SCDMA, GSM/WCDMA"; 
+        case 19:                                       return "TD-SCDMA, WCDMA and LTE";
+        case 20:                                       return "TD-SCDMA, GSM/WCDMA and LTE"; 
+        case 21:                                       return "TD-SCDMA,EvDo,CDMA,GSM/WCDMA";
+        case 22:                                       return "TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo";
+      //case 30:                                       return "LTE/GSM";
+      //case 31:                                       return "LTE TDD Only mode";
+        case 32:                                       return "CDMA,GSM(2G Global)";
+        case 33:                                       return "CDMA,EVDO,GSM";
+        case 34:                                       return "LTE,CDMA,EVDO,GSM(4G Global, 4M)";        
+        default:
+            return "unDefined";
+    }
+}
+/*hq add for key information output end*/
+
+static int regCodeToRadioTechnology(int code);
 
 void update_call_state(void *response, size_t responselen, int slot) {
     int num = responselen / sizeof(RIL_Call *);
@@ -118,7 +220,12 @@
 
 void update_preferred_network_type(int type, int slot) {
     RLOGD("[SIM%d]update_preferred_network_type: %d", slot, type);
-    preferred_network_type[slot] = type;
+    if(preferred_network_type[slot]!=type)
+    {
+        lynq_output_LINFO("[SIM%d]update_preferred_network_type changed from %s to %s\n", slot+1, preferredNetworkTypeToString(preferred_network_type[slot]),preferredNetworkTypeToString(type));
+        preferred_network_type[slot]=type;
+    }   
+       
 }
 
 int get_preferred_network_type(int slot) {
@@ -229,6 +336,7 @@
 
 void set_default_sim_voice(int slot_id){
     RLOGD("set_default_sim_voice: %d", slot_id);
+    lynq_output_LINFO("Default voice SIM card is set : [SIM%d]", slot_id+1);
     default_sim_voice = slot_id;
 }
 
@@ -248,6 +356,7 @@
             RLOGD("set_default_sim_data, deactive data call done");
         }
         RLOGD("set_default_sim_data, set prop");
+        lynq_output_LINFO("Default data SIM card is set : [SIM%d]", slot+1);
         default_sim_data = slot;
         utils::mtk_property_set(PROP_DEFAULT_DATA_SIM, std::to_string(default_sim_data + 1).c_str());
         while(!isRadioAvailable(RIL_SOCKET_ID(slot))) {
@@ -280,6 +389,7 @@
 
 void set_default_sim_sms(int slot_id){
     RLOGD("set_default_sim_sms: %d", slot_id);
+    lynq_output_LINFO("Default sms SIM card is set : [SIM%d]", slot_id+1);
     default_sim_sms = slot_id;
 }
 
@@ -287,7 +397,7 @@
     return default_sim_sms;
 }
 
-static int regCodeToServiceState(int request,int code, int slot);
+static int regCodeToServiceState(int code);
 
 const char * radioStateToString(RIL_RadioState s) {
     switch (s) {
@@ -365,8 +475,10 @@
 
 void updateCardStatusV6(RIL_CardStatus_v6 *card_status,int slot)
 {
+    int oldStatus = UNKOWN_VALUE;
     if(cur_CardS_Status[slot] != NULL) {
-        RLOGD("[slot%d]updateCardStatusV6", slot);
+        oldStatus = cur_CardS_Status[slot]->card_state;
+        RLOGD("[slot%d]updateCardStatusV6", slot);        
         for(int i = 0; i < cur_CardS_Status[slot]->num_applications; i++) {
         free(cur_CardS_Status[slot]->applications[i].aid_ptr);
         cur_CardS_Status[slot]->applications[i].aid_ptr = NULL;
@@ -405,6 +517,10 @@
             cur_CardS_Status[slot]->applications[i].aid_ptr = strdup(card_status->applications[i].aid_ptr);
             cur_CardS_Status[slot]->applications[i].app_label_ptr = strdup(card_status->applications[i].app_label_ptr);
         }
+        if(card_status->card_state != oldStatus)
+        {
+            lynq_output_LINFO("[SIM%d] Card State changed from %s to %s\n",slot+1,cardStateToString(oldStatus),cardStateToString(card_status->card_state));          
+        }
     } else {
         RLOGD("[slot%d]updateCardStatusV6: sim card message is null", slot);
     }
@@ -431,33 +547,68 @@
 void update_reg_voice_service_state(int request, char *code, int slot, int32_t token)
 {
     if((reg_voice_service_state[slot] != atoi(code)) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) {
-        reg_voice_service_state[slot] = atoi(code);
-        regCodeToServiceState(request, atoi(code), slot);
+        RLOGD("[slot%d]regCodeToServiceState %d, request: %s",slot, code, android::requestToString(request));
+
+        int oldstatus = regCodeToServiceState(reg_voice_service_state[slot]);
+        int status = regCodeToServiceState(atoi(code));
+
+        reg_voice_service_state[slot] = atoi(code);        
+
+        printf("[QUERY][VOICE REG_STATUS][SIM%d] The current service state is %s, code is %d\n", slot,serviceStateToString(status),atoi(code));
+        if(oldstatus != status){
+            lynq_output_LINFO("[SIM%d] Voice Registration State changed from %s to %s\n",slot+1,serviceStateToString(oldstatus),serviceStateToString(status));          
+        }
     }
 }
 
 void update_reg_voice_radio_tech(int request, int code, int slot, int32_t token) {
     if((reg_voice_radio_tech[slot] != code) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)){
+        RLOGD("[slot%d]regCodeToRadioTechnology %d, request: %s",slot, code,android::requestToString(request));
+
+        int oldstatus=regCodeToRadioTechnology(reg_voice_radio_tech[slot]);
+        int status=regCodeToRadioTechnology(code);
+
         reg_voice_radio_tech[slot] = code;
-        regCodeToRadioTechnology(request, code, slot);
+        
+        printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is %s, code is %d\n", slot,RadioNwToString(status),code);
+        if(oldstatus != status){
+            lynq_output_LINFO("[SIM%d] Voice Radio Access Network changed from %s to %s\n",slot+1,RadioNwToString(oldstatus),RadioNwToString(status));          
+        }
     }
 }
 
 void update_reg_data_service_state(int request, char *code,int slot, int32_t token)
 {
     if((reg_data_service_state[slot] != atoi(code)) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) {
+        RLOGD("[slot%d]regCodeToServiceState %d, request: %s",slot, code, android::requestToString(request));
+
+        int oldstatus = regCodeToServiceState(reg_voice_service_state[slot]); 
         reg_data_service_state[slot] = atoi(code);
         /*Warren change for SZZT 2021//11/14 start*/
-        int status = regCodeToServiceState(request, atoi(code), slot);
-        current_data_reg = status;
+        int status = regCodeToServiceState(atoi(code));           
+        current_data_reg = status;       
         /*Warren change for SZZT 2021//11/14 end*/
+        
+        printf("[QUERY][DATA REG_STATUS][SIM%d] The current service state %s, code is %d\n", slot,serviceStateToString(status),atoi(code));
+        if(oldstatus != status){
+            lynq_output_LINFO("[SIM%d] Data Registration State changed from %s to %s\n",slot+1,serviceStateToString(oldstatus),serviceStateToString(status));
+        }
     }
 }
 
 void update_reg_data_radio_tech(int request, int code, int slot, int32_t token){
     if((reg_data_radio_tech[slot] != code) || ((token&RIL_TOKEN_MARK) == RIL_TOKEN_MARK)) {
+        RLOGD("[slot%d]regCodeToRadioTechnology %d, request: %s",slot, code, android::requestToString(request));
+
+        int oldstatus=regCodeToRadioTechnology(reg_data_radio_tech[slot]);        
+        int status=regCodeToRadioTechnology(code);
+
         reg_data_radio_tech[slot] = code;
-        regCodeToRadioTechnology(request, code, slot);
+
+        printf("[QUERY][DATA REG_STATUS][SIM%d] The registered radio technology is %s, code is %d\n", slot,RadioNwToString(status),code);
+        if(oldstatus != status){
+            lynq_output_LINFO("[SIM%d] Data Radio Access Network changed from %s to %s\n",slot+1,RadioNwToString(oldstatus),RadioNwToString(status));          
+        }
     }
 }
 
@@ -546,9 +697,8 @@
     return radio_status[soc_id] != RADIO_STATE_UNAVAILABLE;
 }
 
-static int regCodeToServiceState(int request,int code, int slot)
-{
-    RLOGD("[slot%d]regCodeToServiceState %d, request: %s",slot, code, android::requestToString(request));
+static int regCodeToServiceState(int code)
+{    
     switch (code)
     {
         case 0:
@@ -559,50 +709,28 @@
         case 12:// same as 2, but indicates that emergency call is possible.
         case 13:// same as 3, but indicates that emergency call is possible.
         case 14:// same as 4, but indicates that emergency call is possible.
-        {
-            if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-                printf("[QUERY][VOICE REG_STATUS][SIM%d] The current service state is OUT OF SERVICE\n", slot);
-            } else {
-                printf("[QUERY][DATA  REG_STATUS][SIM%d] The current service state is OUT OF SERVICE\n", slot);
-            }
+        {           
             return STATE_OUT_OF_SERVICE;
         }
 
         case 1:
         case 5:
         {
-            if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-                printf("[QUERY][VOICE REG_STATUS][SIM%d] The current service state is IN SERVICE\n", slot);
-            } else {
-                printf("[QUERY][DATA  REG_STATUS][SIM%d] The current service state is IN SERVICE\n", slot);
-            }
             return STATE_IN_SERVICE;
         }
 
         default:
-        {
-            if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-                printf("[QUERY][VOICE REG_STATUS][SIM%d] Unexpected service state %d\n", slot, code);
-            } else {
-                printf("[QUERY][DATA  REG_STATUS][SIM%d] Unexpected service state %d\n", slot, code);
-            }
-            RLOGW("[SIM%d]regCodeToServiceState: unexpected service state %d", slot, code);
-            return STATE_OUT_OF_SERVICE;
+        {            
+            return UNKOWN_VALUE;
         }
     }
 }
 
-static int regCodeToRadioTechnology(int request, int code, int slot) {
-    RLOGD("[slot%d]regCodeToRadioTechnology %d, request: %s",slot, code, android::requestToString(request));
+static int regCodeToRadioTechnology(int code) {
     switch(code) {
     case RADIO_TECH_LTE:
-    {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is 4G\n", slot);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] The registered radio technology is 4G\n", slot);
-        }
-        break;
+    {       
+        return RADIO_NW_4G;        
     }
     case RADIO_TECH_GSM:
     case RADIO_TECH_GPRS:
@@ -610,13 +738,8 @@
     case RADIO_TECH_IS95A:
     case RADIO_TECH_IS95B:
     case RADIO_TECH_1xRTT:
-    {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is 2G\n", slot);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] The registered radio technology is 2G\n", slot);
-        }
-        break;
+    {       
+        return RADIO_NW_2G;  
     }
     case RADIO_TECH_UMTS:
     case RADIO_TECH_HSDPA:
@@ -629,43 +752,23 @@
     case RADIO_TECH_EVDO_A:
     case RADIO_TECH_EVDO_B:
     {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is 3G\n", slot);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] The registered radio technology is 3G\n", slot);
-        }
-        break;
+        return RADIO_NW_3G;
     }
 #ifdef TELEMATIC_5G_SUPPORT
     case RADIO_TECH_NR://5G
     {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is 5G\n", slot);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] The registered radio technology is 5G\n", slot);
-        }
-        break;
+        return RADIO_NW_5G;
     }
 #endif
     case RADIO_TECH_UNKNOWN:
-    {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] The registered radio technology is unknown\n", slot);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] The registered radio technology is unknown\n", slot);
-        }
-        break;
+    {        
+        return UNKOWN_VALUE;
     }
     default:
-    {
-        if(request == RIL_REQUEST_VOICE_REGISTRATION_STATE) {
-            printf("[QUERY][VOICE REG_STATUS][SIM%d] %d is unexpected value\n",slot, code);
-        } else {
-            printf("[QUERY][DATA  REG_STATUS][SIM%d] %d is unexpected value\n",slot, code);
-        }
+    {        
+        return UNKOWN_VALUE;
     }
-    }
-    return 0;
+    }    
 }
 
 int get_reg_data_radio_tech(int slot) {
@@ -830,3 +933,71 @@
         return -1;
     }
 }
+/*hq add for key info output 2022/03/01 begin*/
+void lynq_output_LINFO_all()
+{
+    int slot,startSlot=0,slotNum=SIM_COUNT;     
+
+    if(default_sim_voice==default_sim_data && default_sim_voice==default_sim_sms){
+        startSlot=default_sim_voice;
+        slotNum=1;        
+    }   
+
+    lynq_output_info("+LINFO: Report switch when key information changed is set: %d\n",lynq_output_LINFO_enable);          
+    lynq_output_info("+LINFO: Default voice SIM card is set : [SIM%d]\n", default_sim_voice+1);    
+    lynq_output_info("+LINFO: Default data SIM card is set : [SIM%d]\n", default_sim_data+1);
+    lynq_output_info("+LINFO: Default sms SIM card is set : [SIM%d]\n", default_sim_sms+1);
+   
+    for(slot=startSlot;slot<startSlot+slotNum;slot++){   
+        lynq_output_info("+LINFO: [SIM%d] Card State is %s\n",slot+1,cardStateToString((cur_CardS_Status[slot]!=NULL ? cur_CardS_Status[slot]->card_state:UNKOWN_VALUE)));                  
+        lynq_output_info("+LINFO: [SIM%d] Preferred network_type: is %s\n", slot+1, preferredNetworkTypeToString(preferred_network_type[slot]));
+        lynq_output_info("+LINFO: [SIM%d] Voice Registration State is %s\n",slot+1,serviceStateToString(regCodeToServiceState(reg_voice_service_state[slot])));
+        lynq_output_info("+LINFO: [SIM%d] Voice Radio Access Network is %s\n",slot+1,RadioNwToString(regCodeToRadioTechnology(reg_voice_radio_tech[slot])));
+        lynq_output_info("+LINFO: [SIM%d] Data Registration State is %s\n",slot+1,serviceStateToString(regCodeToServiceState(reg_data_service_state[slot])));
+        lynq_output_info("+LINFO: [SIM%d] Data Radio Access Network is %s\n",slot+1,RadioNwToString(regCodeToRadioTechnology(reg_data_radio_tech[slot])));          
+    }  
+    return;
+}
+void lynq_output_LINFO(const char* format,...)
+{
+    char buf[1024] = {0};
+    int n;
+    char ebuf[1024] = {0};
+
+    if(lynq_output_LINFO_enable)
+    {
+        va_list args;
+        va_start(args, format);
+        vsnprintf(buf, sizeof(buf), format, args);
+        va_end(args);
+
+        printf("hq %s",buf);
+        n=snprintf(ebuf,sizeof(ebuf),"+LINFO: %s", buf);
+
+        n=write(ttyGS3_fd, ebuf, strlen(ebuf));
+        if(n < 0)
+        {
+            perror("lynq resp write:");
+        }
+    }
+    return;
+}
+void lynq_output_info(const char* format,...)
+{
+    char buf[1024] = {0};
+    int n;   
+    
+    va_list args;
+    va_start(args, format);
+    vsnprintf(buf, sizeof(buf), format, args);
+    va_end(args);     
+       
+    n=write(ttyGS3_fd, buf, strlen(buf));
+    if(n < 0)
+    {
+        perror("lynq resp write:");
+    }
+
+    return;
+}
+/*hq add for key info output 2022/03/01 end*/
diff --git a/src/lynq/framework/lynq-atsvc/src/common.h b/src/lynq/framework/lynq-atsvc/src/common.h
index b36822b..2131984 100755
--- a/src/lynq/framework/lynq-atsvc/src/common.h
+++ b/src/lynq/framework/lynq-atsvc/src/common.h
@@ -148,6 +148,11 @@
 extern int modemStatus;
 /*Warren add for SZZT 2021/11/14 end*/
 
+extern int lynq_output_LINFO_enable;
+void lynq_output_info(const char* format,...);
+void lynq_output_LINFO(const char* format,...);
+void lynq_output_LINFO_all();
+    
 typedef struct {
     char *name;           /* User printable name of the function. */
     int (*func)(int argc, char *argv[], RIL_SOCKET_ID socket_id, RequestInfo *pRI);       /* Function to call to do the job. */
diff --git a/src/lynq/framework/lynq-atsvc/src/lynq_common.cpp b/src/lynq/framework/lynq-atsvc/src/lynq_common.cpp
index 045831a..b29cb17 100755
--- a/src/lynq/framework/lynq-atsvc/src/lynq_common.cpp
+++ b/src/lynq/framework/lynq-atsvc/src/lynq_common.cpp
@@ -100,6 +100,8 @@
 
             return LYNQ_GOTO_RNDIS_REQ;
         }
+        case LYNQ_REQUEST_LINFO:
+            return LYNQ_GOTO_LINFO_REQ;
         case LYNQ_REQUEST_FACTORY:
             return LYNQ_GOTO_FACTORY;
         default:
@@ -554,5 +556,32 @@
     pthread_mutex_unlock(&lynq_at_mutex);
     return;
 }
-
-
+void lynqInfo(char*argv[])
+{
+    int type = atoi(argv[2]);
+   
+    if(type==2){                            
+        lynq_output_LINFO_all();     
+        syncRespToUsb(0);
+    }
+    else if(type==0){                           
+        int status = atoi(argv[3]);
+        if(status==1 || status==0){
+            lynq_output_LINFO_enable=status;
+            lynq_output_info("+LINFO: Report switch when key information changed is set: %d\n",lynq_output_LINFO_enable);    
+            syncRespToUsb(0);
+        }   
+        else {
+            lynq_output_info("parameter error\n"); 
+            syncRespToUsb(100);    
+        }
+    }
+    else if(type==1){        
+        lynq_output_info("+LINFO: (0-1)\n");         
+        syncRespToUsb(0);
+    }
+    else {   
+        lynq_output_info("parameter error\n"); 
+        syncRespToUsb(100);
+    }
+}
diff --git a/src/lynq/framework/lynq-atsvc/src/lynq_common.h b/src/lynq/framework/lynq-atsvc/src/lynq_common.h
index 304aa6c..f2da811 100755
--- a/src/lynq/framework/lynq-atsvc/src/lynq_common.h
+++ b/src/lynq/framework/lynq-atsvc/src/lynq_common.h
@@ -29,6 +29,8 @@
 #define LYNQ_GOTO_RNDIS_REQ 5
 /*factory*/
 #define LYNQ_GOTO_FACTORY 6
+/*info output*/
+#define LYNQ_GOTO_LINFO_REQ 7
 
 #define LYNQ_APN_LEN_MAX 100
 #define LYNQ_APNTPYE_LEN_MAX 50
@@ -53,6 +55,7 @@
 #define LYNQ_PLAT_LGMDS (LYNQ_VERSION +14)
 #define LYNQ_REQUEST_RNDIS (LYNQ_VERSION +15)
 #define LYNQ_REQUEST_FACTORY (LYNQ_VERSION +16)
+#define LYNQ_REQUEST_LINFO (LYNQ_VERSION +17)
 #define LYNQ_USER_REQUEST_GNSS (LYNQ_VERSION +100)
 #define LYNQ_USER_REQUEST_OTHRE (LYNQ_VERSION +101)
 
@@ -100,5 +103,5 @@
 int lynqATWaitWithTime(int time);//time(s)
 void lynqAtRespWatingEvent();
 int syncRespToUsb(int error_code);
-
+void lynqInfo(char*argv[]);
 #endif
diff --git a/src/lynq/framework/lynq-atsvc/src/ril.cpp b/src/lynq/framework/lynq-atsvc/src/ril.cpp
index fcdb7c3..4c16695 100755
--- a/src/lynq/framework/lynq-atsvc/src/ril.cpp
+++ b/src/lynq/framework/lynq-atsvc/src/ril.cpp
@@ -6508,6 +6508,11 @@
                     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]);