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