1/* 2 * Copyright (C) 2021-2024 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_modem.h" 17#include "vendor_adapter.h" 18#include "vendor_report.h" 19#include "vendor_util.h" 20 21struct ResponseAck { 22 ResponseInfo *responseInfo; 23 uint8_t *respDataPointer; 24 int32_t respDataLen; 25}; 26 27static int32_t ResponseModemReport( 28 int32_t slotId, const ReqDataInfo *requestInfo, int32_t err, struct ResponseAck *respDataAck) 29{ 30 if (requestInfo == NULL) { 31 TELEPHONY_LOGE("requestInfo is nullptr!"); 32 return HRIL_ERR_GENERIC_FAILURE; 33 } 34 if (respDataAck == NULL) { 35 TELEPHONY_LOGE("respDataAck is nullptr!"); 36 return HRIL_ERR_GENERIC_FAILURE; 37 } 38 struct ReportInfo reportInfo; 39 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 40 OnModemReport(slotId, reportInfo, (const uint8_t *)(respDataAck->respDataPointer), respDataAck->respDataLen); 41 if (respDataAck->responseInfo != NULL) { 42 FreeResponseInfo(respDataAck->responseInfo); 43 } 44 return err; 45} 46 47static int32_t GetResponseErrorCode(ResponseInfo *pResponseInfo) 48{ 49 char *pLine = NULL; 50 int32_t ret = HRIL_ERR_GENERIC_FAILURE; 51 if (pResponseInfo && pResponseInfo->result) { 52 pLine = pResponseInfo->result; 53 SkipATPrefix(&pLine); 54 NextInt(&pLine, &ret); 55 } 56 57 if (ret == -1) { 58 ret = HRIL_ERR_INVALID_RESPONSE; 59 } 60 TELEPHONY_LOGD("modem response error code: %{public}d", ret); 61 return ret; 62} 63 64void ReqSetRadioState(const ReqDataInfo *requestInfo, int32_t function, int32_t reset) 65{ 66 if (requestInfo == NULL) { 67 return; 68 } 69 struct ReportInfo reportInfo; 70 int32_t ret = SetRadioState(function, reset); 71 if (ret == HRIL_ERR_SUCCESS) { 72 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_SUCCESS, HRIL_RESPONSE, 0); 73 } else { 74 TELEPHONY_LOGE("ReqSetRadioState failed"); 75 if (ret == HRIL_ERR_REPEAT_STATUS) { 76 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_REPEAT_STATUS, HRIL_RESPONSE, 0); 77 } else { 78 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_GENERIC_FAILURE, HRIL_RESPONSE, 0); 79 } 80 } 81 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0); 82} 83 84static void ErrorHandler(const ReqDataInfo *requestInfo, ResponseInfo *pResponse) 85{ 86 if (requestInfo == NULL) { 87 return; 88 } 89 struct ReportInfo reportInfo; 90 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_GENERIC_FAILURE, HRIL_RESPONSE, 0); 91 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0); 92 FreeResponseInfo(pResponse); 93} 94 95void ReqGetRadioState(const ReqDataInfo *requestInfo) 96{ 97 if (requestInfo == NULL) { 98 return; 99 } 100 const long long timeOut = DEFAULT_TIMEOUT; 101 char *pLine = NULL; 102 int32_t radioState = -1; 103 ResponseInfo *pResponse = NULL; 104 struct ReportInfo reportInfo; 105 106 int32_t ret = SendCommandLock("AT+CFUN?", "+CFUN", timeOut, &pResponse); 107 if (ret != 0 || pResponse == NULL || !pResponse->success) { 108 TELEPHONY_LOGE("AT+CFUN send failed"); 109 return ErrorHandler(requestInfo, pResponse); 110 } 111 if (pResponse->head != NULL) { 112 pLine = pResponse->head->data; 113 } 114 115 ret = SkipATPrefix(&pLine); 116 if (ret != 0) { 117 return ErrorHandler(requestInfo, pResponse); 118 } 119 ret = NextInt(&pLine, &radioState); 120 if (ret != 0) { 121 return ErrorHandler(requestInfo, pResponse); 122 } 123 124 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_SUCCESS, HRIL_RESPONSE, 0); 125 OnModemReport(requestInfo->slotId, reportInfo, (const uint8_t *)&radioState, sizeof(int32_t)); 126 FreeResponseInfo(pResponse); 127 return; 128} 129 130void ReqGetImei(const ReqDataInfo *requestInfo) 131{ 132 if (requestInfo == NULL) { 133 return; 134 } 135 int32_t err = HRIL_ERR_SUCCESS; 136 ResponseInfo *responseInfo = NULL; 137 TELEPHONY_LOGD("enter to [%{public}s]:%{public}d", __func__, __LINE__); 138 int32_t ret = SendCommandLock("AT+CGSN", NULL, DEFAULT_TIMEOUT, &responseInfo); 139 struct ResponseAck respDataAck = { responseInfo, NULL, 0 }; 140 if (responseInfo == NULL) { 141 TELEPHONY_LOGE("responseInfo is null"); 142 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_NULL_POINT, &respDataAck); 143 return; 144 } 145 respDataAck.responseInfo = responseInfo; 146 if (ret != 0 || !responseInfo->success) { 147 err = GetResponseErrorCode(responseInfo); 148 TELEPHONY_LOGE("send AT CMD failed!"); 149 ResponseModemReport(requestInfo->slotId, requestInfo, err, &respDataAck); 150 return; 151 } 152 if (responseInfo->head == NULL) { 153 TELEPHONY_LOGE("no data!"); 154 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck); 155 return; 156 } 157 char *imeiSn = responseInfo->head->data; 158 if ((imeiSn == NULL) || (strlen(imeiSn) == 0)) { 159 TELEPHONY_LOGE("ReqGetImei: ResponseInfo is Invalid!"); 160 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck); 161 return; 162 } 163 respDataAck.respDataPointer = (uint8_t *)imeiSn; 164 respDataAck.respDataLen = strlen(imeiSn); 165 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_SUCCESS, &respDataAck); 166} 167 168void ReqGetImeiSv(const ReqDataInfo *requestInfo) 169{ 170 if (requestInfo == NULL) { 171 return; 172 } 173 ResponseInfo *responseInfo = NULL; 174 struct ReportInfo reportInfo; 175 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_SUCCESS, HRIL_RESPONSE, 0); 176 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0); 177 FreeResponseInfo(responseInfo); 178} 179 180void ReqGetMeid(const ReqDataInfo *requestInfo) 181{ 182 if (requestInfo == NULL) { 183 return; 184 } 185 int32_t err = HRIL_ERR_SUCCESS; 186 ResponseInfo *responseInfo = NULL; 187 TELEPHONY_LOGD("enter to [%{public}s]:%{public}d", __func__, __LINE__); 188 int32_t ret = SendCommandLock("AT+MEID", NULL, DEFAULT_TIMEOUT, &responseInfo); 189 struct ResponseAck respDataAck = { responseInfo, NULL, 0 }; 190 if (responseInfo == NULL) { 191 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_NULL_POINT, &respDataAck); 192 return; 193 } 194 respDataAck.responseInfo = responseInfo; 195 if (ret != 0 || !responseInfo->success) { 196 err = GetResponseErrorCode(responseInfo); 197 TELEPHONY_LOGE("send AT CMD failed!"); 198 ResponseModemReport(requestInfo->slotId, requestInfo, err, &respDataAck); 199 return; 200 } 201 if (responseInfo->head == NULL) { 202 TELEPHONY_LOGE("no data!"); 203 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck); 204 return; 205 } 206 char *meidSn = responseInfo->head->data; 207 if ((meidSn == NULL) || (strlen(meidSn) == 0)) { 208 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck); 209 return; 210 } 211 respDataAck.respDataPointer = (uint8_t *)meidSn; 212 respDataAck.respDataLen = strlen(meidSn); 213 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_SUCCESS, &respDataAck); 214} 215 216static HRilRadioTech ConvertVoiceTechToRadioTech(HRilVoiceSubMode subMode) 217{ 218 switch (subMode) { 219 case HRIL_ACT_GSM: 220 case HRIL_ACT_GPRS: 221 case HRIL_ACT_EDGE: 222 return RADIO_TECHNOLOGY_GSM; 223 case HRIL_ACT_HSPA: 224 case HRIL_ACT_HSDPA: 225 case HRIL_ACT_HSUPA: 226 return RADIO_TECHNOLOGY_HSPA; 227 case HRIL_ACT_HSPAP: 228 case HRIL_ACT_DC_HSPAP: 229 return RADIO_TECHNOLOGY_HSPAP; 230 case HRIL_ACT_WCDMA: 231 return RADIO_TECHNOLOGY_WCDMA; 232 case HRIL_ACT_LTE: 233 return RADIO_TECHNOLOGY_LTE; 234 case HRIL_ACT_IS95A: 235 case HRIL_ACT_IS95B: 236 case HRIL_ACT_CDMA2000_1X: 237 case HRIL_ACT_HYBRID_CDMA2000_1X: 238 return RADIO_TECHNOLOGY_1XRTT; 239 case HRIL_ACT_EVDO_REL0: 240 case HRIL_ACT_EVDO_RELA: 241 case HRIL_ACT_EVDO_RELB: 242 case HRIL_ACT_HYBRID_EVDO_REL0: 243 case HRIL_ACT_HYBRID_EVDO_RELA: 244 case HRIL_ACT_HYBRID_EVDO_RELB: 245 return RADIO_TECHNOLOGY_EVDO; 246 case HRIL_ACT_TDSCDMA: 247 return RADIO_TECHNOLOGY_TD_SCDMA; 248 case HRIL_ACT_LTE_CA: 249 return RADIO_TECHNOLOGY_LTE_CA; 250 case HRIL_ACT_802_16E: 251 return RADIO_TECHNOLOGY_IWLAN; 252 case HRIL_ACT_NR: 253 return RADIO_TECHNOLOGY_NR; 254 default: 255 return RADIO_TECHNOLOGY_UNKNOWN; 256 } 257} 258 259int32_t ProcessVoiceRadioInfo(const char *s, const HRilVoiceRadioInfo *hrilVoiceRadioInfo) 260{ 261 int32_t srvStatus = 0; 262 int32_t srvDomain = 0; 263 int32_t roamStatus = 0; 264 int32_t simStatus = 0; 265 int32_t lockStatus = 0; 266 int32_t sysMode = 0; 267 int32_t actType = 0; 268 char *str = (char *)s; 269 HRilVoiceRadioInfo *voiceRadioInfo = (HRilVoiceRadioInfo *)hrilVoiceRadioInfo; 270 if ((str == NULL) || (voiceRadioInfo == NULL)) { 271 TELEPHONY_LOGE("ProcessVoiceRadioInfo s or voiceRadioInfo param is null"); 272 return HRIL_ERR_NULL_POINT; 273 } else { 274 (void)memset_s(voiceRadioInfo, sizeof(HRilVoiceRadioInfo), 0, sizeof(HRilVoiceRadioInfo)); 275 TELEPHONY_LOGD("result: %{public}s", str); 276 int32_t err = SkipATPrefix(&str); 277 if (err < 0) { 278 TELEPHONY_LOGE("skip failed: [%{public}s]", str); 279 return HRIL_ERR_INVALID_RESPONSE; 280 } 281 int32_t commaNum = FindCommaCharNum(str); 282 const int32_t VOICE_COMMA_NUM = 8; 283 if (commaNum != VOICE_COMMA_NUM) { 284 TELEPHONY_LOGE("ProcessVoiceRadioInfo failed commaNum: [%{public}d]", commaNum); 285 return HRIL_ERR_INVALID_RESPONSE; 286 } 287 NextIntNotSkipNextComma(&str, &srvStatus); 288 voiceRadioInfo->srvStatus = srvStatus; 289 NextIntNotSkipNextComma(&str, &srvDomain); 290 voiceRadioInfo->srvDomain = srvDomain; 291 NextIntNotSkipNextComma(&str, &roamStatus); 292 voiceRadioInfo->roamStatus = roamStatus; 293 NextIntNotSkipNextComma(&str, &simStatus); 294 voiceRadioInfo->simStatus = simStatus; 295 if (NextIntNotSkipNextComma(&str, &lockStatus) < 0) { 296 voiceRadioInfo->lockStatus = 0; 297 } else { 298 voiceRadioInfo->lockStatus = lockStatus; 299 } 300 NextIntNotSkipNextComma(&str, &sysMode); 301 voiceRadioInfo->sysMode = sysMode; 302 NextStr(&str, &(voiceRadioInfo->sysModeName)); 303 NextIntNotSkipNextComma(&str, &actType); 304 voiceRadioInfo->actType = ConvertVoiceTechToRadioTech((HRilVoiceSubMode)actType); 305 NextStr(&str, &(voiceRadioInfo->actName)); 306 return HRIL_ERR_SUCCESS; 307 } 308} 309 310void ReqGetVoiceRadioTechnology(const ReqDataInfo *requestInfo) 311{ 312 if (requestInfo == NULL) { 313 return; 314 } 315 int32_t err = HRIL_ERR_SUCCESS; 316 struct ReportInfo reportInfo; 317 ResponseInfo *responseInfo = NULL; 318 char *result = NULL; 319 int32_t ret = SendCommandLock("AT^SYSINFOEX", "^SYSINFOEX:", DEFAULT_TIMEOUT, &responseInfo); 320 if (responseInfo == NULL) { 321 TELEPHONY_LOGE("responseInfo is nullptr!"); 322 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_NULL_POINT, HRIL_RESPONSE, 0); 323 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0); 324 return; 325 } 326 if (ret != 0 || !responseInfo->success) { 327 err = GetResponseErrorCode(responseInfo); 328 TELEPHONY_LOGE("send AT CMD failed!"); 329 } 330 HRilVoiceRadioInfo voiceRadioInfo = {0}; 331 if (responseInfo->head != NULL) { 332 result = responseInfo->head->data; 333 } 334 ret = ProcessVoiceRadioInfo(result, &voiceRadioInfo); 335 if (ret != 0) { 336 TELEPHONY_LOGE("ProcessVoiceRadioInfo format unexpected: %{public}s", result); 337 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_INVALID_RESPONSE, HRIL_RESPONSE, 0); 338 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0); 339 FreeResponseInfo(responseInfo); 340 return; 341 } 342 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0); 343 OnModemReport(requestInfo->slotId, reportInfo, (const uint8_t *)&voiceRadioInfo, sizeof(HRilVoiceRadioInfo)); 344 FreeResponseInfo(responseInfo); 345} 346