1/*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "at_data.h"
17
18#include <stdlib.h>
19
20#include "at_support.h"
21#include "hril_notification.h"
22#include "securec.h"
23#include "vendor_report.h"
24
25static int32_t ConvertPdpFailReason(int32_t errorCode)
26{
27    int32_t modemErrorCode = errorCode;
28    int32_t errNo;
29    switch (modemErrorCode) {
30        case PDP_CME_ERR_USER_VERIFICATION:
31        case PDP_CME_ERR_INCORRECT_PASSWORD:
32            errNo = HRIL_PDP_ERR_USER_VERIFICATION;
33            break;
34        case PDP_CME_ERR_INCORRECT_PARAMETERS:
35        case PDP_CME_ERR_OPERATOR_DETERMINED_BARRING:
36            errNo = HRIL_PDP_ERR_OPERATOR_DETERMINED_BARRING;
37            break;
38        case PDP_CME_ERR_SHORTAGE_RESOURCES:
39            errNo = HRIL_PDP_ERR_SHORTAGE_RESOURCES;
40            break;
41        case PDP_CME_ERR_MISSING_OR_UNKNOWN_APN:
42            errNo = HRIL_PDP_ERR_MISSING_OR_UNKNOWN_APN;
43            break;
44        case PDP_CME_ERR_UNKNOWN_PDP_ADDR_OR_TYPE:
45            errNo = HRIL_PDP_ERR_UNKNOWN_PDP_ADDR_OR_TYPE;
46            break;
47        case PDP_CME_ERR_ACTIVATION_REJECTED_GGSN:
48            errNo = HRIL_PDP_ERR_ACTIVATION_REJECTED_GGSN;
49            break;
50        case PDP_CME_ERR_SERVICE_ACTIVATION_REJECTED_UNSPECIFIED:
51            errNo = HRIL_PDP_ERR_ACTIVATION_REJECTED_UNSPECIFIED;
52            break;
53        case PDP_CME_ERR_SERVICE_OPTION_NOT_SUPPORTED:
54            errNo = HRIL_PDP_ERR_SERVICE_OPTION_NOT_SUPPORTED;
55            break;
56        case PDP_CME_ERR_SERVICE_OPTION_NOT_SUBSCRIBED:
57            errNo = HRIL_PDP_ERR_REQUESTED_SERVICE_OPTION_NOT_SUBSCRIBED;
58            break;
59        case PDP_CME_ERR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER:
60            errNo = HRIL_PDP_ERR_SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER;
61            break;
62        case PDP_CME_ERR_NSAPI_ALREADY_USED:
63            errNo = HRIL_PDP_ERR_NSAPI_ALREADY_USED;
64            break;
65        case PDP_CME_ERR_PROTOCOL_ERRORS:
66            errNo = HRIL_PDP_ERR_PROTOCOL_ERRORS;
67            break;
68        default:
69            errNo = HRIL_PDP_ERR_UNKNOWN;
70            break;
71    }
72    return errNo;
73}
74
75static int32_t OnDataReportErrorMessages(const ReqDataInfo *requestInfo, int32_t err, ResponseInfo *pResponse)
76{
77    int32_t errorNo = HRIL_ERR_SUCCESS;
78
79    int32_t slotId = GetSlotId(requestInfo);
80    ModemReportErrorInfo errInfo = GetReportErrorInfo(pResponse);
81    if (err != HRIL_ERR_SUCCESS) {
82        if (err == AT_ERR_CHANNEL_CLOSED) {
83            err = HRIL_ERR_MODEM_DEVICE_CLOSE;
84        } else {
85            err = HRIL_ERR_CMD_SEND_FAILURE;
86        }
87    }
88    errorNo = (err != HRIL_ERR_SUCCESS) ? err : errInfo.errorNo;
89    FreeResponseInfo(pResponse);
90    if (requestInfo != NULL) {
91        struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errorNo, HRIL_RESPONSE, 0);
92        reportInfo.modemErrInfo = errInfo;
93        OnDataReport(slotId, reportInfo, NULL, 0);
94    } else {
95        struct ReportInfo reportInfo =
96            CreateReportInfo(requestInfo, errorNo, HRIL_NOTIFICATION, HNOTI_DATA_PDP_CONTEXT_LIST_UPDATED);
97        reportInfo.modemErrInfo = errInfo;
98        OnDataReport(GetSlotId(NULL), reportInfo, NULL, 0);
99    }
100    return errorNo;
101}
102
103static int32_t OnDataReportPdpErrorMessages(const ReqDataInfo *requestInfo, int32_t err, ResponseInfo *pResponse)
104{
105    HRilDataCallResponse pDataCall = {};
106    ModemReportErrorInfo errInfo = GetReportErrorInfo(pResponse);
107    FreeResponseInfo(pResponse);
108    if (err != HRIL_ERR_SUCCESS) {
109        if (err == AT_ERR_CHANNEL_CLOSED) {
110            err = HRIL_ERR_MODEM_DEVICE_CLOSE;
111        } else {
112            err = HRIL_ERR_CMD_SEND_FAILURE;
113        }
114    }
115    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
116    reportInfo.modemErrInfo = errInfo;
117    pDataCall.reason = ConvertPdpFailReason(errInfo.errorNo);
118    pDataCall.retryTime = INT_DEFAULT_VALUE;
119    pDataCall.cid = INT_DEFAULT_VALUE;
120    OnDataReport(GetSlotId(requestInfo), reportInfo, (const uint8_t *)&pDataCall, sizeof(HRilDataCallResponse));
121    return (err != HRIL_ERR_SUCCESS) ? err : errInfo.errorNo;
122}
123
124int32_t ParsePdpCmd(char *str, HRilDataCallResponse *outData)
125{
126    char *pStr = NULL;
127
128    if (str == NULL || outData == NULL) {
129        TELEPHONY_LOGE("param error");
130        return HRIL_ERR_NULL_POINT;
131    }
132    pStr = str;
133    if (ReportStrWith(str, "+CGACT:")) {
134        if (SkipATPrefix(&pStr) < 0) {
135            return HRIL_ERR_NULL_POINT;
136        }
137        if (NextInt(&pStr, &outData->cid) < 0) {
138            return HRIL_ERR_NULL_POINT;
139        }
140        if (NextInt(&pStr, &outData->active) < 0) {
141            return HRIL_ERR_NULL_POINT;
142        }
143        outData->reason = HRIL_PDP_ERR_RETRY;
144    } else if (ReportStrWith(str, "+CGDCONT:")) {
145        if (SkipATPrefix(&pStr) < 0) {
146            return HRIL_ERR_NULL_POINT;
147        }
148        if (NextInt(&pStr, &outData->cid) < 0) {
149            return HRIL_ERR_NULL_POINT;
150        }
151        if (NextStr(&pStr, &outData->type) < 0) {
152            return HRIL_ERR_NULL_POINT;
153        }
154    } else {
155        return HRIL_ERR_NULL_POINT;
156    }
157    return HRIL_ERR_SUCCESS;
158}
159
160static HRilDataCallResponse *CreatDataCallResponseAndInit(int32_t count)
161{
162    int32_t size;
163    HRilDataCallResponse *newDcr = NULL;
164
165    size = count * sizeof(HRilDataCallResponse);
166    if (size <= 0) {
167        TELEPHONY_LOGE("param is error, size=%{public}d", size);
168        return newDcr;
169    }
170    newDcr = (HRilDataCallResponse *)malloc(size);
171    if (newDcr == NULL) {
172        return NULL;
173    }
174    (void)memset_s(newDcr, size, 0, size);
175    return newDcr;
176}
177
178static ModemReportErrorInfo SendInquireCGACT(int32_t *outDataNum, HRilDataCallResponse **ppDcr)
179{
180    int32_t ret;
181    int32_t dataCallNum = 0;
182    Line *pLine = NULL;
183    ResponseInfo *pResponse = NULL;
184    ModemReportErrorInfo errInfo = {};
185
186    ret = SendCommandLock("AT+CGACT?", "+CGACT:", 0, &pResponse);
187    if (ret != 0 || pResponse == NULL || !pResponse->success || outDataNum == NULL || ppDcr == NULL) {
188        errInfo = GetReportErrorInfo(pResponse);
189        errInfo.errorNo = (ret != HRIL_ERR_SUCCESS) ? ret : errInfo.errorNo;
190        TELEPHONY_LOGE("send AT CMD failed! ret:%{public}d", errInfo.errorNo);
191        FreeResponseInfo(pResponse);
192        return errInfo;
193    }
194
195    for (pLine = pResponse->head; pLine != NULL; pLine = pLine->next) {
196        dataCallNum++;
197    }
198
199    *ppDcr = CreatDataCallResponseAndInit(dataCallNum);
200    if (*ppDcr == NULL) {
201        pResponse->success = 0;
202        errInfo = GetReportErrorInfo(pResponse);
203        FreeResponseInfo(pResponse);
204        TELEPHONY_LOGE("ppDcr is NULL! ret:%{public}d", errInfo.errorNo);
205        return errInfo;
206    }
207    HRilDataCallResponse *pDataCall = *ppDcr;
208    for (pLine = pResponse->head; pLine != NULL; pLine = pLine->next) {
209        ret = ParsePdpCmd(pLine->data, pDataCall);
210        if (ret != 0) {
211            continue;
212        }
213        pDataCall++;
214    }
215    *outDataNum = dataCallNum;
216    FreeResponseInfo(pResponse);
217    return errInfo;
218}
219
220static void BuildDataInfoList(
221    int32_t *validCount, int32_t dataNum, ResponseInfo *response, HRilDataCallResponse **ppDcr)
222{
223    if (validCount == NULL || response == NULL || ppDcr == NULL || *ppDcr == NULL) {
224        return;
225    }
226    int32_t ret;
227    int32_t i = 0;
228    int32_t count = 0;
229    int32_t dataCallNum = 0;
230    Line *pLine = NULL;
231    ResponseInfo *pResponse = response;
232    HRilDataCallResponse *pDataCall = *ppDcr;
233    HRilDataCallResponse dataCGDCONT;
234
235    dataCallNum = dataNum;
236    for (pLine = pResponse->head; pLine != NULL; pLine = pLine->next) {
237        ret = memset_s(&dataCGDCONT, sizeof(HRilDataCallResponse), 0, sizeof(HRilDataCallResponse));
238        if (ret != EOK) {
239            TELEPHONY_LOGE("memset_s is failed!");
240        }
241        ret = ParsePdpCmd(pLine->data, &dataCGDCONT);
242        if (ret != 0) {
243            TELEPHONY_LOGE("parser pdp command failed: [%{public}s],ret=%{public}d", pLine->data, ret);
244            continue;
245        }
246        for (i = 0; i < dataCallNum; i++) {
247            if ((*ppDcr)[i].cid == dataCGDCONT.cid) {
248                break;
249            }
250        }
251        if (i >= dataCallNum) {
252            continue;
253        }
254        if (dataCGDCONT.type != NULL) {
255            pDataCall->type = strdup(dataCGDCONT.type);
256        }
257        pDataCall->netPortName = strdup(NET_NODE);
258        pDataCall++;
259        count++;
260    }
261    *validCount = count;
262}
263
264static int32_t AddressFormat(uint64_t addr, char *outBuf, size_t bufLen)
265{
266    int32_t data[IPV4_INDEX_MAX] = { 0 };
267    const int32_t index1st = 0;
268    const int32_t index2nd = 1;
269    const int32_t index3rd = 2;
270    const int32_t index4th = 3;
271
272    if ((outBuf == NULL) || !bufLen) {
273        TELEPHONY_LOGE("outBuf is Null or bufLen is zero!");
274        return -HRIL_ERR_GENERIC_FAILURE;
275    }
276    int32_t ret = memset_s(outBuf, bufLen, 0, bufLen);
277    if (ret != EOK) {
278        TELEPHONY_LOGE("memset_s outBuf is failed!");
279        return -HRIL_ERR_GENERIC_FAILURE;
280    }
281    data[index1st] = (int32_t)((addr >> ADDR_OFFSET_0BIT) & ADDR_MASK);
282    data[index2nd] = (int32_t)((addr >> ADDR_OFFSET_8BIT) & ADDR_MASK);
283    data[index3rd] = (int32_t)((addr >> ADDR_OFFSET_16BIT) & ADDR_MASK);
284    data[index4th] = (int32_t)((addr >> ADDR_OFFSET_24BIT) & ADDR_MASK);
285    GenerateCommand(
286        outBuf, MAX_CMD_LENGTH, "%d.%d.%d.%d", data[index1st], data[index2nd], data[index3rd], data[index4th]);
287    return HRIL_ERR_SUCCESS;
288}
289
290static int32_t NetMaskFormat(uint64_t addr, char *outBuf, size_t bufLen)
291{
292    if (addr < IPV4_MASK_MIN || addr > IPV4_MASK_MAX) {
293        return HRIL_ERR_NULL_POINT;
294    }
295    if ((outBuf == NULL) || !bufLen) {
296        TELEPHONY_LOGE("outBuf is Null or bufLen is zero!");
297        return HRIL_ERR_NULL_POINT;
298    }
299    int32_t ret = memset_s(outBuf, bufLen, 0, bufLen);
300    if (ret != EOK) {
301        TELEPHONY_LOGE("memset_s outBuf is failed!");
302        return HRIL_ERR_NULL_POINT;
303    }
304    int32_t prefixLen = IPV4_MASK_LEN_MIN;
305    for (int32_t i = ADDR_OFFSET_8BIT; i <= ADDR_OFFSET_24BIT; i += ADDR_OFFSET_8BIT) {
306        uint32_t maskValue = (addr >> i) & ADDR_MASK;
307        while ((maskValue & IPV4_BIT_MASK) != 0) {
308            prefixLen++;
309            maskValue = (maskValue << 1);
310        }
311    }
312    GenerateCommand(outBuf, MAX_CMD_LENGTH, "/%d", prefixLen);
313    return HRIL_ERR_SUCCESS;
314}
315
316static ModemReportErrorInfo GetLinkInformation(int32_t activeIndex, HRilDataCallResponse **ppDcr)
317{
318    int32_t ret;
319    char readBuf[MAX_CMD_LENGTH] = {0};
320    char *lineStr = NULL;
321    Line *pLine = NULL;
322    ResponseInfo *pResponse = NULL;
323    ModemReportErrorInfo errInfo = {};
324
325    ret = SendCommandLock("AT^DHCP?", "^DHCP:", 0, &pResponse);
326    if (ret != 0 || pResponse == NULL || pResponse->head == NULL || !pResponse->success) {
327        errInfo = GetReportErrorInfo(pResponse);
328        errInfo.errorNo = (ret != HRIL_ERR_SUCCESS) ? ret : errInfo.errorNo;
329        TELEPHONY_LOGE("send AT CMD failed! ret:%{public}d", errInfo.errorNo);
330        FreeResponseInfo(pResponse);
331        return errInfo;
332    }
333    if (ppDcr == NULL || *ppDcr == NULL) {
334        pResponse->success = 0;
335        errInfo = GetReportErrorInfo(pResponse);
336        FreeResponseInfo(pResponse);
337        TELEPHONY_LOGE("ppDcr is NULL! ret:%{public}d", errInfo.errorNo);
338        return errInfo;
339    }
340    pLine = pResponse->head;
341    lineStr = pLine->data;
342    uint64_t addr = 0;
343    SkipATPrefix(&lineStr);
344    NextULongFromHex(&lineStr, &addr); // ip
345    AddressFormat(addr, readBuf, MAX_CMD_LENGTH);
346    NextULongFromHex(&lineStr, &addr); // subnet mask
347    ret = strlen(readBuf);
348    NetMaskFormat(addr, &readBuf[ret], MAX_CMD_LENGTH - ret);
349    (*ppDcr)[activeIndex].address = strdup(readBuf);
350    NextULongFromHex(&lineStr, &addr); // default gateway
351    AddressFormat(addr, readBuf, MAX_CMD_LENGTH);
352    (*ppDcr)[activeIndex].gateway = strdup(readBuf);
353    NextULongFromHex(&lineStr, &addr); // DHCP server
354    NextULongFromHex(&lineStr, &addr); // primary DNS server
355    AddressFormat(addr, readBuf, MAX_CMD_LENGTH);
356    (*ppDcr)[activeIndex].dns = strdup(readBuf);
357    NextULongFromHex(&lineStr, &addr); // secondary DNS server
358    FreeResponseInfo(pResponse);
359    (*ppDcr)[activeIndex].reason = HRIL_PDP_ERR_NONE;
360    return errInfo;
361}
362
363static ModemReportErrorInfo SendInquireCGDCONT(int32_t *validCount, int32_t dataNum, HRilDataCallResponse **ppDcr)
364{
365    int32_t ret;
366    ResponseInfo *pResponse = NULL;
367    ModemReportErrorInfo errInfo = {};
368
369    ret = SendCommandLock("AT+CGDCONT?", "+CGDCONT:", 0, &pResponse);
370    if (ret != 0 || pResponse == NULL || !pResponse->success) {
371        errInfo = GetReportErrorInfo(pResponse);
372        errInfo.errorNo = (ret != HRIL_ERR_SUCCESS) ? ret : errInfo.errorNo;
373        TELEPHONY_LOGE("send AT CMD failed! ret:%{public}d", errInfo.errorNo);
374        FreeResponseInfo(pResponse);
375        return errInfo;
376    }
377
378    if (ppDcr == NULL || *ppDcr == NULL) {
379        pResponse->success = 0;
380        errInfo = GetReportErrorInfo(pResponse);
381        FreeResponseInfo(pResponse);
382        TELEPHONY_LOGE("ppDcr is NULL! ret:%{public}d", errInfo.errorNo);
383        return errInfo;
384    }
385    BuildDataInfoList(validCount, dataNum, pResponse, ppDcr);
386    FreeResponseInfo(pResponse);
387    return errInfo;
388}
389
390static int32_t QueryAllSupportPDNInfos(PDNInfo *pdnInfo)
391{
392    if (pdnInfo == NULL) {
393        return -1;
394    }
395    char *pStr = NULL;
396    int32_t ret = -1;
397    Line *pLine = NULL;
398    PDNInfo *pdns = pdnInfo;
399    ResponseInfo *pResponse = NULL;
400
401    ret = SendCommandLock("AT+CGDCONT?", "+CGDCONT:", 0, &pResponse);
402    if (ret != 0 || pResponse == NULL || !pResponse->success) {
403        ModemReportErrorInfo errInfo = GetReportErrorInfo(pResponse);
404        errInfo.errorNo = (ret != HRIL_ERR_SUCCESS) ? ret : errInfo.errorNo;
405        TELEPHONY_LOGE("send AT CMD failed! ret:%{public}d", ret);
406        FreeResponseInfo(pResponse);
407        return errInfo.errorNo;
408    }
409    for (pLine = pResponse->head; pLine != NULL; pLine = pLine->next) {
410        pStr = pLine->data;
411        ret = SkipATPrefix(&pStr);
412        if (ret < 0) {
413            pdns->cid = INT_DEFAULT_VALUE;
414        }
415        ret = NextInt(&pStr, &pdns->cid);
416        if (ret < 0) {
417            pdns->cid = INT_DEFAULT_VALUE;
418        }
419        ret = NextStr(&pStr, &pdns->ipType);
420        if (ret < 0) {
421            pdns->cid = INT_DEFAULT_VALUE;
422        }
423        ret = NextStr(&pStr, &pdns->apn);
424        if (ret < 0) {
425            pdns->cid = INT_DEFAULT_VALUE;
426        }
427        pdns++;
428    }
429    FreeResponseInfo(pResponse);
430    return ret;
431}
432
433static int32_t IsStrEmpty(const char *str)
434{
435    if (str == NULL || strcmp(str, "") == 0) {
436        return TRUE;
437    }
438    return FALSE;
439}
440
441static int32_t IsStrEqual(const char *src1, const char *src2)
442{
443    int32_t ret = FALSE;
444    if (IsStrEmpty(src1) && IsStrEmpty(src2)) {
445        ret = TRUE;
446    } else if (!IsStrEmpty(src1) && !IsStrEmpty(src2)) {
447        if (strcasecmp(src1, src2) == 0) {
448            ret = TRUE;
449        } else {
450            TELEPHONY_LOGE("IsStrEqual src1=%{public}s, src2=%{public}s", src1, src2);
451        }
452    } else {
453        TELEPHONY_LOGE("IsStrEqual src1 or src2 is empty!");
454    }
455    return ret;
456}
457
458static int32_t QuerySupportCID(const PDNInfo *pdnInfos, int32_t pdnSize, const char *apn, const char *ipType)
459{
460    int32_t i;
461    int32_t j;
462    int32_t isUsedCid = 0;
463    int32_t cid = INT_DEFAULT_VALUE;
464    if (pdnInfos == NULL) {
465        return cid;
466    }
467
468    for (j = 0; j < pdnSize; j++) {
469        if (IsStrEqual(apn, pdnInfos[j].apn)) {
470            cid = pdnInfos[j].cid;
471            break;
472        }
473    }
474    if (cid > 0) {
475        return cid;
476    }
477    for (i = MIN_CID; i <= MAX_CID; i++) {
478        isUsedCid = 0;
479        for (j = 0; j < pdnSize; j++) {
480            if (pdnInfos[j].cid == i) {
481                isUsedCid = 1;
482                break;
483            }
484        }
485        if (isUsedCid == 1) {
486            cid = i;
487            break;
488        }
489    }
490    return cid;
491}
492
493static int32_t GetNeedActivateCid(const char *apn, const char *ipType)
494{
495    int32_t cid = DEFAULT_CID;
496    PDNInfo pdnInfos[MAX_PDP_NUM] = {{DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""},
497        {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""},
498        {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}, {DEFAULT_CID, "", ""}};
499
500    if (!QueryAllSupportPDNInfos(pdnInfos)) {
501        cid = QuerySupportCID(pdnInfos, MAX_PDP_NUM, apn, ipType);
502    }
503    return cid;
504}
505
506static void FreeDataCallResponse(HRilDataCallResponse *pDcrs, int32_t size)
507{
508    int32_t i = 0;
509
510    if (pDcrs == NULL) {
511        return;
512    }
513    for (i = 0; i < size; i++) {
514        if (pDcrs[i].address != NULL) {
515            free(pDcrs[i].address);
516        }
517        if (pDcrs[i].netPortName != NULL) {
518            free(pDcrs[i].netPortName);
519        }
520        if (pDcrs[i].type != NULL) {
521            free(pDcrs[i].type);
522        }
523        if (pDcrs[i].dns != NULL) {
524            free(pDcrs[i].dns);
525        }
526        if (pDcrs[i].gateway != NULL) {
527            free(pDcrs[i].gateway);
528        }
529    }
530    free(pDcrs);
531}
532
533static void DataReportMessage(int32_t cid, const ReqDataInfo *requestInfo, ModemReportErrorInfo errInfo,
534    HRilDataCallResponse *pDataCalls, int32_t validNum)
535{
536    struct ReportInfo reportInfo = {};
537    int32_t slotId = GetSlotId(requestInfo);
538    if (requestInfo != NULL) {
539        /* Report results */
540        int32_t index;
541        reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
542        reportInfo.modemErrInfo = errInfo;
543        if ((cid == DEFAULT_CID) || (pDataCalls == NULL)) {
544            OnDataReport(slotId, reportInfo, (const uint8_t *)pDataCalls, validNum * sizeof(HRilDataCallResponse));
545            FreeDataCallResponse(pDataCalls, validNum);
546            return;
547        }
548        for (index = 0; index < validNum; index++) {
549            if (pDataCalls[index].cid == cid) {
550                break;
551            }
552        }
553        OnDataReport(slotId, reportInfo, (const uint8_t *)&pDataCalls[index], sizeof(HRilDataCallResponse));
554    } else {
555        /* Change notice */
556        reportInfo.requestInfo = NULL;
557        reportInfo.error = errInfo.errorNo;
558        reportInfo.modemErrInfo = errInfo;
559        reportInfo.notifyId = HNOTI_DATA_PDP_CONTEXT_LIST_UPDATED;
560        reportInfo.type = HRIL_NOTIFICATION;
561        OnDataReport(GetSlotId(NULL), reportInfo, (const uint8_t *)pDataCalls, validNum * sizeof(HRilDataCallResponse));
562    }
563    FreeDataCallResponse(pDataCalls, validNum);
564}
565
566static void InquirePdpContextList(int32_t cid, const ReqDataInfo *requestInfo)
567{
568    int32_t validNum = 0;
569    int32_t queryCount = 0;
570    int32_t dataCallNum = 0;
571    HRilDataCallResponse *pDataCalls = NULL;
572
573    do {
574        ModemReportErrorInfo errInfo = SendInquireCGACT(&dataCallNum, &pDataCalls);
575        if (errInfo.errorNo != HRIL_ERR_SUCCESS) {
576            TELEPHONY_LOGE("SendInquireCGACT send failed");
577            OnDataReportErrorMessages(requestInfo, errInfo.errorNo, NULL);
578            FreeDataCallResponse(pDataCalls, validNum);
579            return;
580        }
581        for (int32_t i = 0; i < dataCallNum; i++) {
582            if ((pDataCalls[i].cid == cid) && (DEACTIVATE == pDataCalls[i].active)) {
583                errInfo.errorNo = HRIL_ERR_GENERIC_FAILURE;
584                usleep(QUERY_DELAY_MS * DELAY_US_OFFSET);
585                queryCount++;
586                break;
587            }
588        }
589        if (errInfo.errorNo == HRIL_ERR_SUCCESS) {
590            break;
591        }
592    } while ((cid != DEFAULT_CID) && (queryCount < QUERY_MAX_COUNT));
593
594    ModemReportErrorInfo errInfo = SendInquireCGDCONT(&validNum, dataCallNum, &pDataCalls);
595    if (errInfo.errorNo != HRIL_ERR_SUCCESS) {
596        TELEPHONY_LOGE("SendInquireCGDCONT send failed");
597        OnDataReportErrorMessages(requestInfo, errInfo.errorNo, NULL);
598        FreeDataCallResponse(pDataCalls, validNum);
599        return;
600    }
601    for (int32_t index = 0; index < validNum; index++) {
602        if (ACTIVATE == pDataCalls[index].active) {
603            errInfo = GetLinkInformation(index, &pDataCalls);
604            if (errInfo.errorNo != HRIL_ERR_SUCCESS) {
605                TELEPHONY_LOGE("Get link information is failed!");
606                OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
607                FreeDataCallResponse(pDataCalls, validNum);
608                return;
609            }
610        }
611    }
612    DataReportMessage(cid, requestInfo, errInfo, pDataCalls, validNum);
613}
614
615static int32_t SendCmdCGDCONT(int32_t cid, const ReqDataInfo *requestInfo, const HRilDataInfo *pDataInfo)
616{
617    if (pDataInfo == NULL) {
618        return -1;
619    }
620    int32_t ret;
621    int32_t err = HRIL_ERR_SUCCESS;
622    char cmd[MAX_CMD_LENGTH] = {0};
623    ResponseInfo *pResponse = NULL;
624    ret = GenerateCommand(
625        cmd, MAX_CMD_LENGTH, "AT+CGDCONT=%d,\"%s\",\"%s\",\"\",0,0", cid, pDataInfo->type, pDataInfo->apn);
626    if (ret < 0) {
627        TELEPHONY_LOGE("GenerateCommand is failed!");
628        OnDataReportPdpErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
629        return ret;
630    }
631    ret = SendCommandLock(cmd, NULL, 0, &pResponse);
632    if (ret != 0 || pResponse == NULL || !pResponse->success) {
633        err = (ret != HRIL_ERR_SUCCESS) ? ret : err;
634        ret = OnDataReportPdpErrorMessages(requestInfo, err, pResponse);
635        TELEPHONY_LOGE("cmd send failed, err:%{public}d", ret);
636        return ret;
637    }
638    FreeResponseInfo(pResponse);
639    return HRIL_ERR_SUCCESS;
640}
641
642static int32_t SendCmdNDISDUP(int32_t cid, int32_t activate, const ReqDataInfo *requestInfo)
643{
644    int32_t ret;
645    int32_t err = HRIL_ERR_SUCCESS;
646    char cmd[MAX_CMD_LENGTH] = {0};
647    ResponseInfo *pResponse = NULL;
648
649    ret = GenerateCommand(cmd, MAX_CMD_LENGTH, "AT^NDISDUP=%d,%d", cid, activate);
650    if (ret < 0) {
651        TELEPHONY_LOGE("GenerateCommand is failed!");
652        OnDataReportPdpErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
653        return ret;
654    }
655    ret = SendCommandLock(cmd, NULL, 0, &pResponse);
656    if ((ret != HRIL_ERR_SUCCESS) || pResponse == NULL || !pResponse->success) {
657        err = (ret != HRIL_ERR_SUCCESS) ? ret : err;
658        ret = OnDataReportPdpErrorMessages(requestInfo, err, pResponse);
659        TELEPHONY_LOGE("cmd send failed, err:%{public}d", ret);
660        return ret;
661    }
662    FreeResponseInfo(pResponse);
663    return HRIL_ERR_SUCCESS;
664}
665
666static int32_t RouteUp(void)
667{
668    int32_t ret = system("ifconfig usb0 up");
669    if (ret != 0) {
670        TELEPHONY_LOGE("exec system is failed! ret:%{public}d, %{public}s", ret, strerror(ret));
671        return ret;
672    }
673    TELEPHONY_LOGI("Open net device is finished!");
674    return HRIL_ERR_SUCCESS;
675}
676
677static int32_t RouteDown(void)
678{
679    int32_t ret = system("ifconfig usb0 down");
680    if (ret != 0) {
681        TELEPHONY_LOGE("exec system is failed! ret:%{public}d, %{public}s", ret, strerror(ret));
682        return ret;
683    }
684    TELEPHONY_LOGI("Close net device is finished!");
685    return HRIL_ERR_SUCCESS;
686}
687
688void ReqActivatePdpContext(const ReqDataInfo *requestInfo, const HRilDataInfo *data)
689{
690    int32_t cid = INT_DEFAULT_VALUE;
691    const HRilDataInfo *pDataInfo = data;
692
693    if (pDataInfo == NULL) {
694        TELEPHONY_LOGE("data is null!!!");
695        OnDataReportPdpErrorMessages(requestInfo, HRIL_ERR_INVALID_PARAMETER, NULL);
696        return;
697    }
698    if (RouteUp() != HRIL_ERR_SUCCESS) {
699        OnDataReportPdpErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
700        return;
701    }
702    cid = GetNeedActivateCid(pDataInfo->apn, pDataInfo->type);
703    if (cid == INT_DEFAULT_VALUE) {
704        TELEPHONY_LOGE("cid is invalid!!!");
705        OnDataReportPdpErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
706        RouteDown();
707        return;
708    }
709    if (SendCmdCGDCONT(cid, requestInfo, pDataInfo) != HRIL_ERR_SUCCESS) {
710        RouteDown();
711        return;
712    }
713    if (SendCmdNDISDUP(cid, ACTIVATE, requestInfo) != HRIL_ERR_SUCCESS) {
714        RouteDown();
715        return;
716    }
717    InquirePdpContextList(cid, requestInfo);
718}
719
720void ReqActivatePdpContextWithApnTypes(const ReqDataInfo *requestInfo, const HRilDataInfoWithApnTypes *data)
721{
722    TELEPHONY_LOGI("Call V1_1 ReqActivatePdpContext");
723    HRilDataInfo pDataInfo;
724    pDataInfo.cid = data->cid;
725    pDataInfo.reason = data->reason;
726    pDataInfo.roamingEnable = data->roamingEnable;
727    pDataInfo.verType = data->verType;
728    pDataInfo.userName = data->userName;
729    pDataInfo.password = data->password;
730    pDataInfo.apn = data->apn;
731    pDataInfo.type = data->type;
732    pDataInfo.roamingType = data->roamingType;
733    ReqActivatePdpContext(requestInfo, &pDataInfo);
734}
735
736void ReqDeactivatePdpContext(const ReqDataInfo *requestInfo, const HRilDataInfo *data)
737{
738    const HRilDataInfo *pDataInfo = data;
739    ModemReportErrorInfo errInfo = {};
740
741    if (pDataInfo == NULL) {
742        TELEPHONY_LOGE("data is null!!!");
743        OnDataReportErrorMessages(requestInfo, HRIL_ERR_INVALID_PARAMETER, NULL);
744        return;
745    }
746    if (SendCmdNDISDUP(pDataInfo->cid, DEACTIVATE, requestInfo) != HRIL_ERR_SUCCESS) {
747        RouteDown();
748        return;
749    }
750    if (RouteDown() != HRIL_ERR_SUCCESS) {
751        OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
752        return;
753    }
754    DataReportMessage(pDataInfo->cid, requestInfo, errInfo, NULL, 0);
755}
756
757void ReqGetPdpContextList(const ReqDataInfo *requestInfo)
758{
759    InquirePdpContextList(DEFAULT_CID, requestInfo);
760}
761
762static void PdpContextListCallback(uint8_t *param)
763{
764    InquirePdpContextList(DEFAULT_CID, NULL);
765}
766
767void PdpContextListUpdate(void)
768{
769    struct timeval tv = {0, CALLBACK_DELAY_MS * DELAY_US_OFFSET};
770    OnTimerCallback(PdpContextListCallback, NULL, &tv);
771}
772
773static int32_t SetDataProfileInfo(int32_t cid, const ReqDataInfo *requestInfo, const HRilDataInfo *pDataInfo)
774{
775    if (pDataInfo == NULL) {
776        return -1;
777    }
778    int32_t ret;
779    int32_t err = HRIL_ERR_SUCCESS;
780    char cmd[MAX_CMD_LENGTH] = {0};
781    ResponseInfo *pResponse = NULL;
782
783    ret = GenerateCommand(
784        cmd, MAX_CMD_LENGTH, "AT+CGDCONT=%d,\"%s\",\"%s\",\"\",0,0", cid, pDataInfo->type, pDataInfo->apn);
785    if (ret < 0) {
786        TELEPHONY_LOGE("GenerateCommand is failed!");
787        OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
788        return ret;
789    }
790    ret = SendCommandLock(cmd, NULL, 0, &pResponse);
791    if (ret != 0 || pResponse == NULL || !pResponse->success) {
792        err = (ret != HRIL_ERR_SUCCESS) ? ret : err;
793        ret = OnDataReportErrorMessages(requestInfo, err, pResponse);
794        TELEPHONY_LOGE("cmd send failed, err:%{public}d", err);
795        return ret;
796    }
797    FreeResponseInfo(pResponse);
798    if ((pDataInfo->verType >= VERIFY_TYPE_MIN) && (pDataInfo->verType <= VERIFY_TYPE_MAX)) {
799        ret = GenerateCommand(cmd, MAX_CMD_LENGTH, "AT^AUTHDATA=%d,%d,\"\",\"%s\",\"%s\"", cid, pDataInfo->verType,
800            pDataInfo->password, pDataInfo->userName);
801        if (ret < 0) {
802            TELEPHONY_LOGE("GenerateCommand is failed!");
803            OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
804            return ret;
805        }
806        ret = SendCommandLock(cmd, NULL, 0, &pResponse);
807        if (ret != 0 || pResponse == NULL || !pResponse->success) {
808            err = (ret != HRIL_ERR_SUCCESS) ? ret : err;
809            ret = OnDataReportErrorMessages(requestInfo, err, pResponse);
810            TELEPHONY_LOGE("cmd send failed, err:%{public}d", err);
811            return ret;
812        }
813        FreeResponseInfo(pResponse);
814    }
815    return HRIL_ERR_SUCCESS;
816}
817
818void ReqSetInitApnInfo(const ReqDataInfo *requestInfo, const HRilDataInfo *data)
819{
820    int32_t cid = INT_DEFAULT_VALUE;
821    const HRilDataInfo *pDataInfo = data;
822    ModemReportErrorInfo errInfo = {};
823
824    if (pDataInfo == NULL) {
825        TELEPHONY_LOGE("data is null!!!");
826        OnDataReportErrorMessages(requestInfo, HRIL_ERR_INVALID_PARAMETER, NULL);
827        return;
828    }
829    cid = GetNeedActivateCid(pDataInfo->apn, pDataInfo->type);
830    if (cid == INT_DEFAULT_VALUE) {
831        TELEPHONY_LOGE("cid is invalid!!!");
832        OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
833        return;
834    }
835    if (SetDataProfileInfo(cid, requestInfo, pDataInfo) != HRIL_ERR_SUCCESS) {
836        TELEPHONY_LOGE("Set data profile info is failed!");
837        return;
838    }
839    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
840    reportInfo.modemErrInfo = errInfo;
841    OnDataReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
842}
843
844void ReqSetLinkBandwidthReportingRule(const ReqDataInfo *requestInfo, const HRilLinkBandwidthReportingRule *data)
845{
846    const HRilLinkBandwidthReportingRule *linkBandwidthRule = data;
847    ModemReportErrorInfo errInfo = {};
848
849    if (linkBandwidthRule == NULL) {
850        TELEPHONY_LOGE("data is null!!!");
851        OnDataReportErrorMessages(requestInfo, HRIL_ERR_INVALID_PARAMETER, NULL);
852        return;
853    }
854    TELEPHONY_LOGI("rat:%{public}d, delayMs:%{public}d", linkBandwidthRule->rat, linkBandwidthRule->delayMs);
855    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
856    reportInfo.modemErrInfo = errInfo;
857    OnDataReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
858}
859
860static int32_t CallCmdC5GQOSRDP(const char *lineCmd, HRilLinkBandwidthInfo *outCall)
861{
862    char *pLine = (char *)lineCmd;
863    if (pLine == NULL || outCall == NULL) {
864        TELEPHONY_LOGE("pLine or outCall is null.");
865        return HRIL_ERR_NULL_POINT;
866    }
867    if (SkipATPrefix(&pLine) < 0) {
868        return HRIL_ERR_NULL_POINT;
869    }
870    if (NextInt(&pLine, &outCall->cid) < 0) {
871        return HRIL_ERR_NULL_POINT;
872    }
873    if (NextInt(&pLine, &outCall->qi) < 0) {
874        return HRIL_ERR_NULL_POINT;
875    }
876    if (NextInt(&pLine, &outCall->dlGfbr) < 0) {
877        return HRIL_ERR_NULL_POINT;
878    }
879    if (NextInt(&pLine, &outCall->ulGfbr) < 0) {
880        return HRIL_ERR_NULL_POINT;
881    }
882    if (NextInt(&pLine, &outCall->dlMfbr) < 0) {
883        return HRIL_ERR_NULL_POINT;
884    }
885    if (NextInt(&pLine, &outCall->ulMfbr) < 0) {
886        return HRIL_ERR_NULL_POINT;
887    }
888    if (NextInt(&pLine, &outCall->ulSambr) < 0) {
889        return HRIL_ERR_NULL_POINT;
890    }
891    if (NextInt(&pLine, &outCall->dlSambr) < 0) {
892        return HRIL_ERR_NULL_POINT;
893    }
894    if (NextInt(&pLine, &outCall->averagingWindow) < 0) {
895        return HRIL_ERR_NULL_POINT;
896    }
897    return HRIL_ERR_SUCCESS;
898}
899
900void ReqGetLinkBandwidthInfo(const ReqDataInfo *requestInfo, const int32_t cid)
901{
902    int32_t ret;
903    char *line = NULL;
904    int32_t err = HRIL_ERR_SUCCESS;
905    HRilLinkBandwidthInfo uplinkAndDownlinkBandwidth = {0};
906    ResponseInfo *pResponse = NULL;
907    char cmd[MAX_CMD_LENGTH] = {0};
908
909    ModemReportErrorInfo errInfo = InitModemReportErrorInfo();
910    ret = GenerateCommand(cmd, MAX_CMD_LENGTH, "AT+C5GQOSRDP=%d", cid);
911    if (ret < 0) {
912        TELEPHONY_LOGE("GenerateCommand is failed!");
913        OnDataReportErrorMessages(requestInfo, HRIL_ERR_GENERIC_FAILURE, NULL);
914        return;
915    }
916    ret = SendCommandLock(cmd, "+C5GQOSRDP:", 0, &pResponse);
917    if (ret || pResponse == NULL || !pResponse->success) {
918        err = ret ? ret : err;
919        TELEPHONY_LOGE("cmd send failed, err:%{public}d", err);
920        OnDataReportErrorMessages(requestInfo, err, pResponse);
921        return;
922    }
923    if (pResponse->head) {
924        line = pResponse->head->data;
925        ret = CallCmdC5GQOSRDP(line, &uplinkAndDownlinkBandwidth);
926        if (ret != 0) {
927            TELEPHONY_LOGE("Parse C5GQOSRDP data is fail. ret:%{public}d", ret);
928            return;
929        }
930        TELEPHONY_LOGI(
931            "+C5GQOSRDP:%{public}d, %{public}d", uplinkAndDownlinkBandwidth.cid, uplinkAndDownlinkBandwidth.qi);
932    } else {
933        TELEPHONY_LOGE("ERROR: pResponse->head is null");
934        err = HRIL_ERR_GENERIC_FAILURE;
935    }
936    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
937    reportInfo.modemErrInfo = errInfo;
938    OnDataReport(GetSlotId(requestInfo), reportInfo, (const uint8_t *)&uplinkAndDownlinkBandwidth,
939        sizeof(HRilLinkBandwidthInfo));
940    FreeResponseInfo(pResponse);
941}
942
943void ReqSetDataPermitted(const ReqDataInfo *requestInfo, const int32_t dataPermitted)
944{
945    TELEPHONY_LOGI("dataPermitted:%{public}d", dataPermitted);
946    ModemReportErrorInfo errInfo = {};
947    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
948    reportInfo.modemErrInfo = errInfo;
949    OnDataReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
950}
951
952void ReqGetLinkCapability(const ReqDataInfo *requestInfo)
953{
954    ModemReportErrorInfo errInfo = { 0 };
955    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
956    reportInfo.modemErrInfo = errInfo;
957    OnDataReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
958}
959
960void ReqCleanAllConnections(const ReqDataInfo *requestInfo)
961{
962    ModemReportErrorInfo errInfo = { 0 };
963    struct ReportInfo reportInfo = CreateReportInfo(requestInfo, errInfo.errorNo, HRIL_RESPONSE, 0);
964    reportInfo.modemErrInfo = errInfo;
965    OnDataReport(GetSlotId(requestInfo), reportInfo, NULL, 0);
966}
967