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
21 struct ResponseAck {
22 ResponseInfo *responseInfo;
23 uint8_t *respDataPointer;
24 int32_t respDataLen;
25 };
26
ResponseModemReport(int32_t slotId,const ReqDataInfo * requestInfo,int32_t err,struct ResponseAck * respDataAck)27 static 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
GetResponseErrorCode(ResponseInfo * pResponseInfo)47 static 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
ReqSetRadioState(const ReqDataInfo * requestInfo,int32_t function,int32_t reset)64 void 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
ErrorHandler(const ReqDataInfo * requestInfo,ResponseInfo * pResponse)84 static 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
ReqGetRadioState(const ReqDataInfo * requestInfo)95 void 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
ReqGetImei(const ReqDataInfo * requestInfo)130 void 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
ReqGetImeiSv(const ReqDataInfo * requestInfo)168 void 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
ReqGetMeid(const ReqDataInfo * requestInfo)180 void 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
ConvertVoiceTechToRadioTech(HRilVoiceSubMode subMode)216 static 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
ProcessVoiceRadioInfo(const char * s,const HRilVoiceRadioInfo * hrilVoiceRadioInfo)259 int32_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
ReqGetVoiceRadioTechnology(const ReqDataInfo * requestInfo)310 void 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