xref: /OK3568_Linux_fs/app/forlinx/quectelCM/QMIThread.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /******************************************************************************
2*4882a593Smuzhiyun   @file    QMIThread.c
3*4882a593Smuzhiyun   @brief   QMI WWAN connectivity manager.
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun   DESCRIPTION
6*4882a593Smuzhiyun   Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun   INITIALIZATION AND SEQUENCING REQUIREMENTS
9*4882a593Smuzhiyun   None.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun   ---------------------------------------------------------------------------
12*4882a593Smuzhiyun   Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd.  All Rights Reserved.
13*4882a593Smuzhiyun   Quectel Wireless Solution Proprietary and Confidential.
14*4882a593Smuzhiyun   ---------------------------------------------------------------------------
15*4882a593Smuzhiyun ******************************************************************************/
16*4882a593Smuzhiyun #include "QMIThread.h"
17*4882a593Smuzhiyun #ifndef MIN
18*4882a593Smuzhiyun #define MIN(a, b)	((a) < (b)? (a): (b))
19*4882a593Smuzhiyun #endif
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun extern char *strndup (const char *__string, size_t __n);
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define qmi_rsp_check_and_return() do { \
24*4882a593Smuzhiyun         if (err < 0 || pResponse == NULL) { \
25*4882a593Smuzhiyun             dbg_time("%s err = %d", __func__, err); \
26*4882a593Smuzhiyun             return err; \
27*4882a593Smuzhiyun         } \
28*4882a593Smuzhiyun         pMUXMsg = &pResponse->MUXMsg; \
29*4882a593Smuzhiyun         if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \
30*4882a593Smuzhiyun             USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \
31*4882a593Smuzhiyun             dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \
32*4882a593Smuzhiyun                 le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), QMUXError); \
33*4882a593Smuzhiyun             free(pResponse); \
34*4882a593Smuzhiyun             return QMUXError; \
35*4882a593Smuzhiyun         } \
36*4882a593Smuzhiyun } while(0)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define qmi_rsp_check() do { \
39*4882a593Smuzhiyun         if (err < 0 || pResponse == NULL) { \
40*4882a593Smuzhiyun             dbg_time("%s err = %d", __func__, err); \
41*4882a593Smuzhiyun             return err; \
42*4882a593Smuzhiyun         } \
43*4882a593Smuzhiyun         pMUXMsg = &pResponse->MUXMsg; \
44*4882a593Smuzhiyun         if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) { \
45*4882a593Smuzhiyun             USHORT QMUXError = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); \
46*4882a593Smuzhiyun             dbg_time("%s QMUXResult = 0x%x, QMUXError = 0x%x", __func__, \
47*4882a593Smuzhiyun                 le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult), QMUXError); \
48*4882a593Smuzhiyun         } \
49*4882a593Smuzhiyun } while(0)
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun static uint32_t WdsConnectionIPv4Handle = 0;
52*4882a593Smuzhiyun static uint32_t WdsConnectionIPv6Handle = 0;
53*4882a593Smuzhiyun static int s_is_cdma = 0;
54*4882a593Smuzhiyun static int s_5g_type = WWAN_DATA_CLASS_NONE;
55*4882a593Smuzhiyun static int s_hdr_personality = 0; // 0x01-HRPD, 0x02-eHRPD
qstrcpy(char * to,const char * from)56*4882a593Smuzhiyun static char *qstrcpy(char *to, const char *from) { //no __strcpy_chk
57*4882a593Smuzhiyun 	char *save = to;
58*4882a593Smuzhiyun 	for (; (*to = *from) != '\0'; ++from, ++to);
59*4882a593Smuzhiyun 	return(save);
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static int s_9x07 = 1;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun typedef USHORT (*CUSTOMQMUX)(PQMUX_MSG pMUXMsg, void *arg);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun // To retrieve the ith (Index) TLV
GetTLV(PQCQMUX_MSG_HDR pQMUXMsgHdr,int TLVType)67*4882a593Smuzhiyun PQMI_TLV_HDR GetTLV (PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType) {
68*4882a593Smuzhiyun     int TLVFind = 0;
69*4882a593Smuzhiyun     USHORT Length = le16_to_cpu(pQMUXMsgHdr->Length);
70*4882a593Smuzhiyun     PQMI_TLV_HDR pTLVHdr = (PQMI_TLV_HDR)(pQMUXMsgHdr + 1);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun     while (Length >= sizeof(QMI_TLV_HDR)) {
73*4882a593Smuzhiyun         TLVFind++;
74*4882a593Smuzhiyun         if (TLVType > 0x1000) {
75*4882a593Smuzhiyun             if ((TLVFind + 0x1000) == TLVType)
76*4882a593Smuzhiyun                 return pTLVHdr;
77*4882a593Smuzhiyun         } else  if (pTLVHdr->TLVType == TLVType) {
78*4882a593Smuzhiyun             return pTLVHdr;
79*4882a593Smuzhiyun         }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun         Length -= (le16_to_cpu((pTLVHdr->TLVLength)) + sizeof(QMI_TLV_HDR));
82*4882a593Smuzhiyun         pTLVHdr = (PQMI_TLV_HDR)(((UCHAR *)pTLVHdr) + le16_to_cpu(pTLVHdr->TLVLength) + sizeof(QMI_TLV_HDR));
83*4882a593Smuzhiyun     }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun    return NULL;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
GetQMUXTransactionId(void)88*4882a593Smuzhiyun static USHORT GetQMUXTransactionId(void) {
89*4882a593Smuzhiyun     static int TransactionId = 0;
90*4882a593Smuzhiyun     if (++TransactionId > 0xFFFF)
91*4882a593Smuzhiyun         TransactionId = 1;
92*4882a593Smuzhiyun     return TransactionId;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
ComposeQMUXMsg(UCHAR QMIType,USHORT Type,CUSTOMQMUX customQmuxMsgFunction,void * arg)95*4882a593Smuzhiyun static PQCQMIMSG ComposeQMUXMsg(UCHAR QMIType, USHORT Type, CUSTOMQMUX customQmuxMsgFunction, void *arg) {
96*4882a593Smuzhiyun     UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE];
97*4882a593Smuzhiyun     PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf;
98*4882a593Smuzhiyun     int Length;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun     memset(QMIBuf, 0x00, sizeof(QMIBuf));
101*4882a593Smuzhiyun     pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
102*4882a593Smuzhiyun     pRequest->QMIHdr.CtlFlags = 0x00;
103*4882a593Smuzhiyun     pRequest->QMIHdr.QMIType = QMIType;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun     pRequest->MUXMsg.QMUXHdr.CtlFlags = QMUX_CTL_FLAG_SINGLE_MSG | QMUX_CTL_FLAG_TYPE_CMD;
106*4882a593Smuzhiyun     pRequest->MUXMsg.QMUXHdr.TransactionId = cpu_to_le16(GetQMUXTransactionId());
107*4882a593Smuzhiyun     pRequest->MUXMsg.QMUXMsgHdr.Type = cpu_to_le16(Type);
108*4882a593Smuzhiyun     if (customQmuxMsgFunction)
109*4882a593Smuzhiyun         pRequest->MUXMsg.QMUXMsgHdr.Length = cpu_to_le16(customQmuxMsgFunction(&pRequest->MUXMsg, arg) - sizeof(QCQMUX_MSG_HDR));
110*4882a593Smuzhiyun     else
111*4882a593Smuzhiyun         pRequest->MUXMsg.QMUXMsgHdr.Length = cpu_to_le16(0x0000);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun     pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->MUXMsg.QMUXMsgHdr.Length) + sizeof(QCQMUX_MSG_HDR) + sizeof(QCQMUX_HDR)
114*4882a593Smuzhiyun         + sizeof(QCQMI_HDR) - 1);
115*4882a593Smuzhiyun     Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun     pRequest = (PQCQMIMSG)malloc(Length);
118*4882a593Smuzhiyun     if (pRequest == NULL) {
119*4882a593Smuzhiyun         dbg_time("%s fail to malloc", __func__);
120*4882a593Smuzhiyun     } else {
121*4882a593Smuzhiyun         memcpy(pRequest, QMIBuf, Length);
122*4882a593Smuzhiyun     }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     return pRequest;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun #if 0
128*4882a593Smuzhiyun static USHORT NasSetEventReportReq(PQMUX_MSG pMUXMsg, void *arg) {
129*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.TLVType = 0x10;
130*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.TLVLength = 0x04;
131*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.ReportSigStrength = 0x00;
132*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.NumTresholds = 2;
133*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.TresholdList[0] = -113;
134*4882a593Smuzhiyun     pMUXMsg->SetEventReportReq.TresholdList[1] = -50;
135*4882a593Smuzhiyun     return sizeof(QMINAS_SET_EVENT_REPORT_REQ_MSG);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun static USHORT WdsSetEventReportReq(PQMUX_MSG pMUXMsg, void *arg) {
139*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLVType = 0x10;          // 0x10 -- current channel rate indicator
140*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLVLength = 0x0001;        // 1
141*4882a593Smuzhiyun     pMUXMsg->EventReportReq.Mode = 0x00;             // 0-do not report; 1-report when rate changes
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV2Type = 0x11;         // 0x11
144*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV2Length = 0x0005;       // 5
145*4882a593Smuzhiyun     pMUXMsg->EventReportReq.StatsPeriod = 0x00;      // seconds between reports; 0-do not report
146*4882a593Smuzhiyun     pMUXMsg->EventReportReq.StatsMask = 0x000000ff;        //
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV3Type = 0x12;          // 0x12 -- current data bearer indicator
149*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV3Length = 0x0001;        // 1
150*4882a593Smuzhiyun     pMUXMsg->EventReportReq.Mode3 = 0x01;             // 0-do not report; 1-report when changes
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV4Type = 0x13;          // 0x13 -- dormancy status indicator
153*4882a593Smuzhiyun     pMUXMsg->EventReportReq.TLV4Length = 0x0001;        // 1
154*4882a593Smuzhiyun     pMUXMsg->EventReportReq.DormancyStatus = 0x00;    // 0-do not report; 1-report when changes
155*4882a593Smuzhiyun     return sizeof(QMIWDS_SET_EVENT_REPORT_REQ_MSG);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun static USHORT DmsSetEventReportReq(PQMUX_MSG pMUXMsg) {
159*4882a593Smuzhiyun     PPIN_STATUS pPinState = (PPIN_STATUS)(&pMUXMsg->DmsSetEventReportReq + 1);
160*4882a593Smuzhiyun     PUIM_STATE pUimState = (PUIM_STATE)(pPinState + 1);
161*4882a593Smuzhiyun     // Pin State
162*4882a593Smuzhiyun     pPinState->TLVType = 0x12;
163*4882a593Smuzhiyun     pPinState->TLVLength = 0x01;
164*4882a593Smuzhiyun     pPinState->ReportPinState = 0x01;
165*4882a593Smuzhiyun     // UIM State
166*4882a593Smuzhiyun     pUimState->TLVType = 0x15;
167*4882a593Smuzhiyun     pUimState->TLVLength = 0x01;
168*4882a593Smuzhiyun     pUimState->UIMState = 0x01;
169*4882a593Smuzhiyun     return sizeof(QMIDMS_SET_EVENT_REPORT_REQ_MSG) + sizeof(PIN_STATUS) + sizeof(UIM_STATE);
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun #endif
172*4882a593Smuzhiyun 
WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg,void * arg)173*4882a593Smuzhiyun static USHORT WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) {
174*4882a593Smuzhiyun     PQMIWDS_TECHNOLOGY_PREFERECE pTechPref;
175*4882a593Smuzhiyun     PQMIWDS_AUTH_PREFERENCE pAuthPref;
176*4882a593Smuzhiyun     PQMIWDS_USERNAME pUserName;
177*4882a593Smuzhiyun     PQMIWDS_PASSWD pPasswd;
178*4882a593Smuzhiyun     PQMIWDS_APNNAME pApnName;
179*4882a593Smuzhiyun     PQMIWDS_IP_FAMILY_TLV pIpFamily;
180*4882a593Smuzhiyun     USHORT TLVLength = 0;
181*4882a593Smuzhiyun     UCHAR *pTLV;
182*4882a593Smuzhiyun     PROFILE_T *profile = (PROFILE_T *)arg;
183*4882a593Smuzhiyun     const char *profile_user = profile->user;
184*4882a593Smuzhiyun     const char *profile_password = profile->password;
185*4882a593Smuzhiyun     int profile_auth = profile->auth;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun     if (s_is_cdma && (profile_user == NULL || profile_user[0] == '\0') && (profile_password == NULL || profile_password[0] == '\0')) {
188*4882a593Smuzhiyun         profile_user = "ctnet@mycdma.cn";
189*4882a593Smuzhiyun         profile_password = "vnet.mobi";
190*4882a593Smuzhiyun         profile_auth = 2; //chap
191*4882a593Smuzhiyun     }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun     pTLV = (UCHAR *)(&pMUXMsg->StartNwInterfaceReq + 1);
194*4882a593Smuzhiyun     pMUXMsg->StartNwInterfaceReq.Length = 0;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun     // Set technology Preferece
197*4882a593Smuzhiyun     pTechPref = (PQMIWDS_TECHNOLOGY_PREFERECE)(pTLV + TLVLength);
198*4882a593Smuzhiyun     pTechPref->TLVType = 0x30;
199*4882a593Smuzhiyun     pTechPref->TLVLength = cpu_to_le16(0x01);
200*4882a593Smuzhiyun     if (s_is_cdma == 0)
201*4882a593Smuzhiyun         pTechPref->TechPreference = 0x01;
202*4882a593Smuzhiyun     else
203*4882a593Smuzhiyun         pTechPref->TechPreference = 0x02;
204*4882a593Smuzhiyun     TLVLength +=(le16_to_cpu(pTechPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun     // Set APN Name
207*4882a593Smuzhiyun     if (profile->apn && !s_is_cdma) { //cdma no apn
208*4882a593Smuzhiyun         pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength);
209*4882a593Smuzhiyun         pApnName->TLVType = 0x14;
210*4882a593Smuzhiyun         pApnName->TLVLength = cpu_to_le16(strlen(profile->apn));
211*4882a593Smuzhiyun         qstrcpy((char *)&pApnName->ApnName, profile->apn);
212*4882a593Smuzhiyun         TLVLength +=(le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
213*4882a593Smuzhiyun     }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun     // Set User Name
216*4882a593Smuzhiyun     if (profile_user) {
217*4882a593Smuzhiyun         pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength);
218*4882a593Smuzhiyun         pUserName->TLVType = 0x17;
219*4882a593Smuzhiyun         pUserName->TLVLength = cpu_to_le16(strlen(profile_user));
220*4882a593Smuzhiyun         qstrcpy((char *)&pUserName->UserName, profile_user);
221*4882a593Smuzhiyun         TLVLength += (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
222*4882a593Smuzhiyun     }
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun     // Set Password
225*4882a593Smuzhiyun     if (profile_password) {
226*4882a593Smuzhiyun         pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength);
227*4882a593Smuzhiyun         pPasswd->TLVType = 0x18;
228*4882a593Smuzhiyun         pPasswd->TLVLength = cpu_to_le16(strlen(profile_password));
229*4882a593Smuzhiyun         qstrcpy((char *)&pPasswd->Passwd, profile_password);
230*4882a593Smuzhiyun 	TLVLength += (le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
231*4882a593Smuzhiyun     }
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun     // Set Auth Protocol
234*4882a593Smuzhiyun     if (profile_user && profile_password) {
235*4882a593Smuzhiyun         pAuthPref = (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength);
236*4882a593Smuzhiyun         pAuthPref->TLVType = 0x16;
237*4882a593Smuzhiyun         pAuthPref->TLVLength = cpu_to_le16(0x01);
238*4882a593Smuzhiyun         pAuthPref->AuthPreference = profile_auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2
239*4882a593Smuzhiyun         TLVLength += (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
240*4882a593Smuzhiyun     }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun     // Add IP Family Preference
243*4882a593Smuzhiyun     pIpFamily = (PQMIWDS_IP_FAMILY_TLV)(pTLV + TLVLength);
244*4882a593Smuzhiyun     pIpFamily->TLVType = 0x19;
245*4882a593Smuzhiyun     pIpFamily->TLVLength = cpu_to_le16(0x01);
246*4882a593Smuzhiyun     pIpFamily->IpFamily = profile->curIpFamily;
247*4882a593Smuzhiyun     TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun     //Set Profile Index
250*4882a593Smuzhiyun     if (profile->pdp && !s_is_cdma) { //cdma only support one pdp, so no need to set profile index
251*4882a593Smuzhiyun         PQMIWDS_PROFILE_IDENTIFIER pProfileIndex = (PQMIWDS_PROFILE_IDENTIFIER)(pTLV + TLVLength);
252*4882a593Smuzhiyun         pProfileIndex->TLVLength = cpu_to_le16(0x01);
253*4882a593Smuzhiyun         pProfileIndex->TLVType = 0x31;
254*4882a593Smuzhiyun         pProfileIndex->ProfileIndex = profile->pdp;
255*4882a593Smuzhiyun         if (s_is_cdma && s_hdr_personality == 0x02) {
256*4882a593Smuzhiyun             pProfileIndex->TLVType = 0x32; //profile_index_3gpp2
257*4882a593Smuzhiyun             pProfileIndex->ProfileIndex = 101;
258*4882a593Smuzhiyun         }
259*4882a593Smuzhiyun         TLVLength += (le16_to_cpu(pProfileIndex->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
260*4882a593Smuzhiyun     }
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun     return sizeof(QMIWDS_START_NETWORK_INTERFACE_REQ_MSG) + TLVLength;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
WdsStopNwInterfaceReq(PQMUX_MSG pMUXMsg,void * arg)265*4882a593Smuzhiyun static USHORT WdsStopNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) {
266*4882a593Smuzhiyun     pMUXMsg->StopNwInterfaceReq.TLVType = 0x01;
267*4882a593Smuzhiyun     pMUXMsg->StopNwInterfaceReq.TLVLength = cpu_to_le16(0x04);
268*4882a593Smuzhiyun     if (*((int *)arg) == IpFamilyV4)
269*4882a593Smuzhiyun         pMUXMsg->StopNwInterfaceReq.Handle =  cpu_to_le32(WdsConnectionIPv4Handle);
270*4882a593Smuzhiyun     else
271*4882a593Smuzhiyun         pMUXMsg->StopNwInterfaceReq.Handle =  cpu_to_le32(WdsConnectionIPv6Handle);
272*4882a593Smuzhiyun     return sizeof(QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
WdsSetClientIPFamilyPref(PQMUX_MSG pMUXMsg,void * arg)275*4882a593Smuzhiyun static USHORT WdsSetClientIPFamilyPref(PQMUX_MSG pMUXMsg, void *arg) {
276*4882a593Smuzhiyun     pMUXMsg->SetClientIpFamilyPrefReq.TLVType = 0x01;
277*4882a593Smuzhiyun     pMUXMsg->SetClientIpFamilyPrefReq.TLVLength = cpu_to_le16(0x01);
278*4882a593Smuzhiyun     pMUXMsg->SetClientIpFamilyPrefReq.IpPreference = *((UCHAR *)arg);
279*4882a593Smuzhiyun     return sizeof(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun 
WdsSetAutoConnect(PQMUX_MSG pMUXMsg,void * arg)282*4882a593Smuzhiyun static USHORT WdsSetAutoConnect(PQMUX_MSG pMUXMsg, void *arg) {
283*4882a593Smuzhiyun     pMUXMsg->SetAutoConnectReq.TLVType = 0x01;
284*4882a593Smuzhiyun     pMUXMsg->SetAutoConnectReq.TLVLength = cpu_to_le16(0x01);
285*4882a593Smuzhiyun     pMUXMsg->SetAutoConnectReq.autoconnect_setting = *((UCHAR *)arg);
286*4882a593Smuzhiyun     return sizeof(QMIWDS_SET_AUTO_CONNECT_REQ_MSG);
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun enum peripheral_ep_type {
290*4882a593Smuzhiyun 	DATA_EP_TYPE_RESERVED	= 0x0,
291*4882a593Smuzhiyun 	DATA_EP_TYPE_HSIC	= 0x1,
292*4882a593Smuzhiyun 	DATA_EP_TYPE_HSUSB	= 0x2,
293*4882a593Smuzhiyun 	DATA_EP_TYPE_PCIE	= 0x3,
294*4882a593Smuzhiyun 	DATA_EP_TYPE_EMBEDDED	= 0x4,
295*4882a593Smuzhiyun 	DATA_EP_TYPE_BAM_DMUX	= 0x5,
296*4882a593Smuzhiyun };
297*4882a593Smuzhiyun 
WdsSetQMUXBindMuxDataPort(PQMUX_MSG pMUXMsg,void * arg)298*4882a593Smuzhiyun static USHORT WdsSetQMUXBindMuxDataPort(PQMUX_MSG pMUXMsg, void *arg) {
299*4882a593Smuzhiyun     QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLVType = 0x10;
302*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLVLength = cpu_to_le16(0x08);
303*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.ep_type = cpu_to_le32(qmap_settings->ep_type);
304*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.iface_id = cpu_to_le32(qmap_settings->iface_id);
305*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLV2Type = 0x11;
306*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLV2Length = cpu_to_le16(0x01);
307*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.MuxId = qmap_settings->MuxId;
308*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLV3Type = 0x13;
309*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.TLV3Length = cpu_to_le16(0x04);
310*4882a593Smuzhiyun     pMUXMsg->BindMuxDataPortReq.client_type = cpu_to_le32(1); //WDS_CLIENT_TYPE_TETHERED
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun     return sizeof(QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun static int qmap_version = 0x05;
WdaSetDataFormat(PQMUX_MSG pMUXMsg,void * arg)316*4882a593Smuzhiyun static USHORT WdaSetDataFormat(PQMUX_MSG pMUXMsg, void *arg) {
317*4882a593Smuzhiyun     QMAP_SETTING *qmap_settings = (QMAP_SETTING *)arg;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun     if (qmap_settings->rx_urb_size == 0) {
320*4882a593Smuzhiyun         PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS pWdsAdminQosTlv;
321*4882a593Smuzhiyun         PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto;
322*4882a593Smuzhiyun         PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV dlTlp;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun         pWdsAdminQosTlv = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS)(&pMUXMsg->QMUXMsgHdr + 1);
325*4882a593Smuzhiyun         pWdsAdminQosTlv->TLVType = 0x10;
326*4882a593Smuzhiyun         pWdsAdminQosTlv->TLVLength = cpu_to_le16(0x0001);
327*4882a593Smuzhiyun         pWdsAdminQosTlv->QOSSetting = 0; /* no-QOS header */
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun         linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(pWdsAdminQosTlv + 1);
330*4882a593Smuzhiyun         linkProto->TLVType = 0x11;
331*4882a593Smuzhiyun         linkProto->TLVLength = cpu_to_le16(4);
332*4882a593Smuzhiyun         linkProto->Value = cpu_to_le32(0x01);     /* Set Ethernet  mode */
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun         dlTlp = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)(linkProto + 1);;
335*4882a593Smuzhiyun         dlTlp->TLVType = 0x13;
336*4882a593Smuzhiyun         dlTlp->TLVLength = cpu_to_le16(4);
337*4882a593Smuzhiyun         dlTlp->Value = cpu_to_le32(0x00);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun         if (sizeof(*linkProto) != 7 )
340*4882a593Smuzhiyun             dbg_time("%s sizeof(*linkProto) = %zu, is not 7!", __func__, sizeof(*linkProto) );
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun         return sizeof(QCQMUX_MSG_HDR) + sizeof(*pWdsAdminQosTlv) + sizeof(*linkProto) + sizeof(*dlTlp);
343*4882a593Smuzhiyun     }
344*4882a593Smuzhiyun     else {
345*4882a593Smuzhiyun     //Indicates whether the Quality of Service(QOS) data format is used by the client.
346*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVType = 0x10;
347*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.QosDataFormatTlv.TLVLength = cpu_to_le16(0x0001);
348*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.QosDataFormatTlv.QOSSetting = 0; /* no-QOS header */
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun     //Underlying Link Layer Protocol
351*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVType = 0x11;
352*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.TLVLength = cpu_to_le16(4);
353*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UnderlyingLinkLayerProtocolTlv.Value = cpu_to_le32(0x02);     /* Set IP  mode */
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun     //Uplink (UL) data aggregation protocol to be used for uplink data transfer.
356*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVType = 0x12;
357*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4);
358*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //UL QMAP is enabled
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun     //Downlink (DL) data aggregation protocol to be used for downlink data transfer
361*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVType = 0x13;
362*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.TLVLength = cpu_to_le16(4);
363*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationProtocolTlv.Value = cpu_to_le32(qmap_version); //DL QMAP is enabled
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     //Maximum number of datagrams in a single aggregated packet on downlink
366*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVType = 0x15;
367*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4);
368*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(qmap_settings->rx_urb_size/512);
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun     //Maximum size in bytes of a single aggregated packet allowed on downlink
371*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVType = 0x16;
372*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4);
373*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DownlinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(qmap_settings->rx_urb_size);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun     //Peripheral End Point ID
376*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.epTlv.TLVType = 0x17;
377*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.epTlv.TLVLength = cpu_to_le16(8);
378*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.epTlv.ep_type = cpu_to_le32(qmap_settings->ep_type);
379*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.epTlv.iface_id = cpu_to_le32(qmap_settings->iface_id);
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun #ifdef QUECTEL_UL_DATA_AGG
382*4882a593Smuzhiyun         if (!qmap_settings->ul_data_aggregation_max_datagrams) {
383*4882a593Smuzhiyun             return ((size_t)&((QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG *)0)->DlMinimumPassingTlv);
384*4882a593Smuzhiyun         }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun      //Maximum number of datagrams in a single aggregated packet on uplink
387*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.TLVType = 0x19;
388*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.TLVLength = cpu_to_le16(4);
389*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.DlMinimumPassingTlv.Value = cpu_to_le32(qmap_settings->dl_minimum_padding);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun      //Maximum number of datagrams in a single aggregated packet on uplink
392*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.TLVType = 0x1B;
393*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.TLVLength = cpu_to_le16(4);
394*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxDatagramsTlv.Value = cpu_to_le32(qmap_settings->ul_data_aggregation_max_datagrams);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun     //Maximum size in bytes of a single aggregated packet allowed on downlink
397*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.TLVType = 0x1C;
398*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.TLVLength = cpu_to_le16(4);
399*4882a593Smuzhiyun         pMUXMsg->SetDataFormatReq.UplinkDataAggregationMaxSizeTlv.Value = cpu_to_le32(qmap_settings->ul_data_aggregation_max_size);
400*4882a593Smuzhiyun #endif
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun         return sizeof(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG);
403*4882a593Smuzhiyun     }
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun #ifdef CONFIG_SIM
DmsUIMVerifyPinReqSend(PQMUX_MSG pMUXMsg,void * arg)407*4882a593Smuzhiyun static USHORT DmsUIMVerifyPinReqSend(PQMUX_MSG pMUXMsg, void *arg) {
408*4882a593Smuzhiyun     pMUXMsg->UIMVerifyPinReq.TLVType = 0x01;
409*4882a593Smuzhiyun     pMUXMsg->UIMVerifyPinReq.PINID = 0x01; //Pin1, not Puk
410*4882a593Smuzhiyun     pMUXMsg->UIMVerifyPinReq.PINLen = strlen((const char *)arg);
411*4882a593Smuzhiyun     qstrcpy((PCHAR)&pMUXMsg->UIMVerifyPinReq.PINValue, ((const char *)arg));
412*4882a593Smuzhiyun     pMUXMsg->UIMVerifyPinReq.TLVLength = cpu_to_le16(2 + strlen((const char *)arg));
413*4882a593Smuzhiyun     return sizeof(QMIDMS_UIM_VERIFY_PIN_REQ_MSG) + (strlen((const char *)arg) - 1);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
UimVerifyPinReqSend(PQMUX_MSG pMUXMsg,void * arg)416*4882a593Smuzhiyun static USHORT UimVerifyPinReqSend(PQMUX_MSG pMUXMsg, void *arg)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.TLVType = 0x01;
419*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.TLVLength = cpu_to_le16(0x02);
420*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.Session_Type = 0x00;
421*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.Aid_Len = 0x00;
422*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.TLV2Type = 0x02;
423*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.TLV2Length = cpu_to_le16(2 + strlen((const char *)arg));
424*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.PINID = 0x01;  //Pin1, not Puk
425*4882a593Smuzhiyun     pMUXMsg->UIMUIMVerifyPinReq.PINLen= strlen((const char *)arg);
426*4882a593Smuzhiyun     qstrcpy((PCHAR)&pMUXMsg->UIMUIMVerifyPinReq.PINValue, ((const char *)arg));
427*4882a593Smuzhiyun     return sizeof(QMIUIM_VERIFY_PIN_REQ_MSG) + (strlen((const char *)arg) - 1);
428*4882a593Smuzhiyun }
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun #ifdef CONFIG_IMSI_ICCID
UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg,void * arg)431*4882a593Smuzhiyun static USHORT UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg, void *arg) {
432*4882a593Smuzhiyun     PREAD_TRANSPARENT_TLV pReadTransparent;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun     pMUXMsg->UIMUIMReadTransparentReq.TLVType =  0x01;
435*4882a593Smuzhiyun     pMUXMsg->UIMUIMReadTransparentReq.TLVLength = cpu_to_le16(0x02);
436*4882a593Smuzhiyun     if (!strcmp((char *)arg, "EF_ICCID")) {
437*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x06;
438*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02;
441*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x2FE2);
442*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x02;
443*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00;
444*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F;
445*4882a593Smuzhiyun     }
446*4882a593Smuzhiyun     else if(!strcmp((char *)arg, "EF_IMSI")) {
447*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.Session_Type = 0x00;
448*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.Aid_Len = 0x00;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.TLV2Type = 0x02;
451*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.file_id = cpu_to_le16(0x6F07);
452*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path_len = 0x04;
453*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[0] = 0x00;
454*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[1] = 0x3F;
455*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[2] = 0xFF;
456*4882a593Smuzhiyun         pMUXMsg->UIMUIMReadTransparentReq.path[3] = 0x7F;
457*4882a593Smuzhiyun     }
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun     pMUXMsg->UIMUIMReadTransparentReq.TLV2Length = cpu_to_le16(3 +  pMUXMsg->UIMUIMReadTransparentReq.path_len);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun     pReadTransparent = (PREAD_TRANSPARENT_TLV)(&pMUXMsg->UIMUIMReadTransparentReq.path[pMUXMsg->UIMUIMReadTransparentReq.path_len]);
462*4882a593Smuzhiyun     pReadTransparent->TLVType = 0x03;
463*4882a593Smuzhiyun     pReadTransparent->TLVLength = cpu_to_le16(0x04);
464*4882a593Smuzhiyun     pReadTransparent->Offset = cpu_to_le16(0x00);
465*4882a593Smuzhiyun     pReadTransparent->Length = cpu_to_le16(0x00);
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun     return (sizeof(QMIUIM_READ_TRANSPARENT_REQ_MSG) + pMUXMsg->UIMUIMReadTransparentReq.path_len + sizeof(READ_TRANSPARENT_TLV));
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun #endif
470*4882a593Smuzhiyun #endif
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun #ifdef CONFIG_APN
WdsGetProfileSettingsReqSend(PQMUX_MSG pMUXMsg,void * arg)473*4882a593Smuzhiyun static USHORT WdsGetProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) {
474*4882a593Smuzhiyun     PROFILE_T *profile = (PROFILE_T *)arg;
475*4882a593Smuzhiyun     pMUXMsg->GetProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG) - 4);
476*4882a593Smuzhiyun     pMUXMsg->GetProfileSettingsReq.TLVType = 0x01;
477*4882a593Smuzhiyun     pMUXMsg->GetProfileSettingsReq.TLVLength = cpu_to_le16(0x02);
478*4882a593Smuzhiyun     pMUXMsg->GetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2
479*4882a593Smuzhiyun     pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->pdp;
480*4882a593Smuzhiyun     return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG);
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun 
WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg,void * arg)483*4882a593Smuzhiyun static USHORT WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) {
484*4882a593Smuzhiyun     USHORT TLVLength = 0;
485*4882a593Smuzhiyun     UCHAR *pTLV;
486*4882a593Smuzhiyun     PROFILE_T *profile = (PROFILE_T *)arg;
487*4882a593Smuzhiyun     PQMIWDS_PDPTYPE pPdpType;
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun     pMUXMsg->ModifyProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) - 4);
490*4882a593Smuzhiyun     pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01;
491*4882a593Smuzhiyun     pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02);
492*4882a593Smuzhiyun     pMUXMsg->ModifyProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2
493*4882a593Smuzhiyun     pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdp;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun     pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun     pPdpType = (PQMIWDS_PDPTYPE)(pTLV + TLVLength);
498*4882a593Smuzhiyun     pPdpType->TLVType = 0x11;
499*4882a593Smuzhiyun     pPdpType->TLVLength = cpu_to_le16(0x01);
500*4882a593Smuzhiyun // 0 ?C PDP-IP (IPv4)
501*4882a593Smuzhiyun // 1 ?C PDP-PPP
502*4882a593Smuzhiyun // 2 ?C PDP-IPv6
503*4882a593Smuzhiyun // 3 ?C PDP-IPv4v6
504*4882a593Smuzhiyun     if (profile->enable_ipv4 && profile->enable_ipv6)
505*4882a593Smuzhiyun         pPdpType->PdpType = 3;
506*4882a593Smuzhiyun     else if (profile->enable_ipv6)
507*4882a593Smuzhiyun     	pPdpType->PdpType = 2;
508*4882a593Smuzhiyun 	else
509*4882a593Smuzhiyun         pPdpType->PdpType = 0;
510*4882a593Smuzhiyun     TLVLength +=(le16_to_cpu(pPdpType->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun     // Set APN Name
513*4882a593Smuzhiyun     if (profile->apn) {
514*4882a593Smuzhiyun         PQMIWDS_APNNAME pApnName = (PQMIWDS_APNNAME)(pTLV + TLVLength);
515*4882a593Smuzhiyun         pApnName->TLVType = 0x14;
516*4882a593Smuzhiyun         pApnName->TLVLength = cpu_to_le16(strlen(profile->apn));
517*4882a593Smuzhiyun         qstrcpy((char *)&pApnName->ApnName, profile->apn);
518*4882a593Smuzhiyun         TLVLength +=(le16_to_cpu(pApnName->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
519*4882a593Smuzhiyun     }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun     // Set User Name
522*4882a593Smuzhiyun     if (profile->user) {
523*4882a593Smuzhiyun         PQMIWDS_USERNAME pUserName = (PQMIWDS_USERNAME)(pTLV + TLVLength);
524*4882a593Smuzhiyun         pUserName->TLVType = 0x1B;
525*4882a593Smuzhiyun         pUserName->TLVLength = cpu_to_le16(strlen(profile->user));
526*4882a593Smuzhiyun         qstrcpy((char *)&pUserName->UserName, profile->user);
527*4882a593Smuzhiyun         TLVLength += (le16_to_cpu(pUserName->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
528*4882a593Smuzhiyun     }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     // Set Password
531*4882a593Smuzhiyun     if (profile->password) {
532*4882a593Smuzhiyun         PQMIWDS_PASSWD pPasswd = (PQMIWDS_PASSWD)(pTLV + TLVLength);
533*4882a593Smuzhiyun         pPasswd->TLVType = 0x1C;
534*4882a593Smuzhiyun         pPasswd->TLVLength = cpu_to_le16(strlen(profile->password));
535*4882a593Smuzhiyun         qstrcpy((char *)&pPasswd->Passwd, profile->password);
536*4882a593Smuzhiyun         TLVLength +=(le16_to_cpu(pPasswd->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
537*4882a593Smuzhiyun     }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun     // Set Auth Protocol
540*4882a593Smuzhiyun     if (profile->user && profile->password) {
541*4882a593Smuzhiyun         PQMIWDS_AUTH_PREFERENCE pAuthPref = (PQMIWDS_AUTH_PREFERENCE)(pTLV + TLVLength);
542*4882a593Smuzhiyun         pAuthPref->TLVType = 0x1D;
543*4882a593Smuzhiyun         pAuthPref->TLVLength = cpu_to_le16(0x01);
544*4882a593Smuzhiyun         pAuthPref->AuthPreference = profile->auth; // 0 ~ None, 1 ~ Pap, 2 ~ Chap, 3 ~ MsChapV2
545*4882a593Smuzhiyun         TLVLength += (le16_to_cpu(pAuthPref->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
546*4882a593Smuzhiyun     }
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun     return sizeof(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG) + TLVLength;
549*4882a593Smuzhiyun }
550*4882a593Smuzhiyun #endif
551*4882a593Smuzhiyun 
WdsGetRuntimeSettingReq(PQMUX_MSG pMUXMsg,void * arg)552*4882a593Smuzhiyun static USHORT WdsGetRuntimeSettingReq(PQMUX_MSG pMUXMsg, void *arg)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun     (void)arg;
555*4882a593Smuzhiyun     pMUXMsg->GetRuntimeSettingsReq.TLVType = 0x10;
556*4882a593Smuzhiyun     pMUXMsg->GetRuntimeSettingsReq.TLVLength = cpu_to_le16(0x04);
557*4882a593Smuzhiyun     // the following mask also applies to IPV6
558*4882a593Smuzhiyun     pMUXMsg->GetRuntimeSettingsReq.Mask = cpu_to_le32(QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR |
559*4882a593Smuzhiyun                                                       QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR |
560*4882a593Smuzhiyun                                                       QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU |
561*4882a593Smuzhiyun                                                       QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR) |
562*4882a593Smuzhiyun                                           QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR |
563*4882a593Smuzhiyun                                           QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun     return sizeof(QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG);
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun static PQCQMIMSG s_pRequest;
569*4882a593Smuzhiyun static PQCQMIMSG s_pResponse;
570*4882a593Smuzhiyun 
is_response(const PQCQMIMSG pRequest,const PQCQMIMSG pResponse)571*4882a593Smuzhiyun static int is_response(const PQCQMIMSG pRequest, const PQCQMIMSG pResponse) {
572*4882a593Smuzhiyun     if ((pRequest->QMIHdr.QMIType == pResponse->QMIHdr.QMIType)
573*4882a593Smuzhiyun         && (pRequest->QMIHdr.ClientId == pResponse->QMIHdr.ClientId)) {
574*4882a593Smuzhiyun             USHORT requestTID, responseTID;
575*4882a593Smuzhiyun         if (pRequest->QMIHdr.QMIType == QMUX_TYPE_CTL) {
576*4882a593Smuzhiyun             requestTID = pRequest->CTLMsg.QMICTLMsgHdr.TransactionId;
577*4882a593Smuzhiyun             responseTID = pResponse->CTLMsg.QMICTLMsgHdr.TransactionId;
578*4882a593Smuzhiyun         } else {
579*4882a593Smuzhiyun             requestTID = le16_to_cpu(pRequest->MUXMsg.QMUXHdr.TransactionId);
580*4882a593Smuzhiyun             responseTID = le16_to_cpu(pResponse->MUXMsg.QMUXHdr.TransactionId);
581*4882a593Smuzhiyun         }
582*4882a593Smuzhiyun         return (requestTID == responseTID);
583*4882a593Smuzhiyun     }
584*4882a593Smuzhiyun     return 0;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun int (*qmidev_send)(PQCQMIMSG pRequest);
588*4882a593Smuzhiyun 
QmiThreadSendQMITimeout(PQCQMIMSG pRequest,PQCQMIMSG * ppResponse,unsigned msecs,const char * funcname)589*4882a593Smuzhiyun int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname) {
590*4882a593Smuzhiyun     int ret;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun     if (!pRequest)
593*4882a593Smuzhiyun         return -EINVAL;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun     pthread_mutex_lock(&cm_command_mutex);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun     if (ppResponse)
598*4882a593Smuzhiyun         *ppResponse = NULL;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun     dump_qmi(pRequest, le16_to_cpu(pRequest->QMIHdr.Length) + 1);
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun     s_pRequest = pRequest;
603*4882a593Smuzhiyun     s_pResponse = NULL;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     ret = qmidev_send(pRequest);
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun     if (ret == 0) {
608*4882a593Smuzhiyun         ret = pthread_cond_timeout_np(&cm_command_cond, &cm_command_mutex, msecs);
609*4882a593Smuzhiyun         if (!ret) {
610*4882a593Smuzhiyun             if (s_pResponse && ppResponse) {
611*4882a593Smuzhiyun                 *ppResponse = s_pResponse;
612*4882a593Smuzhiyun             } else {
613*4882a593Smuzhiyun                 if (s_pResponse) {
614*4882a593Smuzhiyun                     free(s_pResponse);
615*4882a593Smuzhiyun                     s_pResponse = NULL;
616*4882a593Smuzhiyun                 }
617*4882a593Smuzhiyun             }
618*4882a593Smuzhiyun         } else {
619*4882a593Smuzhiyun             dbg_time("%s message timeout", funcname);
620*4882a593Smuzhiyun         }
621*4882a593Smuzhiyun     }
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun     pthread_mutex_unlock(&cm_command_mutex);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun     return ret;
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun 
QmiThreadRecvQMI(PQCQMIMSG pResponse)628*4882a593Smuzhiyun void QmiThreadRecvQMI(PQCQMIMSG pResponse) {
629*4882a593Smuzhiyun     pthread_mutex_lock(&cm_command_mutex);
630*4882a593Smuzhiyun     if (pResponse == NULL) {
631*4882a593Smuzhiyun         if (s_pRequest) {
632*4882a593Smuzhiyun             free(s_pRequest);
633*4882a593Smuzhiyun             s_pRequest = NULL;
634*4882a593Smuzhiyun             s_pResponse = NULL;
635*4882a593Smuzhiyun             pthread_cond_signal(&cm_command_cond);
636*4882a593Smuzhiyun         }
637*4882a593Smuzhiyun         pthread_mutex_unlock(&cm_command_mutex);
638*4882a593Smuzhiyun         return;
639*4882a593Smuzhiyun     }
640*4882a593Smuzhiyun     dump_qmi(pResponse, le16_to_cpu(pResponse->QMIHdr.Length) + 1);
641*4882a593Smuzhiyun     if (s_pRequest && is_response(s_pRequest, pResponse)) {
642*4882a593Smuzhiyun         free(s_pRequest);
643*4882a593Smuzhiyun         s_pRequest = NULL;
644*4882a593Smuzhiyun         s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1);
645*4882a593Smuzhiyun         if (s_pResponse != NULL) {
646*4882a593Smuzhiyun             memcpy(s_pResponse, pResponse, le16_to_cpu(pResponse->QMIHdr.Length) + 1);
647*4882a593Smuzhiyun         }
648*4882a593Smuzhiyun         pthread_cond_signal(&cm_command_cond);
649*4882a593Smuzhiyun     } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_CTL)
650*4882a593Smuzhiyun                     && (le16_to_cpu(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMICTLType == QMICTL_REVOKE_CLIENT_ID_IND))) {
651*4882a593Smuzhiyun         qmidevice_send_event_to_main(MODEM_REPORT_RESET_EVENT);
652*4882a593Smuzhiyun     } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS)
653*4882a593Smuzhiyun                     && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMINAS_SERVING_SYSTEM_IND)) {
654*4882a593Smuzhiyun         qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
655*4882a593Smuzhiyun     } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS)
656*4882a593Smuzhiyun                     && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMIWDS_GET_PKT_SRVC_STATUS_IND)) {
657*4882a593Smuzhiyun         qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED);
658*4882a593Smuzhiyun     } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_NAS)
659*4882a593Smuzhiyun                     && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMINAS_SYS_INFO_IND)) {
660*4882a593Smuzhiyun         qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
661*4882a593Smuzhiyun     } else if ((pResponse->QMIHdr.QMIType == QMUX_TYPE_WDS_ADMIN)
662*4882a593Smuzhiyun                     && (le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.Type) == QMI_WDA_SET_LOOPBACK_CONFIG_IND)) {
663*4882a593Smuzhiyun     	qmidevice_send_event_to_main_ext(RIL_UNSOL_LOOPBACK_CONFIG_IND,
664*4882a593Smuzhiyun             &pResponse->MUXMsg.SetLoopBackInd, sizeof(pResponse->MUXMsg.SetLoopBackInd));
665*4882a593Smuzhiyun     } else {
666*4882a593Smuzhiyun         if (debug_qmi)
667*4882a593Smuzhiyun             dbg_time("nobody care this qmi msg!!");
668*4882a593Smuzhiyun     }
669*4882a593Smuzhiyun     pthread_mutex_unlock(&cm_command_mutex);
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
requestSetEthMode(PROFILE_T * profile)672*4882a593Smuzhiyun static int requestSetEthMode(PROFILE_T *profile) {
673*4882a593Smuzhiyun     PQCQMIMSG pRequest;
674*4882a593Smuzhiyun     PQCQMIMSG pResponse = NULL;
675*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
676*4882a593Smuzhiyun     int err;
677*4882a593Smuzhiyun     PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV linkProto;
678*4882a593Smuzhiyun     UCHAR IpPreference;
679*4882a593Smuzhiyun     UCHAR autoconnect_setting = 0;
680*4882a593Smuzhiyun     QMAP_SETTING qmap_settings = {0};
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun     qmap_settings.size = sizeof(qmap_settings);
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun     if (profile->qmap_mode) {
685*4882a593Smuzhiyun         profile->rawIP = 1;
686*4882a593Smuzhiyun         s_9x07 = profile->rawIP;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun         qmap_settings.MuxId = profile->muxid;
689*4882a593Smuzhiyun 
690*4882a593Smuzhiyun         if (qmidev_is_pciemhi(profile->qmichannel)) { //SDX20_PCIE
691*4882a593Smuzhiyun             qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB
692*4882a593Smuzhiyun             qmap_settings.ep_type = DATA_EP_TYPE_PCIE;
693*4882a593Smuzhiyun             qmap_settings.iface_id = 0x04;
694*4882a593Smuzhiyun         }
695*4882a593Smuzhiyun         else { // for MDM9x07&MDM9x40&SDX20 USB
696*4882a593Smuzhiyun             qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB
697*4882a593Smuzhiyun             qmap_settings.ep_type = DATA_EP_TYPE_HSUSB;
698*4882a593Smuzhiyun             qmap_settings.iface_id = 0x04;
699*4882a593Smuzhiyun         }
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun         qmap_settings.ul_data_aggregation_max_datagrams = 11; //by test result, 11 can get best TPUT
702*4882a593Smuzhiyun         qmap_settings.ul_data_aggregation_max_size = 8*1024;
703*4882a593Smuzhiyun         qmap_settings.dl_minimum_padding = 0; //no effect when register to real netowrk
704*4882a593Smuzhiyun         if(profile->qmap_version != 0x09)
705*4882a593Smuzhiyun             profile->qmap_version = 0x05;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun         qmap_version = profile->qmap_version;
708*4882a593Smuzhiyun         if (profile->rmnet_info.size) {
709*4882a593Smuzhiyun             qmap_settings.rx_urb_size = profile->rmnet_info.rx_urb_size;
710*4882a593Smuzhiyun             qmap_settings.ep_type = profile->rmnet_info.ep_type;
711*4882a593Smuzhiyun             qmap_settings.iface_id = profile->rmnet_info.iface_id;
712*4882a593Smuzhiyun             qmap_settings.dl_minimum_padding = profile->rmnet_info.dl_minimum_padding;
713*4882a593Smuzhiyun             qmap_version = profile->rmnet_info.qmap_version;
714*4882a593Smuzhiyun         }
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun         if (!profile->wda_client) {
717*4882a593Smuzhiyun             if (qmidev_is_gobinet(profile->qmichannel)) {
718*4882a593Smuzhiyun                 //when QMAP enabled, set data format in GobiNet driver
719*4882a593Smuzhiyun             }
720*4882a593Smuzhiyun             else if (profile->proxy[0]) {
721*4882a593Smuzhiyun                 /* the first running 'quectel-cm' had alloc wda client and set data format,
722*4882a593Smuzhiyun                    so we can ingore to set data format here. */
723*4882a593Smuzhiyun             }
724*4882a593Smuzhiyun             goto skip_WdaSetDataFormat;
725*4882a593Smuzhiyun         }
726*4882a593Smuzhiyun     }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_ADMIN, QMIWDS_ADMIN_SET_DATA_FORMAT_REQ, WdaSetDataFormat, (void *)&qmap_settings);
729*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
730*4882a593Smuzhiyun     qmi_rsp_check_and_return();
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun     linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
733*4882a593Smuzhiyun     if (linkProto != NULL) {
734*4882a593Smuzhiyun         profile->rawIP = (le32_to_cpu(linkProto->Value) == 2);
735*4882a593Smuzhiyun         s_9x07 = profile->rawIP; //MDM90x7 only support RAW IP, do not support Eth
736*4882a593Smuzhiyun     }
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun     linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x16);
739*4882a593Smuzhiyun     if (linkProto != NULL && profile->qmap_mode) {
740*4882a593Smuzhiyun         qmap_settings.rx_urb_size = le32_to_cpu(linkProto->Value);
741*4882a593Smuzhiyun         dbg_time("qmap_settings.rx_urb_size = %u", qmap_settings.rx_urb_size); //must same as rx_urb_size defined in GobiNet&qmi_wwan driver
742*4882a593Smuzhiyun     }
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun #ifdef QUECTEL_UL_DATA_AGG
745*4882a593Smuzhiyun     if (qmap_settings.ul_data_aggregation_max_datagrams)
746*4882a593Smuzhiyun     {
747*4882a593Smuzhiyun         linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x17);
748*4882a593Smuzhiyun         if (linkProto != NULL) {
749*4882a593Smuzhiyun             qmap_settings.ul_data_aggregation_max_datagrams = MIN(qmap_settings.ul_data_aggregation_max_datagrams, le32_to_cpu(linkProto->Value));
750*4882a593Smuzhiyun             dbg_time("qmap_settings.ul_data_aggregation_max_datagrams  = %u", qmap_settings.ul_data_aggregation_max_datagrams);
751*4882a593Smuzhiyun         }
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun         linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x18);
754*4882a593Smuzhiyun         if (linkProto != NULL) {
755*4882a593Smuzhiyun             qmap_settings.ul_data_aggregation_max_size = MIN(qmap_settings.ul_data_aggregation_max_size, le32_to_cpu(linkProto->Value));
756*4882a593Smuzhiyun             dbg_time("qmap_settings.ul_data_aggregation_max_size       = %u", qmap_settings.ul_data_aggregation_max_size);
757*4882a593Smuzhiyun         }
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun         linkProto = (PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1A);
760*4882a593Smuzhiyun         if (linkProto != NULL) {
761*4882a593Smuzhiyun             qmap_settings.dl_minimum_padding = le32_to_cpu(linkProto->Value);
762*4882a593Smuzhiyun             dbg_time("qmap_settings.dl_minimum_padding                 = %u", qmap_settings.dl_minimum_padding);
763*4882a593Smuzhiyun         }
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	if (qmap_settings.ul_data_aggregation_max_datagrams > 1) {
766*4882a593Smuzhiyun 		ql_set_driver_qmap_setting(profile, &qmap_settings);
767*4882a593Smuzhiyun 	}
768*4882a593Smuzhiyun     }
769*4882a593Smuzhiyun #endif
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun     free(pResponse);
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun skip_WdaSetDataFormat:
774*4882a593Smuzhiyun     if (profile->enable_ipv4) {
775*4882a593Smuzhiyun     	if (profile->qmapnet_adapter[0]) {
776*4882a593Smuzhiyun             // bind wds mux data port
777*4882a593Smuzhiyun         	pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_BIND_MUX_DATA_PORT_REQ , WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings);
778*4882a593Smuzhiyun         	err = QmiThreadSendQMI(pRequest, &pResponse);
779*4882a593Smuzhiyun         	qmi_rsp_check_and_return();
780*4882a593Smuzhiyun         	if (pResponse) free(pResponse);
781*4882a593Smuzhiyun         }
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun         // set ipv4
784*4882a593Smuzhiyun     	IpPreference = IpFamilyV4;
785*4882a593Smuzhiyun     	pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, WdsSetClientIPFamilyPref, (void *)&IpPreference);
786*4882a593Smuzhiyun     	err = QmiThreadSendQMI(pRequest, &pResponse);
787*4882a593Smuzhiyun     	if (pResponse) free(pResponse);
788*4882a593Smuzhiyun     }
789*4882a593Smuzhiyun 
790*4882a593Smuzhiyun     if (profile->enable_ipv6) {
791*4882a593Smuzhiyun         if (profile->qmapnet_adapter[0]) {
792*4882a593Smuzhiyun             // bind wds ipv6 mux data port
793*4882a593Smuzhiyun             pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_IPV6, QMIWDS_BIND_MUX_DATA_PORT_REQ , WdsSetQMUXBindMuxDataPort, (void *)&qmap_settings);
794*4882a593Smuzhiyun             err = QmiThreadSendQMI(pRequest, &pResponse);
795*4882a593Smuzhiyun             qmi_rsp_check_and_return();
796*4882a593Smuzhiyun             if (pResponse) free(pResponse);
797*4882a593Smuzhiyun         }
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun         // set ipv6
800*4882a593Smuzhiyun         IpPreference = IpFamilyV6;
801*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_IPV6, QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ, WdsSetClientIPFamilyPref, (void *)&IpPreference);
802*4882a593Smuzhiyun         err = QmiThreadSendQMI(pRequest, &pResponse);
803*4882a593Smuzhiyun         qmi_rsp_check_and_return();
804*4882a593Smuzhiyun         if (pResponse) free(pResponse);
805*4882a593Smuzhiyun     }
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_SET_AUTO_CONNECT_REQ , WdsSetAutoConnect, (void *)&autoconnect_setting);
808*4882a593Smuzhiyun     QmiThreadSendQMI(pRequest, &pResponse);
809*4882a593Smuzhiyun     if (pResponse) free(pResponse);
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun     return 0;
812*4882a593Smuzhiyun }
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun #ifdef CONFIG_SIM
requestGetPINStatus(SIM_Status * pSIMStatus)815*4882a593Smuzhiyun static int requestGetPINStatus(SIM_Status *pSIMStatus) {
816*4882a593Smuzhiyun     PQCQMIMSG pRequest;
817*4882a593Smuzhiyun     PQCQMIMSG pResponse;
818*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
819*4882a593Smuzhiyun     int err;
820*4882a593Smuzhiyun     PQMIDMS_UIM_PIN_STATUS pPin1Status = NULL;
821*4882a593Smuzhiyun     //PQMIDMS_UIM_PIN_STATUS pPin2Status = NULL;
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun     if (s_9x07)
824*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, NULL, NULL);
825*4882a593Smuzhiyun     else
826*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_PIN_STATUS_REQ, NULL, NULL);
827*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
828*4882a593Smuzhiyun     qmi_rsp_check_and_return();
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun     pPin1Status = (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
831*4882a593Smuzhiyun     //pPin2Status = (PQMIDMS_UIM_PIN_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12);
832*4882a593Smuzhiyun 
833*4882a593Smuzhiyun     if (pPin1Status != NULL) {
834*4882a593Smuzhiyun         if (pPin1Status->PINStatus == QMI_PIN_STATUS_NOT_VERIF) {
835*4882a593Smuzhiyun             *pSIMStatus = SIM_PIN;
836*4882a593Smuzhiyun         } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_BLOCKED) {
837*4882a593Smuzhiyun             *pSIMStatus = SIM_PUK;
838*4882a593Smuzhiyun         } else if (pPin1Status->PINStatus == QMI_PIN_STATUS_PERM_BLOCKED) {
839*4882a593Smuzhiyun             *pSIMStatus = SIM_BAD;
840*4882a593Smuzhiyun         }
841*4882a593Smuzhiyun     }
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun     free(pResponse);
844*4882a593Smuzhiyun     return 0;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun 
requestGetSIMStatus(SIM_Status * pSIMStatus)847*4882a593Smuzhiyun static int requestGetSIMStatus(SIM_Status *pSIMStatus) { //RIL_REQUEST_GET_SIM_STATUS
848*4882a593Smuzhiyun     PQCQMIMSG pRequest;
849*4882a593Smuzhiyun     PQCQMIMSG pResponse;
850*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
851*4882a593Smuzhiyun     int err;
852*4882a593Smuzhiyun     const char * SIM_Status_String[] = {
853*4882a593Smuzhiyun         "SIM_ABSENT",
854*4882a593Smuzhiyun         "SIM_NOT_READY",
855*4882a593Smuzhiyun         "SIM_READY", /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */
856*4882a593Smuzhiyun         "SIM_PIN",
857*4882a593Smuzhiyun         "SIM_PUK",
858*4882a593Smuzhiyun         "SIM_NETWORK_PERSONALIZATION"
859*4882a593Smuzhiyun     };
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun     if (s_9x07)
862*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_GET_CARD_STATUS_REQ, NULL, NULL);
863*4882a593Smuzhiyun     else
864*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_STATE_REQ, NULL, NULL);
865*4882a593Smuzhiyun 
866*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
867*4882a593Smuzhiyun     qmi_rsp_check_and_return();
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun     *pSIMStatus = SIM_ABSENT;
870*4882a593Smuzhiyun     if (s_9x07)
871*4882a593Smuzhiyun     {
872*4882a593Smuzhiyun         PQMIUIM_CARD_STATUS pCardStatus = NULL;
873*4882a593Smuzhiyun         PQMIUIM_PIN_STATE pPINState = NULL;
874*4882a593Smuzhiyun         UCHAR CardState = 0x01;
875*4882a593Smuzhiyun         UCHAR PIN1State = QMI_PIN_STATUS_NOT_VERIF;
876*4882a593Smuzhiyun         //UCHAR PIN1Retries;
877*4882a593Smuzhiyun         //UCHAR PUK1Retries;
878*4882a593Smuzhiyun         //UCHAR PIN2State;
879*4882a593Smuzhiyun         //UCHAR PIN2Retries;
880*4882a593Smuzhiyun         //UCHAR PUK2Retries;
881*4882a593Smuzhiyun 
882*4882a593Smuzhiyun         pCardStatus = (PQMIUIM_CARD_STATUS)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10);
883*4882a593Smuzhiyun         if (pCardStatus != NULL)
884*4882a593Smuzhiyun         {
885*4882a593Smuzhiyun             pPINState = (PQMIUIM_PIN_STATE)((PUCHAR)pCardStatus + sizeof(QMIUIM_CARD_STATUS) + pCardStatus->AIDLength);
886*4882a593Smuzhiyun             CardState  = pCardStatus->CardState;
887*4882a593Smuzhiyun             if (CardState == UIM_CARD_STATE_PRESENT) {
888*4882a593Smuzhiyun                 if (pPINState->UnivPIN == 1)
889*4882a593Smuzhiyun                 {
890*4882a593Smuzhiyun                    PIN1State = pCardStatus->UPINState;
891*4882a593Smuzhiyun                    //PIN1Retries = pCardStatus->UPINRetries;
892*4882a593Smuzhiyun                    //PUK1Retries = pCardStatus->UPUKRetries;
893*4882a593Smuzhiyun                 }
894*4882a593Smuzhiyun                 else
895*4882a593Smuzhiyun                 {
896*4882a593Smuzhiyun                    PIN1State = pPINState->PIN1State;
897*4882a593Smuzhiyun                    //PIN1Retries = pPINState->PIN1Retries;
898*4882a593Smuzhiyun                    //PUK1Retries = pPINState->PUK1Retries;
899*4882a593Smuzhiyun                 }
900*4882a593Smuzhiyun                 //PIN2State = pPINState->PIN2State;
901*4882a593Smuzhiyun                 //PIN2Retries = pPINState->PIN2Retries;
902*4882a593Smuzhiyun                 //PUK2Retries = pPINState->PUK2Retries;
903*4882a593Smuzhiyun             }
904*4882a593Smuzhiyun         }
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun         *pSIMStatus = SIM_ABSENT;
907*4882a593Smuzhiyun         if ((CardState == 0x01) &&  ((PIN1State == QMI_PIN_STATUS_VERIFIED)|| (PIN1State == QMI_PIN_STATUS_DISABLED)))
908*4882a593Smuzhiyun         {
909*4882a593Smuzhiyun             *pSIMStatus = SIM_READY;
910*4882a593Smuzhiyun         }
911*4882a593Smuzhiyun         else if (CardState == 0x01)
912*4882a593Smuzhiyun         {
913*4882a593Smuzhiyun             if (PIN1State == QMI_PIN_STATUS_NOT_VERIF)
914*4882a593Smuzhiyun             {
915*4882a593Smuzhiyun                 *pSIMStatus = SIM_PIN;
916*4882a593Smuzhiyun             }
917*4882a593Smuzhiyun             if ( PIN1State == QMI_PIN_STATUS_BLOCKED)
918*4882a593Smuzhiyun             {
919*4882a593Smuzhiyun                 *pSIMStatus = SIM_PUK;
920*4882a593Smuzhiyun             }
921*4882a593Smuzhiyun             else if (PIN1State == QMI_PIN_STATUS_PERM_BLOCKED)
922*4882a593Smuzhiyun             {
923*4882a593Smuzhiyun                 *pSIMStatus = SIM_BAD;
924*4882a593Smuzhiyun             }
925*4882a593Smuzhiyun             else if (PIN1State == QMI_PIN_STATUS_NOT_INIT || PIN1State == QMI_PIN_STATUS_VERIFIED || PIN1State == QMI_PIN_STATUS_DISABLED)
926*4882a593Smuzhiyun             {
927*4882a593Smuzhiyun                 *pSIMStatus = SIM_READY;
928*4882a593Smuzhiyun             }
929*4882a593Smuzhiyun         }
930*4882a593Smuzhiyun         else if (CardState == 0x00 || CardState == 0x02)
931*4882a593Smuzhiyun         {
932*4882a593Smuzhiyun         }
933*4882a593Smuzhiyun         else
934*4882a593Smuzhiyun         {
935*4882a593Smuzhiyun         }
936*4882a593Smuzhiyun     }
937*4882a593Smuzhiyun     else
938*4882a593Smuzhiyun     {
939*4882a593Smuzhiyun     //UIM state. Values:
940*4882a593Smuzhiyun     // 0x00  UIM initialization completed
941*4882a593Smuzhiyun     // 0x01  UIM is locked or the UIM failed
942*4882a593Smuzhiyun     // 0x02  UIM is not present
943*4882a593Smuzhiyun     // 0x03  Reserved
944*4882a593Smuzhiyun     // 0xFF  UIM state is currently
945*4882a593Smuzhiyun     //unavailable
946*4882a593Smuzhiyun         if (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x00) {
947*4882a593Smuzhiyun             *pSIMStatus = SIM_READY;
948*4882a593Smuzhiyun         } else if (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x01) {
949*4882a593Smuzhiyun             *pSIMStatus = SIM_ABSENT;
950*4882a593Smuzhiyun             err = requestGetPINStatus(pSIMStatus);
951*4882a593Smuzhiyun         } else if ((pResponse->MUXMsg.UIMGetStateResp.UIMState == 0x02) || (pResponse->MUXMsg.UIMGetStateResp.UIMState == 0xFF)) {
952*4882a593Smuzhiyun             *pSIMStatus = SIM_ABSENT;
953*4882a593Smuzhiyun         } else {
954*4882a593Smuzhiyun             *pSIMStatus = SIM_ABSENT;
955*4882a593Smuzhiyun         }
956*4882a593Smuzhiyun     }
957*4882a593Smuzhiyun     dbg_time("%s SIMStatus: %s", __func__, SIM_Status_String[*pSIMStatus]);
958*4882a593Smuzhiyun 
959*4882a593Smuzhiyun     free(pResponse);
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun     return 0;
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
requestEnterSimPin(const CHAR * pPinCode)964*4882a593Smuzhiyun static int requestEnterSimPin(const CHAR *pPinCode) {
965*4882a593Smuzhiyun     PQCQMIMSG pRequest;
966*4882a593Smuzhiyun     PQCQMIMSG pResponse;
967*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
968*4882a593Smuzhiyun     int err;
969*4882a593Smuzhiyun 
970*4882a593Smuzhiyun     if (s_9x07)
971*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_VERIFY_PIN_REQ, UimVerifyPinReqSend, (void *)pPinCode);
972*4882a593Smuzhiyun     else
973*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_VERIFY_PIN_REQ, DmsUIMVerifyPinReqSend, (void *)pPinCode);
974*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
975*4882a593Smuzhiyun     qmi_rsp_check_and_return();
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun     free(pResponse);
978*4882a593Smuzhiyun     return 0;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun #endif
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun #ifdef CONFIG_IMSI_ICCID
requestGetICCID(void)983*4882a593Smuzhiyun static int requestGetICCID(void) { //RIL_REQUEST_GET_IMSI
984*4882a593Smuzhiyun     PQCQMIMSG pRequest;
985*4882a593Smuzhiyun     PQCQMIMSG pResponse;
986*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
987*4882a593Smuzhiyun     PQMIUIM_CONTENT pUimContent;
988*4882a593Smuzhiyun     int err;
989*4882a593Smuzhiyun 
990*4882a593Smuzhiyun     if (s_9x07) {
991*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, UimReadTransparentIMSIReqSend, (void *)"EF_ICCID");
992*4882a593Smuzhiyun         err = QmiThreadSendQMI(pRequest, &pResponse);
993*4882a593Smuzhiyun     } else {
994*4882a593Smuzhiyun         return 0;
995*4882a593Smuzhiyun     }
996*4882a593Smuzhiyun     qmi_rsp_check_and_return();
997*4882a593Smuzhiyun 
998*4882a593Smuzhiyun     pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
999*4882a593Smuzhiyun     if (pUimContent != NULL) {
1000*4882a593Smuzhiyun         static char DeviceICCID[32] = {'\0'};
1001*4882a593Smuzhiyun         int i = 0, j = 0;
1002*4882a593Smuzhiyun 
1003*4882a593Smuzhiyun         for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content_len); ++i) {
1004*4882a593Smuzhiyun             char charmaps[] = "0123456789ABCDEF";
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun             DeviceICCID[j++] = charmaps[(pUimContent->content[i] & 0x0F)];
1007*4882a593Smuzhiyun             DeviceICCID[j++] = charmaps[((pUimContent->content[i] & 0xF0) >> 0x04)];
1008*4882a593Smuzhiyun         }
1009*4882a593Smuzhiyun         DeviceICCID[j] = '\0';
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun         dbg_time("%s DeviceICCID: %s", __func__, DeviceICCID);
1012*4882a593Smuzhiyun     }
1013*4882a593Smuzhiyun 
1014*4882a593Smuzhiyun     free(pResponse);
1015*4882a593Smuzhiyun     return 0;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun 
requestGetIMSI(void)1018*4882a593Smuzhiyun static int requestGetIMSI(void) { //RIL_REQUEST_GET_IMSI
1019*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1020*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1021*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1022*4882a593Smuzhiyun     PQMIUIM_CONTENT pUimContent;
1023*4882a593Smuzhiyun     int err;
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun     if (s_9x07) {
1026*4882a593Smuzhiyun         pRequest = ComposeQMUXMsg(QMUX_TYPE_UIM, QMIUIM_READ_TRANSPARENT_REQ, UimReadTransparentIMSIReqSend, (void *)"EF_IMSI");
1027*4882a593Smuzhiyun         err = QmiThreadSendQMI(pRequest, &pResponse);
1028*4882a593Smuzhiyun     } else {
1029*4882a593Smuzhiyun         return 0;
1030*4882a593Smuzhiyun     }
1031*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun     pUimContent = (PQMIUIM_CONTENT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
1034*4882a593Smuzhiyun     if (pUimContent != NULL) {
1035*4882a593Smuzhiyun         static char DeviceIMSI[32] = {'\0'};
1036*4882a593Smuzhiyun         int i = 0, j = 0;
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun         for (i = 0, j = 0; i < le16_to_cpu(pUimContent->content[0]); ++i) {
1039*4882a593Smuzhiyun             if (i != 0)
1040*4882a593Smuzhiyun                 DeviceIMSI[j++] = (pUimContent->content[i+1] & 0x0F) + '0';
1041*4882a593Smuzhiyun             DeviceIMSI[j++] = ((pUimContent->content[i+1] & 0xF0) >> 0x04) + '0';
1042*4882a593Smuzhiyun         }
1043*4882a593Smuzhiyun         DeviceIMSI[j] = '\0';
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun         dbg_time("%s DeviceIMSI: %s", __func__, DeviceIMSI);
1046*4882a593Smuzhiyun     }
1047*4882a593Smuzhiyun 
1048*4882a593Smuzhiyun     free(pResponse);
1049*4882a593Smuzhiyun     return 0;
1050*4882a593Smuzhiyun }
1051*4882a593Smuzhiyun #endif
1052*4882a593Smuzhiyun 
1053*4882a593Smuzhiyun #if 1
quectel_convert_cdma_mcc_2_ascii_mcc(USHORT * p_mcc,USHORT mcc)1054*4882a593Smuzhiyun static void quectel_convert_cdma_mcc_2_ascii_mcc( USHORT *p_mcc, USHORT mcc )
1055*4882a593Smuzhiyun {
1056*4882a593Smuzhiyun   unsigned int d1, d2, d3, buf = mcc + 111;
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun   if ( mcc == 0x3FF ) // wildcard
1059*4882a593Smuzhiyun   {
1060*4882a593Smuzhiyun     *p_mcc = 3;
1061*4882a593Smuzhiyun   }
1062*4882a593Smuzhiyun   else
1063*4882a593Smuzhiyun   {
1064*4882a593Smuzhiyun     d3 = buf % 10;
1065*4882a593Smuzhiyun     buf = ( d3 == 0 ) ? (buf-10)/10 : buf/10;
1066*4882a593Smuzhiyun 
1067*4882a593Smuzhiyun     d2 = buf % 10;
1068*4882a593Smuzhiyun     buf = ( d2 == 0 ) ? (buf-10)/10 : buf/10;
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun     d1 = ( buf == 10 ) ? 0 : buf;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun //dbg_time("d1:%d, d2:%d,d3:%d",d1,d2,d3);
1073*4882a593Smuzhiyun     if ( d1<10 && d2<10 && d3<10 )
1074*4882a593Smuzhiyun     {
1075*4882a593Smuzhiyun     *p_mcc = d1*100+d2*10+d3;
1076*4882a593Smuzhiyun #if 0
1077*4882a593Smuzhiyun       *(p_mcc+0) = '0' + d1;
1078*4882a593Smuzhiyun       *(p_mcc+1) = '0' + d2;
1079*4882a593Smuzhiyun       *(p_mcc+2) = '0' + d3;
1080*4882a593Smuzhiyun #endif
1081*4882a593Smuzhiyun     }
1082*4882a593Smuzhiyun     else
1083*4882a593Smuzhiyun     {
1084*4882a593Smuzhiyun       //dbg_time( "invalid digits %d %d %d", d1, d2, d3 );
1085*4882a593Smuzhiyun       *p_mcc = 0;
1086*4882a593Smuzhiyun     }
1087*4882a593Smuzhiyun   }
1088*4882a593Smuzhiyun }
1089*4882a593Smuzhiyun 
quectel_convert_cdma_mnc_2_ascii_mnc(USHORT * p_mnc,USHORT imsi_11_12)1090*4882a593Smuzhiyun static void quectel_convert_cdma_mnc_2_ascii_mnc( USHORT *p_mnc, USHORT imsi_11_12)
1091*4882a593Smuzhiyun {
1092*4882a593Smuzhiyun   unsigned int d1, d2, buf = imsi_11_12 + 11;
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun   if ( imsi_11_12 == 0x7F ) // wildcard
1095*4882a593Smuzhiyun   {
1096*4882a593Smuzhiyun     *p_mnc = 7;
1097*4882a593Smuzhiyun   }
1098*4882a593Smuzhiyun   else
1099*4882a593Smuzhiyun   {
1100*4882a593Smuzhiyun     d2 = buf % 10;
1101*4882a593Smuzhiyun     buf = ( d2 == 0 ) ? (buf-10)/10 : buf/10;
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun     d1 = ( buf == 10 ) ? 0 : buf;
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun     if ( d1<10 && d2<10 )
1106*4882a593Smuzhiyun     {
1107*4882a593Smuzhiyun      *p_mnc = d1*10 + d2;
1108*4882a593Smuzhiyun     }
1109*4882a593Smuzhiyun     else
1110*4882a593Smuzhiyun     {
1111*4882a593Smuzhiyun       //dbg_time( "invalid digits %d %d", d1, d2, 0 );
1112*4882a593Smuzhiyun       *p_mnc = 0;
1113*4882a593Smuzhiyun     }
1114*4882a593Smuzhiyun   }
1115*4882a593Smuzhiyun }
1116*4882a593Smuzhiyun 
requestGetHomeNetwork(USHORT * p_mcc,USHORT * p_mnc,USHORT * p_sid,USHORT * p_nid)1117*4882a593Smuzhiyun static int requestGetHomeNetwork(USHORT *p_mcc, USHORT *p_mnc, USHORT *p_sid, USHORT *p_nid) {
1118*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1119*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1120*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1121*4882a593Smuzhiyun     int err;
1122*4882a593Smuzhiyun     PHOME_NETWORK pHomeNetwork;
1123*4882a593Smuzhiyun     PHOME_NETWORK_SYSTEMID pHomeNetworkSystemID;
1124*4882a593Smuzhiyun 
1125*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_HOME_NETWORK_REQ, NULL, NULL);
1126*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1127*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1128*4882a593Smuzhiyun 
1129*4882a593Smuzhiyun     pHomeNetwork = (PHOME_NETWORK)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
1130*4882a593Smuzhiyun     if (pHomeNetwork && p_mcc && p_mnc ) {
1131*4882a593Smuzhiyun         *p_mcc = le16_to_cpu(pHomeNetwork->MobileCountryCode);
1132*4882a593Smuzhiyun         *p_mnc = le16_to_cpu(pHomeNetwork->MobileNetworkCode);
1133*4882a593Smuzhiyun         //dbg_time("%s MobileCountryCode: %d, MobileNetworkCode: %d", __func__, *pMobileCountryCode, *pMobileNetworkCode);
1134*4882a593Smuzhiyun     }
1135*4882a593Smuzhiyun 
1136*4882a593Smuzhiyun     pHomeNetworkSystemID = (PHOME_NETWORK_SYSTEMID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10);
1137*4882a593Smuzhiyun     if (pHomeNetworkSystemID && p_sid && p_nid) {
1138*4882a593Smuzhiyun         *p_sid = le16_to_cpu(pHomeNetworkSystemID->SystemID); //china-hefei: sid 14451
1139*4882a593Smuzhiyun         *p_nid = le16_to_cpu(pHomeNetworkSystemID->NetworkID);
1140*4882a593Smuzhiyun         //dbg_time("%s SystemID: %d, NetworkID: %d", __func__, *pSystemID, *pNetworkID);
1141*4882a593Smuzhiyun     }
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun     free(pResponse);
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun     return 0;
1146*4882a593Smuzhiyun }
1147*4882a593Smuzhiyun #endif
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun #if 0
1150*4882a593Smuzhiyun // Lookup table for carriers known to produce SIMs which incorrectly indicate MNC length.
1151*4882a593Smuzhiyun static const char * MCCMNC_CODES_HAVING_3DIGITS_MNC[] = {
1152*4882a593Smuzhiyun     "302370", "302720", "310260",
1153*4882a593Smuzhiyun     "405025", "405026", "405027", "405028", "405029", "405030", "405031", "405032",
1154*4882a593Smuzhiyun     "405033", "405034", "405035", "405036", "405037", "405038", "405039", "405040",
1155*4882a593Smuzhiyun     "405041", "405042", "405043", "405044", "405045", "405046", "405047", "405750",
1156*4882a593Smuzhiyun     "405751", "405752", "405753", "405754", "405755", "405756", "405799", "405800",
1157*4882a593Smuzhiyun     "405801", "405802", "405803", "405804", "405805", "405806", "405807", "405808",
1158*4882a593Smuzhiyun     "405809", "405810", "405811", "405812", "405813", "405814", "405815", "405816",
1159*4882a593Smuzhiyun     "405817", "405818", "405819", "405820", "405821", "405822", "405823", "405824",
1160*4882a593Smuzhiyun     "405825", "405826", "405827", "405828", "405829", "405830", "405831", "405832",
1161*4882a593Smuzhiyun     "405833", "405834", "405835", "405836", "405837", "405838", "405839", "405840",
1162*4882a593Smuzhiyun     "405841", "405842", "405843", "405844", "405845", "405846", "405847", "405848",
1163*4882a593Smuzhiyun     "405849", "405850", "405851", "405852", "405853", "405875", "405876", "405877",
1164*4882a593Smuzhiyun     "405878", "405879", "405880", "405881", "405882", "405883", "405884", "405885",
1165*4882a593Smuzhiyun     "405886", "405908", "405909", "405910", "405911", "405912", "405913", "405914",
1166*4882a593Smuzhiyun     "405915", "405916", "405917", "405918", "405919", "405920", "405921", "405922",
1167*4882a593Smuzhiyun     "405923", "405924", "405925", "405926", "405927", "405928", "405929", "405930",
1168*4882a593Smuzhiyun     "405931", "405932", "502142", "502143", "502145", "502146", "502147", "502148"
1169*4882a593Smuzhiyun };
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun static const char * MCC_CODES_HAVING_3DIGITS_MNC[] = {
1172*4882a593Smuzhiyun     "302",    //Canada
1173*4882a593Smuzhiyun     "310",    //United States of America
1174*4882a593Smuzhiyun     "311",    //United States of America
1175*4882a593Smuzhiyun     "312",    //United States of America
1176*4882a593Smuzhiyun     "313",    //United States of America
1177*4882a593Smuzhiyun     "314",    //United States of America
1178*4882a593Smuzhiyun     "315",    //United States of America
1179*4882a593Smuzhiyun     "316",    //United States of America
1180*4882a593Smuzhiyun     "334",    //Mexico
1181*4882a593Smuzhiyun     "338",    //Jamaica
1182*4882a593Smuzhiyun     "342", //Barbados
1183*4882a593Smuzhiyun     "344",    //Antigua and Barbuda
1184*4882a593Smuzhiyun     "346",    //Cayman Islands
1185*4882a593Smuzhiyun     "348",    //British Virgin Islands
1186*4882a593Smuzhiyun     "365",    //Anguilla
1187*4882a593Smuzhiyun     "708",    //Honduras (Republic of)
1188*4882a593Smuzhiyun     "722",    //Argentine Republic
1189*4882a593Smuzhiyun     "732"    //Colombia (Republic of)
1190*4882a593Smuzhiyun };
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun int requestGetIMSI(const char **pp_imsi, USHORT *pMobileCountryCode, USHORT *pMobileNetworkCode) {
1193*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1194*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1195*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1196*4882a593Smuzhiyun     int err;
1197*4882a593Smuzhiyun 
1198*4882a593Smuzhiyun     if (pp_imsi) *pp_imsi = NULL;
1199*4882a593Smuzhiyun     if (pMobileCountryCode) *pMobileCountryCode = 0;
1200*4882a593Smuzhiyun     if (pMobileNetworkCode) *pMobileNetworkCode = 0;
1201*4882a593Smuzhiyun 
1202*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_UIM_GET_IMSI_REQ, NULL, NULL);
1203*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1204*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1205*4882a593Smuzhiyun 
1206*4882a593Smuzhiyun     if (pMUXMsg->UIMGetIMSIResp.TLV2Type == 0x01 &&  le16_to_cpu(pMUXMsg->UIMGetIMSIResp.TLV2Length) >= 5) {
1207*4882a593Smuzhiyun         int mnc_len = 2;
1208*4882a593Smuzhiyun         unsigned i;
1209*4882a593Smuzhiyun         char tmp[4];
1210*4882a593Smuzhiyun 
1211*4882a593Smuzhiyun         if (pp_imsi) *pp_imsi = strndup((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), le16_to_cpu(pMUXMsg->UIMGetIMSIResp.TLV2Length));
1212*4882a593Smuzhiyun 
1213*4882a593Smuzhiyun         for (i = 0; i < sizeof(MCCMNC_CODES_HAVING_3DIGITS_MNC)/sizeof(MCCMNC_CODES_HAVING_3DIGITS_MNC[0]); i++) {
1214*4882a593Smuzhiyun             if (!strncmp((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), MCCMNC_CODES_HAVING_3DIGITS_MNC[i], 6)) {
1215*4882a593Smuzhiyun                 mnc_len = 3;
1216*4882a593Smuzhiyun                 break;
1217*4882a593Smuzhiyun             }
1218*4882a593Smuzhiyun         }
1219*4882a593Smuzhiyun         if (mnc_len == 2) {
1220*4882a593Smuzhiyun             for (i = 0; i < sizeof(MCC_CODES_HAVING_3DIGITS_MNC)/sizeof(MCC_CODES_HAVING_3DIGITS_MNC[0]); i++) {
1221*4882a593Smuzhiyun                 if (!strncmp((const char *)(&pMUXMsg->UIMGetIMSIResp.IMSI), MCC_CODES_HAVING_3DIGITS_MNC[i], 3)) {
1222*4882a593Smuzhiyun                     mnc_len = 3;
1223*4882a593Smuzhiyun                     break;
1224*4882a593Smuzhiyun                 }
1225*4882a593Smuzhiyun             }
1226*4882a593Smuzhiyun         }
1227*4882a593Smuzhiyun 
1228*4882a593Smuzhiyun         tmp[0] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[0];
1229*4882a593Smuzhiyun         tmp[1] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[1];
1230*4882a593Smuzhiyun         tmp[2] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[2];
1231*4882a593Smuzhiyun         tmp[3] = 0;
1232*4882a593Smuzhiyun         if (pMobileCountryCode) *pMobileCountryCode = atoi(tmp);
1233*4882a593Smuzhiyun         tmp[0] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[3];
1234*4882a593Smuzhiyun         tmp[1] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[4];
1235*4882a593Smuzhiyun         tmp[2] = 0;
1236*4882a593Smuzhiyun         if (mnc_len == 3) {
1237*4882a593Smuzhiyun             tmp[2] = (&pMUXMsg->UIMGetIMSIResp.IMSI)[6];
1238*4882a593Smuzhiyun         }
1239*4882a593Smuzhiyun         if (pMobileNetworkCode) *pMobileNetworkCode = atoi(tmp);
1240*4882a593Smuzhiyun     }
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun     free(pResponse);
1243*4882a593Smuzhiyun 
1244*4882a593Smuzhiyun     return 0;
1245*4882a593Smuzhiyun }
1246*4882a593Smuzhiyun #endif
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun static struct wwan_data_class_str class2str[] = {
1249*4882a593Smuzhiyun     {WWAN_DATA_CLASS_NONE, "UNKNOWN"},
1250*4882a593Smuzhiyun     {WWAN_DATA_CLASS_GPRS, "GPRS"},
1251*4882a593Smuzhiyun     {WWAN_DATA_CLASS_EDGE, "EDGE"},
1252*4882a593Smuzhiyun     {WWAN_DATA_CLASS_UMTS, "UMTS"},
1253*4882a593Smuzhiyun     {WWAN_DATA_CLASS_HSDPA, "HSDPA"},
1254*4882a593Smuzhiyun     {WWAN_DATA_CLASS_HSUPA, "HSUPA"},
1255*4882a593Smuzhiyun     {WWAN_DATA_CLASS_LTE, "LTE"},
1256*4882a593Smuzhiyun     {WWAN_DATA_CLASS_5G_NSA, "5G_NSA"},
1257*4882a593Smuzhiyun     {WWAN_DATA_CLASS_5G_SA, "5G_SA"},
1258*4882a593Smuzhiyun     {WWAN_DATA_CLASS_1XRTT, "1XRTT"},
1259*4882a593Smuzhiyun     {WWAN_DATA_CLASS_1XEVDO, "1XEVDO"},
1260*4882a593Smuzhiyun     {WWAN_DATA_CLASS_1XEVDO_REVA, "1XEVDO_REVA"},
1261*4882a593Smuzhiyun     {WWAN_DATA_CLASS_1XEVDV, "1XEVDV"},
1262*4882a593Smuzhiyun     {WWAN_DATA_CLASS_3XRTT, "3XRTT"},
1263*4882a593Smuzhiyun     {WWAN_DATA_CLASS_1XEVDO_REVB, "1XEVDO_REVB"},
1264*4882a593Smuzhiyun     {WWAN_DATA_CLASS_UMB, "UMB"},
1265*4882a593Smuzhiyun     {WWAN_DATA_CLASS_CUSTOM, "CUSTOM"},
1266*4882a593Smuzhiyun };
1267*4882a593Smuzhiyun 
wwan_data_class2str(ULONG class)1268*4882a593Smuzhiyun static CHAR *wwan_data_class2str(ULONG class)
1269*4882a593Smuzhiyun {
1270*4882a593Smuzhiyun     unsigned int i = 0;
1271*4882a593Smuzhiyun     for (i = 0; i < sizeof(class2str)/sizeof(class2str[0]); i++) {
1272*4882a593Smuzhiyun         if (class2str[i].class == class) {
1273*4882a593Smuzhiyun             return class2str[i].str;
1274*4882a593Smuzhiyun         }
1275*4882a593Smuzhiyun     }
1276*4882a593Smuzhiyun     return "UNKNOWN";
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun 
char2ushort(UCHAR str[3])1279*4882a593Smuzhiyun static USHORT char2ushort(UCHAR str[3]) {
1280*4882a593Smuzhiyun     int i;
1281*4882a593Smuzhiyun     char temp[4];
1282*4882a593Smuzhiyun     USHORT ret= 0;
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun     memcpy(temp, str, 3);
1285*4882a593Smuzhiyun     temp[3] = '\0';
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun     for (i = 0; i < 4; i++) {
1288*4882a593Smuzhiyun         if ((UCHAR)temp[i] == 0xFF) {
1289*4882a593Smuzhiyun             temp[i] = '\0';
1290*4882a593Smuzhiyun         }
1291*4882a593Smuzhiyun     }
1292*4882a593Smuzhiyun     ret = (USHORT)atoi(temp);
1293*4882a593Smuzhiyun 
1294*4882a593Smuzhiyun     return ret;
1295*4882a593Smuzhiyun }
1296*4882a593Smuzhiyun 
requestRegistrationState2(UCHAR * pPSAttachedState)1297*4882a593Smuzhiyun static int requestRegistrationState2(UCHAR *pPSAttachedState) {
1298*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1299*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1300*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1301*4882a593Smuzhiyun     int err;
1302*4882a593Smuzhiyun     USHORT MobileCountryCode = 0;
1303*4882a593Smuzhiyun     USHORT MobileNetworkCode = 0;
1304*4882a593Smuzhiyun     const char *pDataCapStr = "UNKNOW";
1305*4882a593Smuzhiyun     LONG remainingLen;
1306*4882a593Smuzhiyun     PSERVICE_STATUS_INFO pServiceStatusInfo;
1307*4882a593Smuzhiyun     int is_lte = 0;
1308*4882a593Smuzhiyun     PCDMA_SYSTEM_INFO pCdmaSystemInfo;
1309*4882a593Smuzhiyun     PHDR_SYSTEM_INFO pHdrSystemInfo;
1310*4882a593Smuzhiyun     PGSM_SYSTEM_INFO pGsmSystemInfo;
1311*4882a593Smuzhiyun     PWCDMA_SYSTEM_INFO pWcdmaSystemInfo;
1312*4882a593Smuzhiyun     PLTE_SYSTEM_INFO pLteSystemInfo;
1313*4882a593Smuzhiyun     PTDSCDMA_SYSTEM_INFO pTdscdmaSystemInfo;
1314*4882a593Smuzhiyun     PNR5G_SYSTEM_INFO pNr5gSystemInfo;
1315*4882a593Smuzhiyun     UCHAR DeviceClass = 0;
1316*4882a593Smuzhiyun     ULONG DataCapList = 0;
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun     /*  Additional LTE System Info - Availability of Dual connectivity of E-UTRA with NR5G */
1319*4882a593Smuzhiyun     uint8_t endc_available_valid = 0;  /**< Must be set to true if endc_available is being passed */
1320*4882a593Smuzhiyun     uint8_t endc_available = 0x00;
1321*4882a593Smuzhiyun     /**<
1322*4882a593Smuzhiyun        Upper layer indication in LTE SIB2. Values: \n
1323*4882a593Smuzhiyun        - 0x00 -- 5G Not available \n
1324*4882a593Smuzhiyun        - 0x01 -- 5G Available
1325*4882a593Smuzhiyun 
1326*4882a593Smuzhiyun     */
1327*4882a593Smuzhiyun     /*  Additional LTE System Info - DCNR restriction Info */
1328*4882a593Smuzhiyun     uint8_t restrict_dcnr_valid = 0;  /**< Must be set to true if restrict_dcnr is being passed */
1329*4882a593Smuzhiyun     uint8_t restrict_dcnr = 0x01;
1330*4882a593Smuzhiyun     /**<
1331*4882a593Smuzhiyun        DCNR restriction in NAS attach/TAU accept. Values: \n
1332*4882a593Smuzhiyun        - 0x00 -- Not restricted \n
1333*4882a593Smuzhiyun        - 0x01 -- Restricted
1334*4882a593Smuzhiyun     */
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun     *pPSAttachedState = 0;
1337*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SYS_INFO_REQ, NULL, NULL);
1338*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1339*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1340*4882a593Smuzhiyun 
1341*4882a593Smuzhiyun     pServiceStatusInfo = (PSERVICE_STATUS_INFO)(((PCHAR)&pMUXMsg->GetSysInfoResp) + QCQMUX_MSG_HDR_SIZE);
1342*4882a593Smuzhiyun     remainingLen = le16_to_cpu(pMUXMsg->GetSysInfoResp.Length);
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun     s_is_cdma = 0;
1345*4882a593Smuzhiyun     s_5g_type = WWAN_DATA_CLASS_NONE;
1346*4882a593Smuzhiyun     s_hdr_personality = 0;
1347*4882a593Smuzhiyun     while (remainingLen > 0) {
1348*4882a593Smuzhiyun         switch (pServiceStatusInfo->TLVType) {
1349*4882a593Smuzhiyun         case 0x10: // CDMA
1350*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1351*4882a593Smuzhiyun                 DataCapList = WWAN_DATA_CLASS_1XRTT|
1352*4882a593Smuzhiyun                               WWAN_DATA_CLASS_1XEVDO|
1353*4882a593Smuzhiyun                               WWAN_DATA_CLASS_1XEVDO_REVA|
1354*4882a593Smuzhiyun                               WWAN_DATA_CLASS_1XEVDV|
1355*4882a593Smuzhiyun                               WWAN_DATA_CLASS_1XEVDO_REVB;
1356*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_CDMA;
1357*4882a593Smuzhiyun                 s_is_cdma = (0 == is_lte);
1358*4882a593Smuzhiyun             }
1359*4882a593Smuzhiyun             break;
1360*4882a593Smuzhiyun         case 0x11: // HDR
1361*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1362*4882a593Smuzhiyun                 DataCapList = WWAN_DATA_CLASS_3XRTT|
1363*4882a593Smuzhiyun                               WWAN_DATA_CLASS_UMB;
1364*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_CDMA;
1365*4882a593Smuzhiyun                 s_is_cdma = (0 == is_lte);
1366*4882a593Smuzhiyun             }
1367*4882a593Smuzhiyun             break;
1368*4882a593Smuzhiyun         case 0x12: // GSM
1369*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1370*4882a593Smuzhiyun                 DataCapList = WWAN_DATA_CLASS_GPRS|
1371*4882a593Smuzhiyun                               WWAN_DATA_CLASS_EDGE;
1372*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_GSM;
1373*4882a593Smuzhiyun             }
1374*4882a593Smuzhiyun             break;
1375*4882a593Smuzhiyun         case 0x13: // WCDMA
1376*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1377*4882a593Smuzhiyun                 DataCapList = WWAN_DATA_CLASS_UMTS;
1378*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_GSM;
1379*4882a593Smuzhiyun             }
1380*4882a593Smuzhiyun             break;
1381*4882a593Smuzhiyun         case 0x14: // LTE
1382*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1383*4882a593Smuzhiyun                 DataCapList = WWAN_DATA_CLASS_LTE;
1384*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_GSM;
1385*4882a593Smuzhiyun                 is_lte = 1;
1386*4882a593Smuzhiyun                 s_is_cdma = 0;
1387*4882a593Smuzhiyun             }
1388*4882a593Smuzhiyun             break;
1389*4882a593Smuzhiyun         case 0x4A: // NR5G Service Status Info
1390*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == NAS_SYS_SRV_STATUS_SRV_V01) {
1391*4882a593Smuzhiyun                 DataCapList |= WWAN_DATA_CLASS_5G_SA;
1392*4882a593Smuzhiyun                 DeviceClass = DEVICE_CLASS_GSM;
1393*4882a593Smuzhiyun                 is_lte = 1;
1394*4882a593Smuzhiyun                 s_is_cdma = 0;
1395*4882a593Smuzhiyun             }
1396*4882a593Smuzhiyun             break;
1397*4882a593Smuzhiyun         case 0x4B: // NR5G System Info
1398*4882a593Smuzhiyun             pNr5gSystemInfo = (PNR5G_SYSTEM_INFO)pServiceStatusInfo;
1399*4882a593Smuzhiyun             if (pNr5gSystemInfo->srv_domain_valid == 0x01) {
1400*4882a593Smuzhiyun                 if (pNr5gSystemInfo->srv_domain & SYS_SRV_DOMAIN_PS_ONLY_V01) {
1401*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1402*4882a593Smuzhiyun                 }
1403*4882a593Smuzhiyun             }
1404*4882a593Smuzhiyun 
1405*4882a593Smuzhiyun             if (pNr5gSystemInfo->network_id_valid == 0x01) {
1406*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pNr5gSystemInfo->MCC);
1407*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pNr5gSystemInfo->MNC);
1408*4882a593Smuzhiyun             }
1409*4882a593Smuzhiyun             break;
1410*4882a593Smuzhiyun         case 0x4E: //Additional LTE System Info - Availability of Dual Connectivity of E-UTRA with NR5G
1411*4882a593Smuzhiyun             endc_available_valid = 1;
1412*4882a593Smuzhiyun             endc_available = pServiceStatusInfo->SrvStatus;
1413*4882a593Smuzhiyun             break;
1414*4882a593Smuzhiyun 
1415*4882a593Smuzhiyun         case 0x4F: //Additional LTE System Info - DCNR restriction Info
1416*4882a593Smuzhiyun             restrict_dcnr_valid = 1;
1417*4882a593Smuzhiyun             restrict_dcnr = pServiceStatusInfo->SrvStatus;
1418*4882a593Smuzhiyun             break;
1419*4882a593Smuzhiyun 
1420*4882a593Smuzhiyun         case 0x24: // TDSCDMA
1421*4882a593Smuzhiyun             if (pServiceStatusInfo->SrvStatus == 0x02) {
1422*4882a593Smuzhiyun                 pDataCapStr = "TD-SCDMA";
1423*4882a593Smuzhiyun             }
1424*4882a593Smuzhiyun             break;
1425*4882a593Smuzhiyun         case 0x15: // CDMA
1426*4882a593Smuzhiyun             // CDMA_SYSTEM_INFO
1427*4882a593Smuzhiyun             pCdmaSystemInfo = (PCDMA_SYSTEM_INFO)pServiceStatusInfo;
1428*4882a593Smuzhiyun             if (pCdmaSystemInfo->SrvDomainValid == 0x01) {
1429*4882a593Smuzhiyun                 if (pCdmaSystemInfo->SrvDomain & 0x02) {
1430*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1431*4882a593Smuzhiyun                     s_is_cdma = (0 == is_lte);
1432*4882a593Smuzhiyun                 }
1433*4882a593Smuzhiyun             }
1434*4882a593Smuzhiyun #if 0
1435*4882a593Smuzhiyun             if (pCdmaSystemInfo->SrvCapabilityValid == 0x01) {
1436*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1437*4882a593Smuzhiyun                 if (pCdmaSystemInfo->SrvCapability & 0x02) {
1438*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1439*4882a593Smuzhiyun                     s_is_cdma = (0 == is_lte);
1440*4882a593Smuzhiyun                 }
1441*4882a593Smuzhiyun             }
1442*4882a593Smuzhiyun #endif
1443*4882a593Smuzhiyun             if (pCdmaSystemInfo->NetworkIdValid == 0x01) {
1444*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pCdmaSystemInfo->MCC);
1445*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pCdmaSystemInfo->MNC);
1446*4882a593Smuzhiyun             }
1447*4882a593Smuzhiyun             break;
1448*4882a593Smuzhiyun         case 0x16: // HDR
1449*4882a593Smuzhiyun             // HDR_SYSTEM_INFO
1450*4882a593Smuzhiyun             pHdrSystemInfo = (PHDR_SYSTEM_INFO)pServiceStatusInfo;
1451*4882a593Smuzhiyun             if (pHdrSystemInfo->SrvDomainValid == 0x01) {
1452*4882a593Smuzhiyun                 if (pHdrSystemInfo->SrvDomain & 0x02) {
1453*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1454*4882a593Smuzhiyun                     s_is_cdma = (0 == is_lte);
1455*4882a593Smuzhiyun                 }
1456*4882a593Smuzhiyun             }
1457*4882a593Smuzhiyun #if 0
1458*4882a593Smuzhiyun             if (pHdrSystemInfo->SrvCapabilityValid == 0x01) {
1459*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1460*4882a593Smuzhiyun                 if (pHdrSystemInfo->SrvCapability & 0x02) {
1461*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1462*4882a593Smuzhiyun                     s_is_cdma = (0 == is_lte);
1463*4882a593Smuzhiyun                 }
1464*4882a593Smuzhiyun             }
1465*4882a593Smuzhiyun #endif
1466*4882a593Smuzhiyun             if (*pPSAttachedState && pHdrSystemInfo->HdrPersonalityValid == 0x01) {
1467*4882a593Smuzhiyun                 if (pHdrSystemInfo->HdrPersonality == 0x03)
1468*4882a593Smuzhiyun                     s_hdr_personality = 0x02;
1469*4882a593Smuzhiyun                 //else if (pHdrSystemInfo->HdrPersonality == 0x02)
1470*4882a593Smuzhiyun                 //    s_hdr_personality = 0x01;
1471*4882a593Smuzhiyun             }
1472*4882a593Smuzhiyun             USHORT cmda_mcc = 0, cdma_mnc = 0;
1473*4882a593Smuzhiyun             if(!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc,NULL, NULL) && cmda_mcc) {
1474*4882a593Smuzhiyun                 quectel_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc);
1475*4882a593Smuzhiyun                 quectel_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc);
1476*4882a593Smuzhiyun             }
1477*4882a593Smuzhiyun             break;
1478*4882a593Smuzhiyun         case 0x17: // GSM
1479*4882a593Smuzhiyun             // GSM_SYSTEM_INFO
1480*4882a593Smuzhiyun             pGsmSystemInfo = (PGSM_SYSTEM_INFO)pServiceStatusInfo;
1481*4882a593Smuzhiyun             if (pGsmSystemInfo->SrvDomainValid == 0x01) {
1482*4882a593Smuzhiyun                 if (pGsmSystemInfo->SrvDomain & 0x02) {
1483*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1484*4882a593Smuzhiyun                 }
1485*4882a593Smuzhiyun             }
1486*4882a593Smuzhiyun #if 0
1487*4882a593Smuzhiyun             if (pGsmSystemInfo->SrvCapabilityValid == 0x01) {
1488*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1489*4882a593Smuzhiyun                 if (pGsmSystemInfo->SrvCapability & 0x02) {
1490*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1491*4882a593Smuzhiyun                 }
1492*4882a593Smuzhiyun             }
1493*4882a593Smuzhiyun #endif
1494*4882a593Smuzhiyun             if (pGsmSystemInfo->NetworkIdValid == 0x01) {
1495*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pGsmSystemInfo->MCC);
1496*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pGsmSystemInfo->MNC);
1497*4882a593Smuzhiyun             }
1498*4882a593Smuzhiyun             break;
1499*4882a593Smuzhiyun         case 0x18: // WCDMA
1500*4882a593Smuzhiyun             // WCDMA_SYSTEM_INFO
1501*4882a593Smuzhiyun             pWcdmaSystemInfo = (PWCDMA_SYSTEM_INFO)pServiceStatusInfo;
1502*4882a593Smuzhiyun             if (pWcdmaSystemInfo->SrvDomainValid == 0x01) {
1503*4882a593Smuzhiyun                 if (pWcdmaSystemInfo->SrvDomain & 0x02) {
1504*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1505*4882a593Smuzhiyun                 }
1506*4882a593Smuzhiyun             }
1507*4882a593Smuzhiyun #if 0
1508*4882a593Smuzhiyun             if (pWcdmaSystemInfo->SrvCapabilityValid == 0x01) {
1509*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1510*4882a593Smuzhiyun                 if (pWcdmaSystemInfo->SrvCapability & 0x02) {
1511*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1512*4882a593Smuzhiyun                 }
1513*4882a593Smuzhiyun             }
1514*4882a593Smuzhiyun #endif
1515*4882a593Smuzhiyun             if (pWcdmaSystemInfo->NetworkIdValid == 0x01) {
1516*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pWcdmaSystemInfo->MCC);
1517*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pWcdmaSystemInfo->MNC);
1518*4882a593Smuzhiyun             }
1519*4882a593Smuzhiyun             break;
1520*4882a593Smuzhiyun         case 0x19: // LTE_SYSTEM_INFO
1521*4882a593Smuzhiyun             // LTE_SYSTEM_INFO
1522*4882a593Smuzhiyun             pLteSystemInfo = (PLTE_SYSTEM_INFO)pServiceStatusInfo;
1523*4882a593Smuzhiyun             if (pLteSystemInfo->SrvDomainValid == 0x01) {
1524*4882a593Smuzhiyun                 if (pLteSystemInfo->SrvDomain & 0x02) {
1525*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1526*4882a593Smuzhiyun                     is_lte = 1;
1527*4882a593Smuzhiyun                     s_is_cdma = 0;
1528*4882a593Smuzhiyun                 }
1529*4882a593Smuzhiyun             }
1530*4882a593Smuzhiyun #if 0
1531*4882a593Smuzhiyun             if (pLteSystemInfo->SrvCapabilityValid == 0x01) {
1532*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1533*4882a593Smuzhiyun                 if (pLteSystemInfo->SrvCapability & 0x02) {
1534*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1535*4882a593Smuzhiyun                     is_lte = 1;
1536*4882a593Smuzhiyun                     s_is_cdma = 0;
1537*4882a593Smuzhiyun                 }
1538*4882a593Smuzhiyun             }
1539*4882a593Smuzhiyun #endif
1540*4882a593Smuzhiyun             if (pLteSystemInfo->NetworkIdValid == 0x01) {
1541*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pLteSystemInfo->MCC);
1542*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pLteSystemInfo->MNC);
1543*4882a593Smuzhiyun             }
1544*4882a593Smuzhiyun             break;
1545*4882a593Smuzhiyun         case 0x25: // TDSCDMA
1546*4882a593Smuzhiyun             // TDSCDMA_SYSTEM_INFO
1547*4882a593Smuzhiyun             pTdscdmaSystemInfo = (PTDSCDMA_SYSTEM_INFO)pServiceStatusInfo;
1548*4882a593Smuzhiyun             if (pTdscdmaSystemInfo->SrvDomainValid == 0x01) {
1549*4882a593Smuzhiyun                 if (pTdscdmaSystemInfo->SrvDomain & 0x02) {
1550*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1551*4882a593Smuzhiyun                 }
1552*4882a593Smuzhiyun             }
1553*4882a593Smuzhiyun #if 0
1554*4882a593Smuzhiyun             if (pTdscdmaSystemInfo->SrvCapabilityValid == 0x01) {
1555*4882a593Smuzhiyun                 *pPSAttachedState = 0;
1556*4882a593Smuzhiyun                 if (pTdscdmaSystemInfo->SrvCapability & 0x02) {
1557*4882a593Smuzhiyun                     *pPSAttachedState = 1;
1558*4882a593Smuzhiyun                 }
1559*4882a593Smuzhiyun             }
1560*4882a593Smuzhiyun #endif
1561*4882a593Smuzhiyun             if (pTdscdmaSystemInfo->NetworkIdValid == 0x01) {
1562*4882a593Smuzhiyun                 MobileCountryCode = (USHORT)char2ushort(pTdscdmaSystemInfo->MCC);
1563*4882a593Smuzhiyun                 MobileNetworkCode = (USHORT)char2ushort(pTdscdmaSystemInfo->MNC);
1564*4882a593Smuzhiyun             }
1565*4882a593Smuzhiyun             break;
1566*4882a593Smuzhiyun         default:
1567*4882a593Smuzhiyun             break;
1568*4882a593Smuzhiyun         } /* switch (pServiceStatusInfo->TLYType) */
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun         remainingLen -= (le16_to_cpu(pServiceStatusInfo->TLVLength) + 3);
1571*4882a593Smuzhiyun         pServiceStatusInfo = (PSERVICE_STATUS_INFO)((PCHAR)&pServiceStatusInfo->TLVLength + le16_to_cpu(pServiceStatusInfo->TLVLength) + sizeof(USHORT));
1572*4882a593Smuzhiyun     } /* while (remainingLen > 0) */
1573*4882a593Smuzhiyun 
1574*4882a593Smuzhiyun     if (DataCapList & WWAN_DATA_CLASS_LTE) {
1575*4882a593Smuzhiyun         if (endc_available_valid && restrict_dcnr_valid) {
1576*4882a593Smuzhiyun             if (endc_available && !restrict_dcnr) {
1577*4882a593Smuzhiyun                 DataCapList |= WWAN_DATA_CLASS_5G_NSA;
1578*4882a593Smuzhiyun             }
1579*4882a593Smuzhiyun         }
1580*4882a593Smuzhiyun     }
1581*4882a593Smuzhiyun 
1582*4882a593Smuzhiyun     if (DeviceClass == DEVICE_CLASS_CDMA) {
1583*4882a593Smuzhiyun         if (s_hdr_personality == 2) {
1584*4882a593Smuzhiyun             pDataCapStr = s_hdr_personality == 2 ? "eHRPD" : "HRPD";
1585*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVB) {
1586*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVB);
1587*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO_REVA) {
1588*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO_REVA);
1589*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_1XEVDO) {
1590*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XEVDO);
1591*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_1XRTT) {
1592*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_1XRTT);
1593*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_3XRTT) {
1594*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_3XRTT);
1595*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_UMB) {
1596*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMB);
1597*4882a593Smuzhiyun         }
1598*4882a593Smuzhiyun     } else {
1599*4882a593Smuzhiyun         if (DataCapList & WWAN_DATA_CLASS_5G_SA) {
1600*4882a593Smuzhiyun             s_5g_type = WWAN_DATA_CLASS_5G_SA;
1601*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_5G_SA);
1602*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_5G_NSA) {
1603*4882a593Smuzhiyun             s_5g_type = WWAN_DATA_CLASS_5G_NSA;
1604*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_5G_NSA);
1605*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_LTE) {
1606*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_LTE);
1607*4882a593Smuzhiyun         } else if ((DataCapList & WWAN_DATA_CLASS_HSDPA) && (DataCapList & WWAN_DATA_CLASS_HSUPA)) {
1608*4882a593Smuzhiyun             pDataCapStr = "HSDPA_HSUPA";
1609*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_HSDPA) {
1610*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSDPA);
1611*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_HSUPA) {
1612*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_HSUPA);
1613*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_UMTS) {
1614*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_UMTS);
1615*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_EDGE) {
1616*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_EDGE);
1617*4882a593Smuzhiyun         } else if (DataCapList & WWAN_DATA_CLASS_GPRS) {
1618*4882a593Smuzhiyun             pDataCapStr = wwan_data_class2str(WWAN_DATA_CLASS_GPRS);
1619*4882a593Smuzhiyun         }
1620*4882a593Smuzhiyun     }
1621*4882a593Smuzhiyun 
1622*4882a593Smuzhiyun     dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__,
1623*4882a593Smuzhiyun         MobileCountryCode, MobileNetworkCode, (*pPSAttachedState == 1) ? "Attached" : "Detached" , pDataCapStr);
1624*4882a593Smuzhiyun 
1625*4882a593Smuzhiyun     free(pResponse);
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun     return 0;
1628*4882a593Smuzhiyun }
1629*4882a593Smuzhiyun 
requestRegistrationState(UCHAR * pPSAttachedState)1630*4882a593Smuzhiyun static int requestRegistrationState(UCHAR *pPSAttachedState) {
1631*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1632*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1633*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1634*4882a593Smuzhiyun     int err;
1635*4882a593Smuzhiyun     PQMINAS_CURRENT_PLMN_MSG pCurrentPlmn;
1636*4882a593Smuzhiyun     PSERVING_SYSTEM pServingSystem;
1637*4882a593Smuzhiyun     PQMINAS_DATA_CAP pDataCap;
1638*4882a593Smuzhiyun     USHORT MobileCountryCode = 0;
1639*4882a593Smuzhiyun     USHORT MobileNetworkCode = 0;
1640*4882a593Smuzhiyun     const char *pDataCapStr = "UNKNOW";
1641*4882a593Smuzhiyun 
1642*4882a593Smuzhiyun     if (s_9x07) {
1643*4882a593Smuzhiyun         return requestRegistrationState2(pPSAttachedState);
1644*4882a593Smuzhiyun     }
1645*4882a593Smuzhiyun 
1646*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SERVING_SYSTEM_REQ, NULL, NULL);
1647*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1648*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun     pCurrentPlmn = (PQMINAS_CURRENT_PLMN_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12);
1651*4882a593Smuzhiyun     if (pCurrentPlmn) {
1652*4882a593Smuzhiyun         MobileCountryCode = le16_to_cpu(pCurrentPlmn->MobileCountryCode);
1653*4882a593Smuzhiyun         MobileNetworkCode = le16_to_cpu(pCurrentPlmn->MobileNetworkCode);
1654*4882a593Smuzhiyun     }
1655*4882a593Smuzhiyun 
1656*4882a593Smuzhiyun     *pPSAttachedState = 0;
1657*4882a593Smuzhiyun     pServingSystem = (PSERVING_SYSTEM)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
1658*4882a593Smuzhiyun     if (pServingSystem) {
1659*4882a593Smuzhiyun     //Packet-switched domain attach state of the mobile.
1660*4882a593Smuzhiyun     //0x00    PS_UNKNOWN ?Unknown or not applicable
1661*4882a593Smuzhiyun     //0x01    PS_ATTACHED ?Attached
1662*4882a593Smuzhiyun     //0x02    PS_DETACHED ?Detached
1663*4882a593Smuzhiyun         *pPSAttachedState = pServingSystem->RegistrationState;
1664*4882a593Smuzhiyun         if (pServingSystem->RegistrationState == 0x01) //0x01 ?C REGISTERED ?C Registered with a network
1665*4882a593Smuzhiyun             *pPSAttachedState  = pServingSystem->PSAttachedState;
1666*4882a593Smuzhiyun         else {
1667*4882a593Smuzhiyun             //MobileCountryCode = MobileNetworkCode = 0;
1668*4882a593Smuzhiyun             *pPSAttachedState  = 0x02;
1669*4882a593Smuzhiyun         }
1670*4882a593Smuzhiyun     }
1671*4882a593Smuzhiyun 
1672*4882a593Smuzhiyun     pDataCap = (PQMINAS_DATA_CAP)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
1673*4882a593Smuzhiyun     if (pDataCap && pDataCap->DataCapListLen) {
1674*4882a593Smuzhiyun         UCHAR *DataCap = &pDataCap->DataCap;
1675*4882a593Smuzhiyun         if (pDataCap->DataCapListLen == 2) {
1676*4882a593Smuzhiyun             if ((DataCap[0] == 0x06) && ((DataCap[1] == 0x08) || (DataCap[1] == 0x0A)))
1677*4882a593Smuzhiyun                 DataCap[0] = DataCap[1];
1678*4882a593Smuzhiyun         }
1679*4882a593Smuzhiyun         switch (DataCap[0]) {
1680*4882a593Smuzhiyun              case 0x01: pDataCapStr = "GPRS"; break;
1681*4882a593Smuzhiyun              case 0x02: pDataCapStr = "EDGE"; break;
1682*4882a593Smuzhiyun              case 0x03: pDataCapStr = "HSDPA"; break;
1683*4882a593Smuzhiyun              case 0x04: pDataCapStr = "HSUPA"; break;
1684*4882a593Smuzhiyun              case 0x05: pDataCapStr = "UMTS"; break;
1685*4882a593Smuzhiyun              case 0x06: pDataCapStr = "1XRTT"; break;
1686*4882a593Smuzhiyun              case 0x07: pDataCapStr = "1XEVDO"; break;
1687*4882a593Smuzhiyun              case 0x08: pDataCapStr = "1XEVDO_REVA"; break;
1688*4882a593Smuzhiyun              case 0x09: pDataCapStr = "GPRS"; break;
1689*4882a593Smuzhiyun              case 0x0A: pDataCapStr = "1XEVDO_REVB"; break;
1690*4882a593Smuzhiyun              case 0x0B: pDataCapStr = "LTE"; break;
1691*4882a593Smuzhiyun              case 0x0C: pDataCapStr = "HSDPA"; break;
1692*4882a593Smuzhiyun              case 0x0D: pDataCapStr = "HSDPA"; break;
1693*4882a593Smuzhiyun              default: pDataCapStr = "UNKNOW"; break;
1694*4882a593Smuzhiyun         }
1695*4882a593Smuzhiyun     }
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun     if (pServingSystem && pServingSystem->RegistrationState == 0x01 && pServingSystem->InUseRadioIF && pServingSystem->RadioIF == 0x09) {
1698*4882a593Smuzhiyun         pDataCapStr = "TD-SCDMA";
1699*4882a593Smuzhiyun     }
1700*4882a593Smuzhiyun 
1701*4882a593Smuzhiyun     s_is_cdma = 0;
1702*4882a593Smuzhiyun     if (pServingSystem && pServingSystem->RegistrationState == 0x01 && pServingSystem->InUseRadioIF && (pServingSystem->RadioIF == 0x01 || pServingSystem->RadioIF == 0x02)) {
1703*4882a593Smuzhiyun         USHORT cmda_mcc = 0, cdma_mnc = 0;
1704*4882a593Smuzhiyun         s_is_cdma = 1;
1705*4882a593Smuzhiyun         if(!requestGetHomeNetwork(&cmda_mcc, &cdma_mnc,NULL, NULL) && cmda_mcc) {
1706*4882a593Smuzhiyun             quectel_convert_cdma_mcc_2_ascii_mcc(&MobileCountryCode, cmda_mcc);
1707*4882a593Smuzhiyun             quectel_convert_cdma_mnc_2_ascii_mnc(&MobileNetworkCode, cdma_mnc);
1708*4882a593Smuzhiyun         }
1709*4882a593Smuzhiyun         if (1) {
1710*4882a593Smuzhiyun             PQCQMUX_TLV pTLV = (PQCQMUX_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x23);
1711*4882a593Smuzhiyun             if (pTLV)
1712*4882a593Smuzhiyun                 s_hdr_personality = pTLV->Value;
1713*4882a593Smuzhiyun             else
1714*4882a593Smuzhiyun                 s_hdr_personality = 0;
1715*4882a593Smuzhiyun             if (s_hdr_personality == 2)
1716*4882a593Smuzhiyun                 pDataCapStr = "eHRPD";
1717*4882a593Smuzhiyun         }
1718*4882a593Smuzhiyun     }
1719*4882a593Smuzhiyun 
1720*4882a593Smuzhiyun     dbg_time("%s MCC: %d, MNC: %d, PS: %s, DataCap: %s", __func__,
1721*4882a593Smuzhiyun         MobileCountryCode, MobileNetworkCode, (*pPSAttachedState == 1) ? "Attached" : "Detached" , pDataCapStr);
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun     free(pResponse);
1724*4882a593Smuzhiyun 
1725*4882a593Smuzhiyun     return 0;
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun 
requestQueryDataCall(UCHAR * pConnectionStatus,int curIpFamily)1728*4882a593Smuzhiyun static int requestQueryDataCall(UCHAR  *pConnectionStatus, int curIpFamily) {
1729*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1730*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1731*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1732*4882a593Smuzhiyun     int err;
1733*4882a593Smuzhiyun     PQMIWDS_PKT_SRVC_TLV pPktSrvc;
1734*4882a593Smuzhiyun     UCHAR oldConnectionStatus = *pConnectionStatus;
1735*4882a593Smuzhiyun     UCHAR QMIType = (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6;
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_PKT_SRVC_STATUS_REQ, NULL, NULL);
1738*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1739*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun     *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
1742*4882a593Smuzhiyun     pPktSrvc = (PQMIWDS_PKT_SRVC_TLV)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
1743*4882a593Smuzhiyun     if (pPktSrvc) {
1744*4882a593Smuzhiyun         *pConnectionStatus = pPktSrvc->ConnectionStatus;
1745*4882a593Smuzhiyun         if ((le16_to_cpu(pPktSrvc->TLVLength) == 2) && (pPktSrvc->ReconfigReqd == 0x01))
1746*4882a593Smuzhiyun             *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
1747*4882a593Smuzhiyun     }
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun     if (*pConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) {
1750*4882a593Smuzhiyun         if (curIpFamily == IpFamilyV4)
1751*4882a593Smuzhiyun             WdsConnectionIPv4Handle = 0;
1752*4882a593Smuzhiyun         else
1753*4882a593Smuzhiyun             WdsConnectionIPv6Handle = 0;
1754*4882a593Smuzhiyun     }
1755*4882a593Smuzhiyun 
1756*4882a593Smuzhiyun     if (oldConnectionStatus != *pConnectionStatus || debug_qmi) {
1757*4882a593Smuzhiyun         dbg_time("%s %sConnectionStatus: %s", __func__, (curIpFamily == IpFamilyV4) ? "IPv4" : "IPv6",
1758*4882a593Smuzhiyun             (*pConnectionStatus == QWDS_PKT_DATA_CONNECTED) ? "CONNECTED" : "DISCONNECTED");
1759*4882a593Smuzhiyun     }
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun     free(pResponse);
1762*4882a593Smuzhiyun     return 0;
1763*4882a593Smuzhiyun }
1764*4882a593Smuzhiyun 
requestSetupDataCall(PROFILE_T * profile,int curIpFamily)1765*4882a593Smuzhiyun static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
1766*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1767*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1768*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1769*4882a593Smuzhiyun     int err = 0;
1770*4882a593Smuzhiyun     UCHAR QMIType = (curIpFamily == IpFamilyV4) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6;
1771*4882a593Smuzhiyun 
1772*4882a593Smuzhiyun //DualIPSupported means can get ipv4 & ipv6 address at the same time, one wds for ipv4, the other wds for ipv6
1773*4882a593Smuzhiyun     profile->curIpFamily = curIpFamily;
1774*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMIType, QMIWDS_START_NETWORK_INTERFACE_REQ, WdsStartNwInterfaceReq, profile);
1775*4882a593Smuzhiyun     err = QmiThreadSendQMITimeout(pRequest, &pResponse, 120 * 1000, __func__);
1776*4882a593Smuzhiyun     qmi_rsp_check();
1777*4882a593Smuzhiyun 
1778*4882a593Smuzhiyun     if (le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXResult) || le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError)) {
1779*4882a593Smuzhiyun         PQMI_TLV_HDR pTLVHdr;
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun         pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10);
1782*4882a593Smuzhiyun         if (pTLVHdr) {
1783*4882a593Smuzhiyun             uint16_t *data16 = (uint16_t *)(pTLVHdr+1);
1784*4882a593Smuzhiyun             uint16_t call_end_reason = le16_to_cpu(data16[0]);
1785*4882a593Smuzhiyun             dbg_time("call_end_reason is %d", call_end_reason);
1786*4882a593Smuzhiyun         }
1787*4882a593Smuzhiyun 
1788*4882a593Smuzhiyun         pTLVHdr = GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
1789*4882a593Smuzhiyun         if (pTLVHdr) {
1790*4882a593Smuzhiyun             uint16_t *data16 = (uint16_t *)(pTLVHdr+1);
1791*4882a593Smuzhiyun             uint16_t call_end_reason_type = le16_to_cpu(data16[0]);
1792*4882a593Smuzhiyun             uint16_t verbose_call_end_reason  = le16_to_cpu(data16[1]);
1793*4882a593Smuzhiyun 
1794*4882a593Smuzhiyun             dbg_time("call_end_reason_type is %d", call_end_reason_type);
1795*4882a593Smuzhiyun             dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason);
1796*4882a593Smuzhiyun         }
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun         free(pResponse);
1799*4882a593Smuzhiyun         return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
1800*4882a593Smuzhiyun     }
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun     if (curIpFamily == IpFamilyV4) {
1803*4882a593Smuzhiyun         WdsConnectionIPv4Handle = le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle);
1804*4882a593Smuzhiyun         dbg_time("%s WdsConnectionIPv4Handle: 0x%08x", __func__, WdsConnectionIPv4Handle);
1805*4882a593Smuzhiyun     } else {
1806*4882a593Smuzhiyun         WdsConnectionIPv6Handle = le32_to_cpu(pResponse->MUXMsg.StartNwInterfaceResp.Handle);
1807*4882a593Smuzhiyun         dbg_time("%s WdsConnectionIPv6Handle: 0x%08x", __func__, WdsConnectionIPv6Handle);
1808*4882a593Smuzhiyun     }
1809*4882a593Smuzhiyun 
1810*4882a593Smuzhiyun     free(pResponse);
1811*4882a593Smuzhiyun 
1812*4882a593Smuzhiyun     return 0;
1813*4882a593Smuzhiyun }
1814*4882a593Smuzhiyun 
requestDeactivateDefaultPDP(PROFILE_T * profile,int curIpFamily)1815*4882a593Smuzhiyun static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) {
1816*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1817*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1818*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1819*4882a593Smuzhiyun     int err;
1820*4882a593Smuzhiyun     UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6;
1821*4882a593Smuzhiyun 
1822*4882a593Smuzhiyun     (void)profile;
1823*4882a593Smuzhiyun     if (curIpFamily == IpFamilyV4 && WdsConnectionIPv4Handle == 0)
1824*4882a593Smuzhiyun         return 0;
1825*4882a593Smuzhiyun     if (curIpFamily == IpFamilyV6 && WdsConnectionIPv6Handle == 0)
1826*4882a593Smuzhiyun         return 0;
1827*4882a593Smuzhiyun 
1828*4882a593Smuzhiyun     dbg_time("%s WdsConnectionIPv%dHandle", __func__, curIpFamily == IpFamilyV4 ? 4 : 6);
1829*4882a593Smuzhiyun 
1830*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMIType, QMIWDS_STOP_NETWORK_INTERFACE_REQ , WdsStopNwInterfaceReq, &curIpFamily);
1831*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1832*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1833*4882a593Smuzhiyun 
1834*4882a593Smuzhiyun     if (curIpFamily == IpFamilyV4)
1835*4882a593Smuzhiyun         WdsConnectionIPv4Handle = 0;
1836*4882a593Smuzhiyun     else
1837*4882a593Smuzhiyun          WdsConnectionIPv6Handle = 0;
1838*4882a593Smuzhiyun     free(pResponse);
1839*4882a593Smuzhiyun     return 0;
1840*4882a593Smuzhiyun }
1841*4882a593Smuzhiyun 
requestGetIPAddress(PROFILE_T * profile,int curIpFamily)1842*4882a593Smuzhiyun static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) {
1843*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1844*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1845*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1846*4882a593Smuzhiyun     int err;
1847*4882a593Smuzhiyun     PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR pIpv4Addr;
1848*4882a593Smuzhiyun     PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR pIpv6Addr = NULL;
1849*4882a593Smuzhiyun     PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU pMtu;
1850*4882a593Smuzhiyun     IPV4_T *pIpv4 = &profile->ipv4;
1851*4882a593Smuzhiyun     IPV6_T *pIpv6 = &profile->ipv6;
1852*4882a593Smuzhiyun     UCHAR QMIType = (curIpFamily == 0x04) ? QMUX_TYPE_WDS : QMUX_TYPE_WDS_IPV6;
1853*4882a593Smuzhiyun     PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR pPCSCFIpv6Addr;
1854*4882a593Smuzhiyun 	PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR pPCSCFIpv4Addr;
1855*4882a593Smuzhiyun 
1856*4882a593Smuzhiyun     if (curIpFamily == IpFamilyV4) {
1857*4882a593Smuzhiyun         memset(pIpv4, 0x00, sizeof(IPV4_T));
1858*4882a593Smuzhiyun         if (WdsConnectionIPv4Handle == 0)
1859*4882a593Smuzhiyun             return 0;
1860*4882a593Smuzhiyun     } else if (curIpFamily == IpFamilyV6) {
1861*4882a593Smuzhiyun         memset(pIpv6, 0x00, sizeof(IPV6_T));
1862*4882a593Smuzhiyun         if (WdsConnectionIPv6Handle == 0)
1863*4882a593Smuzhiyun             return 0;
1864*4882a593Smuzhiyun     }
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMIType, QMIWDS_GET_RUNTIME_SETTINGS_REQ, WdsGetRuntimeSettingReq, NULL);
1867*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1868*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1869*4882a593Smuzhiyun 
1870*4882a593Smuzhiyun 	pPCSCFIpv6Addr = (PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x2e);    // 0x2e - pcscf ipv6 address
1871*4882a593Smuzhiyun 	if (pPCSCFIpv6Addr) {
1872*4882a593Smuzhiyun     	if (pPCSCFIpv6Addr->PCSCFNumber == 1) {
1873*4882a593Smuzhiyun         	UCHAR *PCSCFIpv6Addr1 = (UCHAR *)(pPCSCFIpv6Addr + 1);
1874*4882a593Smuzhiyun         	memcpy(profile->PCSCFIpv6Addr1, PCSCFIpv6Addr1, 16);
1875*4882a593Smuzhiyun         }else if (pPCSCFIpv6Addr->PCSCFNumber == 2) {
1876*4882a593Smuzhiyun         	UCHAR *PCSCFIpv6Addr1 = (UCHAR *)(pPCSCFIpv6Addr + 1);
1877*4882a593Smuzhiyun         	UCHAR *PCSCFIpv6Addr2 = PCSCFIpv6Addr1 + 16;
1878*4882a593Smuzhiyun         	memcpy(profile->PCSCFIpv6Addr1, PCSCFIpv6Addr1, 16);
1879*4882a593Smuzhiyun         	memcpy(profile->PCSCFIpv6Addr2, PCSCFIpv6Addr2, 16);
1880*4882a593Smuzhiyun         }
1881*4882a593Smuzhiyun     }
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun 	pPCSCFIpv4Addr = (PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x23);    // 0x23 - pcscf ipv4 address
1884*4882a593Smuzhiyun 	if (pPCSCFIpv4Addr) {
1885*4882a593Smuzhiyun     	if (pPCSCFIpv4Addr->PCSCFNumber == 1) {
1886*4882a593Smuzhiyun         	UCHAR *PCSCFIpv4Addr1 = (UCHAR *)(pPCSCFIpv4Addr + 1);
1887*4882a593Smuzhiyun         	memcpy(&profile->PCSCFIpv4Addr1, PCSCFIpv4Addr1, 4);
1888*4882a593Smuzhiyun         }else if (pPCSCFIpv4Addr->PCSCFNumber == 2) {
1889*4882a593Smuzhiyun         	UCHAR *PCSCFIpv4Addr1 = (UCHAR *)(pPCSCFIpv4Addr + 1);
1890*4882a593Smuzhiyun         	UCHAR *PCSCFIpv4Addr2 = PCSCFIpv4Addr1 + 4;
1891*4882a593Smuzhiyun         	memcpy(&profile->PCSCFIpv4Addr1, PCSCFIpv4Addr1, 4);
1892*4882a593Smuzhiyun         	memcpy(&profile->PCSCFIpv4Addr2, PCSCFIpv4Addr2, 4);
1893*4882a593Smuzhiyun         }
1894*4882a593Smuzhiyun     }
1895*4882a593Smuzhiyun 
1896*4882a593Smuzhiyun     pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS);
1897*4882a593Smuzhiyun     if (pIpv4Addr) {
1898*4882a593Smuzhiyun         pIpv4->DnsPrimary = pIpv4Addr->IPV4Address;
1899*4882a593Smuzhiyun     }
1900*4882a593Smuzhiyun 
1901*4882a593Smuzhiyun     pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS);
1902*4882a593Smuzhiyun     if (pIpv4Addr) {
1903*4882a593Smuzhiyun         pIpv4->DnsSecondary = pIpv4Addr->IPV4Address;
1904*4882a593Smuzhiyun     }
1905*4882a593Smuzhiyun 
1906*4882a593Smuzhiyun     pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY);
1907*4882a593Smuzhiyun     if (pIpv4Addr) {
1908*4882a593Smuzhiyun         pIpv4->Gateway = pIpv4Addr->IPV4Address;
1909*4882a593Smuzhiyun     }
1910*4882a593Smuzhiyun 
1911*4882a593Smuzhiyun     pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET);
1912*4882a593Smuzhiyun     if (pIpv4Addr) {
1913*4882a593Smuzhiyun         pIpv4->SubnetMask = pIpv4Addr->IPV4Address;
1914*4882a593Smuzhiyun     }
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun     pIpv4Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4);
1917*4882a593Smuzhiyun     if (pIpv4Addr) {
1918*4882a593Smuzhiyun         pIpv4->Address = pIpv4Addr->IPV4Address;
1919*4882a593Smuzhiyun     }
1920*4882a593Smuzhiyun 
1921*4882a593Smuzhiyun     pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS);
1922*4882a593Smuzhiyun     if (pIpv6Addr) {
1923*4882a593Smuzhiyun         memcpy(pIpv6->DnsPrimary, pIpv6Addr->IPV6Address, 16);
1924*4882a593Smuzhiyun     }
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun     pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS);
1927*4882a593Smuzhiyun     if (pIpv6Addr) {
1928*4882a593Smuzhiyun         memcpy(pIpv6->DnsSecondary, pIpv6Addr->IPV6Address, 16);
1929*4882a593Smuzhiyun     }
1930*4882a593Smuzhiyun 
1931*4882a593Smuzhiyun     pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY);
1932*4882a593Smuzhiyun     if (pIpv6Addr) {
1933*4882a593Smuzhiyun         memcpy(pIpv6->Gateway, pIpv6Addr->IPV6Address, 16);
1934*4882a593Smuzhiyun         pIpv6->PrefixLengthGateway = pIpv6Addr->PrefixLength;
1935*4882a593Smuzhiyun     }
1936*4882a593Smuzhiyun 
1937*4882a593Smuzhiyun     pIpv6Addr = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6);
1938*4882a593Smuzhiyun     if (pIpv6Addr) {
1939*4882a593Smuzhiyun         memcpy(pIpv6->Address, pIpv6Addr->IPV6Address, 16);
1940*4882a593Smuzhiyun         pIpv6->PrefixLengthIPAddr = pIpv6Addr->PrefixLength;
1941*4882a593Smuzhiyun     }
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun     pMtu = (PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU);
1944*4882a593Smuzhiyun     if (pMtu) {
1945*4882a593Smuzhiyun         if (curIpFamily == IpFamilyV4)
1946*4882a593Smuzhiyun             pIpv4->Mtu =  le32_to_cpu(pMtu->Mtu);
1947*4882a593Smuzhiyun         else
1948*4882a593Smuzhiyun             pIpv6->Mtu =  le32_to_cpu(pMtu->Mtu);
1949*4882a593Smuzhiyun     }
1950*4882a593Smuzhiyun 
1951*4882a593Smuzhiyun     free(pResponse);
1952*4882a593Smuzhiyun     return 0;
1953*4882a593Smuzhiyun }
1954*4882a593Smuzhiyun 
1955*4882a593Smuzhiyun #ifdef CONFIG_APN
requestSetProfile(PROFILE_T * profile)1956*4882a593Smuzhiyun static int requestSetProfile(PROFILE_T *profile) {
1957*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1958*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1959*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1960*4882a593Smuzhiyun     int err;
1961*4882a593Smuzhiyun 
1962*4882a593Smuzhiyun     if (!profile->pdp)
1963*4882a593Smuzhiyun         return 0;
1964*4882a593Smuzhiyun 
1965*4882a593Smuzhiyun     dbg_time("%s[%d] %s/%s/%s/%d", __func__, profile->pdp, profile->apn, profile->user, profile->password, profile->auth);
1966*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_MODIFY_PROFILE_SETTINGS_REQ, WdsModifyProfileSettingsReq, profile);
1967*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1968*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1969*4882a593Smuzhiyun 
1970*4882a593Smuzhiyun     free(pResponse);
1971*4882a593Smuzhiyun     return 0;
1972*4882a593Smuzhiyun }
1973*4882a593Smuzhiyun 
requestGetProfile(PROFILE_T * profile)1974*4882a593Smuzhiyun static int requestGetProfile(PROFILE_T *profile) {
1975*4882a593Smuzhiyun     PQCQMIMSG pRequest;
1976*4882a593Smuzhiyun     PQCQMIMSG pResponse;
1977*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
1978*4882a593Smuzhiyun     int err;
1979*4882a593Smuzhiyun     char *apn = NULL;
1980*4882a593Smuzhiyun     char *user = NULL;
1981*4882a593Smuzhiyun     char *password = NULL;
1982*4882a593Smuzhiyun     int auth = 0;
1983*4882a593Smuzhiyun     PQMIWDS_APNNAME pApnName;
1984*4882a593Smuzhiyun     PQMIWDS_USERNAME pUserName;
1985*4882a593Smuzhiyun     PQMIWDS_PASSWD pPassWd;
1986*4882a593Smuzhiyun     PQMIWDS_AUTH_PREFERENCE pAuthPref;
1987*4882a593Smuzhiyun 
1988*4882a593Smuzhiyun     if (!profile->pdp)
1989*4882a593Smuzhiyun         return 0;
1990*4882a593Smuzhiyun 
1991*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile);
1992*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
1993*4882a593Smuzhiyun     qmi_rsp_check_and_return();
1994*4882a593Smuzhiyun 
1995*4882a593Smuzhiyun     pApnName = (PQMIWDS_APNNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14);
1996*4882a593Smuzhiyun     pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B);
1997*4882a593Smuzhiyun     pPassWd = (PQMIWDS_PASSWD)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1C);
1998*4882a593Smuzhiyun     pAuthPref = (PQMIWDS_AUTH_PREFERENCE)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1D);
1999*4882a593Smuzhiyun 
2000*4882a593Smuzhiyun     if (pApnName/* && le16_to_cpu(pApnName->TLVLength)*/)
2001*4882a593Smuzhiyun         apn = strndup((const char *)(&pApnName->ApnName), le16_to_cpu(pApnName->TLVLength));
2002*4882a593Smuzhiyun     if (pUserName/*  && pUserName->UserName*/)
2003*4882a593Smuzhiyun         user = strndup((const char *)(&pUserName->UserName), le16_to_cpu(pUserName->TLVLength));
2004*4882a593Smuzhiyun     if (pPassWd/*  && le16_to_cpu(pPassWd->TLVLength)*/)
2005*4882a593Smuzhiyun         password = strndup((const char *)(&pPassWd->Passwd), le16_to_cpu(pPassWd->TLVLength));
2006*4882a593Smuzhiyun     if (pAuthPref/*  && le16_to_cpu(pAuthPref->TLVLength)*/) {
2007*4882a593Smuzhiyun         auth = pAuthPref->AuthPreference;
2008*4882a593Smuzhiyun     }
2009*4882a593Smuzhiyun 
2010*4882a593Smuzhiyun #if 0
2011*4882a593Smuzhiyun     if (profile) {
2012*4882a593Smuzhiyun         profile->apn = apn;
2013*4882a593Smuzhiyun         profile->user = user;
2014*4882a593Smuzhiyun         profile->password = password;
2015*4882a593Smuzhiyun         profile->auth = auth;
2016*4882a593Smuzhiyun     }
2017*4882a593Smuzhiyun #endif
2018*4882a593Smuzhiyun 
2019*4882a593Smuzhiyun     dbg_time("%s[%d] %s/%s/%s/%d", __func__, profile->pdp, apn, user, password, auth);
2020*4882a593Smuzhiyun 
2021*4882a593Smuzhiyun     free(pResponse);
2022*4882a593Smuzhiyun     return 0;
2023*4882a593Smuzhiyun }
2024*4882a593Smuzhiyun #endif
2025*4882a593Smuzhiyun 
2026*4882a593Smuzhiyun #ifdef CONFIG_SIGNALINFO
requestGetSignalInfo(void)2027*4882a593Smuzhiyun static int requestGetSignalInfo(void)
2028*4882a593Smuzhiyun {
2029*4882a593Smuzhiyun     PQCQMIMSG pRequest;
2030*4882a593Smuzhiyun     PQCQMIMSG pResponse;
2031*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
2032*4882a593Smuzhiyun     int err;
2033*4882a593Smuzhiyun 
2034*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_NAS, QMINAS_GET_SIG_INFO_REQ, NULL, NULL);
2035*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
2036*4882a593Smuzhiyun     qmi_rsp_check_and_return();
2037*4882a593Smuzhiyun 
2038*4882a593Smuzhiyun 
2039*4882a593Smuzhiyun     // CDMA
2040*4882a593Smuzhiyun     {
2041*4882a593Smuzhiyun         PQMINAS_SIG_INFO_CDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_CDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x10);
2042*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2043*4882a593Smuzhiyun         {
2044*4882a593Smuzhiyun             dbg_time("%s CDMA: RSSI %d dBm, ECIO %.1lf dBm", __func__,
2045*4882a593Smuzhiyun                 ptlv->rssi, (-0.5) * (double)ptlv->ecio);
2046*4882a593Smuzhiyun         }
2047*4882a593Smuzhiyun     }
2048*4882a593Smuzhiyun 
2049*4882a593Smuzhiyun     // HDR
2050*4882a593Smuzhiyun     {
2051*4882a593Smuzhiyun         PQMINAS_SIG_INFO_HDR_TLV_MSG ptlv = (PQMINAS_SIG_INFO_HDR_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x11);
2052*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2053*4882a593Smuzhiyun         {
2054*4882a593Smuzhiyun             dbg_time("%s HDR: RSSI %d dBm, ECIO %.1lf dBm, IO %d dBm", __func__,
2055*4882a593Smuzhiyun                 ptlv->rssi, (-0.5) * (double)ptlv->ecio, ptlv->io);
2056*4882a593Smuzhiyun         }
2057*4882a593Smuzhiyun     }
2058*4882a593Smuzhiyun 
2059*4882a593Smuzhiyun     // GSM
2060*4882a593Smuzhiyun     {
2061*4882a593Smuzhiyun         PQMINAS_SIG_INFO_GSM_TLV_MSG ptlv = (PQMINAS_SIG_INFO_GSM_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x12);
2062*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2063*4882a593Smuzhiyun         {
2064*4882a593Smuzhiyun             dbg_time("%s GSM: RSSI %d dBm", __func__, ptlv->rssi);
2065*4882a593Smuzhiyun         }
2066*4882a593Smuzhiyun     }
2067*4882a593Smuzhiyun 
2068*4882a593Smuzhiyun     // WCDMA
2069*4882a593Smuzhiyun     {
2070*4882a593Smuzhiyun         PQMINAS_SIG_INFO_WCDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_WCDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x13);
2071*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2072*4882a593Smuzhiyun         {
2073*4882a593Smuzhiyun             dbg_time("%s WCDMA: RSSI %d dBm, ECIO %.1lf dBm", __func__,
2074*4882a593Smuzhiyun                 ptlv->rssi, (-0.5) * (double)ptlv->ecio);
2075*4882a593Smuzhiyun         }
2076*4882a593Smuzhiyun     }
2077*4882a593Smuzhiyun 
2078*4882a593Smuzhiyun     // LTE
2079*4882a593Smuzhiyun     {
2080*4882a593Smuzhiyun         PQMINAS_SIG_INFO_LTE_TLV_MSG ptlv = (PQMINAS_SIG_INFO_LTE_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14);
2081*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2082*4882a593Smuzhiyun         {
2083*4882a593Smuzhiyun             dbg_time("%s LTE: RSSI %d dBm, RSRQ %d dB, RSRP %d dBm, SNR %.1lf dB", __func__,
2084*4882a593Smuzhiyun                 ptlv->rssi, ptlv->rsrq, ptlv->rsrp, (0.1) * (double)ptlv->snr);
2085*4882a593Smuzhiyun         }
2086*4882a593Smuzhiyun     }
2087*4882a593Smuzhiyun 
2088*4882a593Smuzhiyun     // TDSCDMA
2089*4882a593Smuzhiyun     {
2090*4882a593Smuzhiyun         PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x15);
2091*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2092*4882a593Smuzhiyun         {
2093*4882a593Smuzhiyun             dbg_time("%s LTE: RSCP %d dBm", __func__, ptlv->rscp);
2094*4882a593Smuzhiyun         }
2095*4882a593Smuzhiyun     }
2096*4882a593Smuzhiyun 
2097*4882a593Smuzhiyun     // 5G_NSA
2098*4882a593Smuzhiyun     if (s_5g_type == WWAN_DATA_CLASS_5G_NSA)
2099*4882a593Smuzhiyun     {
2100*4882a593Smuzhiyun         PQMINAS_SIG_INFO_5G_NSA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_5G_NSA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x17);
2101*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2102*4882a593Smuzhiyun         {
2103*4882a593Smuzhiyun             dbg_time("%s 5G_NSA: RSRP %d dBm, SNR %.1lf dB", __func__, ptlv->rsrp, (0.1) * (double)ptlv->snr);
2104*4882a593Smuzhiyun         }
2105*4882a593Smuzhiyun     }
2106*4882a593Smuzhiyun 
2107*4882a593Smuzhiyun     // 5G_SA
2108*4882a593Smuzhiyun     if (s_5g_type == WWAN_DATA_CLASS_5G_SA)
2109*4882a593Smuzhiyun     {
2110*4882a593Smuzhiyun         PQMINAS_SIG_INFO_5G_SA_TLV_MSG ptlv = (PQMINAS_SIG_INFO_5G_SA_TLV_MSG)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x18);
2111*4882a593Smuzhiyun         if (ptlv && ptlv->TLVLength)
2112*4882a593Smuzhiyun         {
2113*4882a593Smuzhiyun             dbg_time("%s 5G_SA: NR5G_RSRQ %d dB", __func__, ptlv->nr5g_rsrq);
2114*4882a593Smuzhiyun         }
2115*4882a593Smuzhiyun     }
2116*4882a593Smuzhiyun 
2117*4882a593Smuzhiyun     free(pResponse);
2118*4882a593Smuzhiyun     return 0;
2119*4882a593Smuzhiyun }
2120*4882a593Smuzhiyun #endif
2121*4882a593Smuzhiyun 
2122*4882a593Smuzhiyun #ifdef CONFIG_VERSION
requestBaseBandVersion(PROFILE_T * profile)2123*4882a593Smuzhiyun static int requestBaseBandVersion(PROFILE_T *profile) {
2124*4882a593Smuzhiyun     PQCQMIMSG pRequest;
2125*4882a593Smuzhiyun     PQCQMIMSG pResponse;
2126*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
2127*4882a593Smuzhiyun     PDEVICE_REV_ID revId;
2128*4882a593Smuzhiyun     int err;
2129*4882a593Smuzhiyun 
2130*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_GET_DEVICE_REV_ID_REQ, NULL, NULL);
2131*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
2132*4882a593Smuzhiyun     qmi_rsp_check_and_return();
2133*4882a593Smuzhiyun 
2134*4882a593Smuzhiyun     revId = (PDEVICE_REV_ID)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
2135*4882a593Smuzhiyun 
2136*4882a593Smuzhiyun     if (revId && le16_to_cpu(revId->TLVLength))
2137*4882a593Smuzhiyun     {
2138*4882a593Smuzhiyun         char *DeviceRevisionID = strndup((const char *)(&revId->RevisionID), le16_to_cpu(revId->TLVLength));
2139*4882a593Smuzhiyun         dbg_time("%s %s", __func__, DeviceRevisionID);
2140*4882a593Smuzhiyun         strncpy(profile->BaseBandVersion, DeviceRevisionID, sizeof(profile->BaseBandVersion));
2141*4882a593Smuzhiyun         free(DeviceRevisionID);
2142*4882a593Smuzhiyun     }
2143*4882a593Smuzhiyun 
2144*4882a593Smuzhiyun     free(pResponse);
2145*4882a593Smuzhiyun     return 0;
2146*4882a593Smuzhiyun }
2147*4882a593Smuzhiyun #endif
2148*4882a593Smuzhiyun 
2149*4882a593Smuzhiyun #ifdef CONFIG_RESET_RADIO
DmsSetOperatingModeReq(PQMUX_MSG pMUXMsg,void * arg)2150*4882a593Smuzhiyun static USHORT DmsSetOperatingModeReq(PQMUX_MSG pMUXMsg, void *arg) {
2151*4882a593Smuzhiyun     pMUXMsg->SetOperatingModeReq.TLVType = 0x01;
2152*4882a593Smuzhiyun     pMUXMsg->SetOperatingModeReq.TLVLength = cpu_to_le16(1);
2153*4882a593Smuzhiyun     pMUXMsg->SetOperatingModeReq.OperatingMode = *((UCHAR *)arg);
2154*4882a593Smuzhiyun 
2155*4882a593Smuzhiyun     return sizeof(QMIDMS_SET_OPERATING_MODE_REQ_MSG);
2156*4882a593Smuzhiyun }
2157*4882a593Smuzhiyun 
requestSetOperatingMode(UCHAR OperatingMode)2158*4882a593Smuzhiyun static int requestSetOperatingMode(UCHAR OperatingMode) {
2159*4882a593Smuzhiyun     PQCQMIMSG pRequest;
2160*4882a593Smuzhiyun     PQCQMIMSG pResponse;
2161*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
2162*4882a593Smuzhiyun     int err;
2163*4882a593Smuzhiyun 
2164*4882a593Smuzhiyun     dbg_time("%s(%d)", __func__, OperatingMode);
2165*4882a593Smuzhiyun 
2166*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_SET_OPERATING_MODE_REQ, DmsSetOperatingModeReq, &OperatingMode);
2167*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
2168*4882a593Smuzhiyun     qmi_rsp_check_and_return();
2169*4882a593Smuzhiyun 
2170*4882a593Smuzhiyun     free(pResponse);
2171*4882a593Smuzhiyun     return 0;
2172*4882a593Smuzhiyun }
2173*4882a593Smuzhiyun #endif
2174*4882a593Smuzhiyun 
WdaSetLoopBackReq(PQMUX_MSG pMUXMsg,void * arg)2175*4882a593Smuzhiyun static USHORT WdaSetLoopBackReq(PQMUX_MSG pMUXMsg, void *arg) {
2176*4882a593Smuzhiyun     (void)arg;
2177*4882a593Smuzhiyun 	pMUXMsg->SetLoopBackReq.loopback_state.TLVType  = 0x01;
2178*4882a593Smuzhiyun 	pMUXMsg->SetLoopBackReq.loopback_state.TLVLength = cpu_to_le16(1);
2179*4882a593Smuzhiyun 
2180*4882a593Smuzhiyun 	pMUXMsg->SetLoopBackReq.replication_factor.TLVType	= 0x10;
2181*4882a593Smuzhiyun 	pMUXMsg->SetLoopBackReq.replication_factor.TLVLength = cpu_to_le16(4);
2182*4882a593Smuzhiyun 
2183*4882a593Smuzhiyun 	return sizeof(QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG);
2184*4882a593Smuzhiyun }
2185*4882a593Smuzhiyun 
requestSetLoopBackState(UCHAR loopback_state,ULONG replication_factor)2186*4882a593Smuzhiyun static int requestSetLoopBackState(UCHAR loopback_state, ULONG replication_factor) {
2187*4882a593Smuzhiyun     PQCQMIMSG pRequest;
2188*4882a593Smuzhiyun     PQCQMIMSG pResponse;
2189*4882a593Smuzhiyun     PQMUX_MSG pMUXMsg;
2190*4882a593Smuzhiyun     int err;
2191*4882a593Smuzhiyun 
2192*4882a593Smuzhiyun     dbg_time("%s(loopback_state=%d, replication_factor=%u)", __func__, loopback_state, replication_factor);
2193*4882a593Smuzhiyun 
2194*4882a593Smuzhiyun     pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS_ADMIN, QMI_WDA_SET_LOOPBACK_CONFIG_REQ, WdaSetLoopBackReq, NULL);
2195*4882a593Smuzhiyun     pRequest->MUXMsg.SetLoopBackReq.loopback_state.TLVVaule = loopback_state;
2196*4882a593Smuzhiyun     pRequest->MUXMsg.SetLoopBackReq.replication_factor.TLVVaule = cpu_to_le16(replication_factor);
2197*4882a593Smuzhiyun 
2198*4882a593Smuzhiyun     err = QmiThreadSendQMI(pRequest, &pResponse);
2199*4882a593Smuzhiyun     qmi_rsp_check_and_return();
2200*4882a593Smuzhiyun 
2201*4882a593Smuzhiyun     free(pResponse);
2202*4882a593Smuzhiyun     return 0;
2203*4882a593Smuzhiyun }
2204*4882a593Smuzhiyun 
2205*4882a593Smuzhiyun const struct request_ops qmi_request_ops = {
2206*4882a593Smuzhiyun #ifdef CONFIG_VERSION
2207*4882a593Smuzhiyun     .requestBaseBandVersion = requestBaseBandVersion,
2208*4882a593Smuzhiyun #endif
2209*4882a593Smuzhiyun     .requestSetEthMode = requestSetEthMode,
2210*4882a593Smuzhiyun #ifdef CONFIG_SIM
2211*4882a593Smuzhiyun     .requestGetSIMStatus = requestGetSIMStatus,
2212*4882a593Smuzhiyun     .requestEnterSimPin = requestEnterSimPin,
2213*4882a593Smuzhiyun #endif
2214*4882a593Smuzhiyun #ifdef CONFIG_IMSI_ICCID
2215*4882a593Smuzhiyun     .requestGetICCID = requestGetICCID,
2216*4882a593Smuzhiyun     .requestGetIMSI = requestGetIMSI,
2217*4882a593Smuzhiyun #endif
2218*4882a593Smuzhiyun #ifdef CONFIG_APN
2219*4882a593Smuzhiyun     .requestSetProfile = requestSetProfile,
2220*4882a593Smuzhiyun     .requestGetProfile = requestGetProfile,
2221*4882a593Smuzhiyun #endif
2222*4882a593Smuzhiyun     .requestRegistrationState = requestRegistrationState,
2223*4882a593Smuzhiyun     .requestSetupDataCall = requestSetupDataCall,
2224*4882a593Smuzhiyun     .requestQueryDataCall = requestQueryDataCall,
2225*4882a593Smuzhiyun     .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP,
2226*4882a593Smuzhiyun     .requestGetIPAddress = requestGetIPAddress,
2227*4882a593Smuzhiyun #ifdef CONFIG_SIGNALINFO
2228*4882a593Smuzhiyun     .requestGetSignalInfo = requestGetSignalInfo,
2229*4882a593Smuzhiyun #endif
2230*4882a593Smuzhiyun     .requestSetLoopBackState = requestSetLoopBackState,
2231*4882a593Smuzhiyun };
2232