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_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->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
ReqGetMeid(const ReqDataInfo * requestInfo)168 void ReqGetMeid(const ReqDataInfo *requestInfo)
169 {
170 if (requestInfo == NULL) {
171 return;
172 }
173 int32_t err = HRIL_ERR_SUCCESS;
174 ResponseInfo *responseInfo = NULL;
175 TELEPHONY_LOGD("enter to [%{public}s]:%{public}d", __func__, __LINE__);
176 int32_t ret = SendCommandLock("AT+MEID", NULL, DEFAULT_TIMEOUT, &responseInfo);
177 struct ResponseAck respDataAck = { responseInfo, NULL, 0 };
178 if (responseInfo == NULL) {
179 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_NULL_POINT, &respDataAck);
180 return;
181 }
182 respDataAck.responseInfo = responseInfo;
183 if (ret != 0 || !responseInfo->success) {
184 err = GetResponseErrorCode(responseInfo);
185 TELEPHONY_LOGE("send AT CMD failed!");
186 ResponseModemReport(requestInfo->slotId, requestInfo, err, &respDataAck);
187 return;
188 }
189 if (responseInfo->head == NULL) {
190 TELEPHONY_LOGE("no data!");
191 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck);
192 return;
193 }
194 char *meidSn = responseInfo->head->data;
195 if ((meidSn == NULL) || (strlen(meidSn) == 0)) {
196 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_INVALID_RESPONSE, &respDataAck);
197 return;
198 }
199 respDataAck.respDataPointer = (uint8_t *)meidSn;
200 respDataAck.respDataLen = strlen(meidSn);
201 ResponseModemReport(requestInfo->slotId, requestInfo, HRIL_ERR_SUCCESS, &respDataAck);
202 }
203
ConvertVoiceTechToRadioTech(HRilVoiceSubMode subMode)204 static HRilRadioTech ConvertVoiceTechToRadioTech(HRilVoiceSubMode subMode)
205 {
206 switch (subMode) {
207 case HRIL_ACT_GSM:
208 case HRIL_ACT_GPRS:
209 case HRIL_ACT_EDGE:
210 return RADIO_TECHNOLOGY_GSM;
211 case HRIL_ACT_HSPA:
212 case HRIL_ACT_HSDPA:
213 case HRIL_ACT_HSUPA:
214 return RADIO_TECHNOLOGY_HSPA;
215 case HRIL_ACT_HSPAP:
216 case HRIL_ACT_DC_HSPAP:
217 return RADIO_TECHNOLOGY_HSPAP;
218 case HRIL_ACT_WCDMA:
219 return RADIO_TECHNOLOGY_WCDMA;
220 case HRIL_ACT_LTE:
221 return RADIO_TECHNOLOGY_LTE;
222 case HRIL_ACT_IS95A:
223 case HRIL_ACT_IS95B:
224 case HRIL_ACT_CDMA2000_1X:
225 case HRIL_ACT_HYBRID_CDMA2000_1X:
226 return RADIO_TECHNOLOGY_1XRTT;
227 case HRIL_ACT_EVDO_REL0:
228 case HRIL_ACT_EVDO_RELA:
229 case HRIL_ACT_EVDO_RELB:
230 case HRIL_ACT_HYBRID_EVDO_REL0:
231 case HRIL_ACT_HYBRID_EVDO_RELA:
232 case HRIL_ACT_HYBRID_EVDO_RELB:
233 return RADIO_TECHNOLOGY_EVDO;
234 case HRIL_ACT_TDSCDMA:
235 return RADIO_TECHNOLOGY_TD_SCDMA;
236 case HRIL_ACT_LTE_CA:
237 return RADIO_TECHNOLOGY_LTE_CA;
238 case HRIL_ACT_802_16E:
239 return RADIO_TECHNOLOGY_IWLAN;
240 case HRIL_ACT_NR:
241 return RADIO_TECHNOLOGY_NR;
242 default:
243 return RADIO_TECHNOLOGY_UNKNOWN;
244 }
245 }
246
ProcessVoiceRadioInfo(const char * s,const HRilVoiceRadioInfo * hrilVoiceRadioInfo)247 int32_t ProcessVoiceRadioInfo(const char *s, const HRilVoiceRadioInfo *hrilVoiceRadioInfo)
248 {
249 int32_t srvStatus = 0;
250 int32_t srvDomain = 0;
251 int32_t roamStatus = 0;
252 int32_t simStatus = 0;
253 int32_t lockStatus = 0;
254 int32_t sysMode = 0;
255 int32_t actType = 0;
256 char *str = (char *)s;
257 HRilVoiceRadioInfo *voiceRadioInfo = (HRilVoiceRadioInfo *)hrilVoiceRadioInfo;
258 if ((str == NULL) || (voiceRadioInfo == NULL)) {
259 TELEPHONY_LOGE("ProcessVoiceRadioInfo s or voiceRadioInfo param is null");
260 return HRIL_ERR_NULL_POINT;
261 } else {
262 (void)memset_s(voiceRadioInfo, sizeof(HRilVoiceRadioInfo), 0, sizeof(HRilVoiceRadioInfo));
263 TELEPHONY_LOGD("result: %{public}s", str);
264 int32_t err = SkipATPrefix(&str);
265 if (err < 0) {
266 TELEPHONY_LOGE("skip failed: [%{public}s]", str);
267 return HRIL_ERR_INVALID_RESPONSE;
268 }
269 int32_t commaNum = FindCommaCharNum(str);
270 const int32_t VOICE_COMMA_NUM = 8;
271 if (commaNum != VOICE_COMMA_NUM) {
272 TELEPHONY_LOGE("ProcessVoiceRadioInfo failed commaNum: [%{public}d]", commaNum);
273 return HRIL_ERR_INVALID_RESPONSE;
274 }
275 NextIntNotSkipNextComma(&str, &srvStatus);
276 voiceRadioInfo->srvStatus = srvStatus;
277 NextIntNotSkipNextComma(&str, &srvDomain);
278 voiceRadioInfo->srvDomain = srvDomain;
279 NextIntNotSkipNextComma(&str, &roamStatus);
280 voiceRadioInfo->roamStatus = roamStatus;
281 NextIntNotSkipNextComma(&str, &simStatus);
282 voiceRadioInfo->simStatus = simStatus;
283 if (NextIntNotSkipNextComma(&str, &lockStatus) < 0) {
284 voiceRadioInfo->lockStatus = 0;
285 } else {
286 voiceRadioInfo->lockStatus = lockStatus;
287 }
288 NextIntNotSkipNextComma(&str, &sysMode);
289 voiceRadioInfo->sysMode = sysMode;
290 NextStr(&str, &(voiceRadioInfo->sysModeName));
291 NextIntNotSkipNextComma(&str, &actType);
292 voiceRadioInfo->actType = ConvertVoiceTechToRadioTech((HRilVoiceSubMode)actType);
293 NextStr(&str, &(voiceRadioInfo->actName));
294 return HRIL_ERR_SUCCESS;
295 }
296 }
297
ReqGetVoiceRadioTechnology(const ReqDataInfo * requestInfo)298 void ReqGetVoiceRadioTechnology(const ReqDataInfo *requestInfo)
299 {
300 if (requestInfo == NULL) {
301 return;
302 }
303 int32_t err = HRIL_ERR_SUCCESS;
304 struct ReportInfo reportInfo;
305 ResponseInfo *responseInfo = NULL;
306 char *result = NULL;
307 int32_t ret = SendCommandLock("AT^SYSINFOEX", "^SYSINFOEX:", DEFAULT_TIMEOUT, &responseInfo);
308 if (responseInfo == NULL) {
309 TELEPHONY_LOGE("responseInfo is nullptr!");
310 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_NULL_POINT, HRIL_RESPONSE, 0);
311 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0);
312 return;
313 }
314 if (ret != 0 || !responseInfo->success) {
315 err = GetResponseErrorCode(responseInfo);
316 TELEPHONY_LOGE("send AT CMD failed!");
317 }
318 HRilVoiceRadioInfo voiceRadioInfo = {0};
319 if (responseInfo->head != NULL) {
320 result = responseInfo->head->data;
321 }
322 ret = ProcessVoiceRadioInfo(result, &voiceRadioInfo);
323 if (ret != 0) {
324 TELEPHONY_LOGE("ProcessVoiceRadioInfo format unexpected: %{public}s", result);
325 reportInfo = CreateReportInfo(requestInfo, HRIL_ERR_INVALID_RESPONSE, HRIL_RESPONSE, 0);
326 OnModemReport(requestInfo->slotId, reportInfo, NULL, 0);
327 FreeResponseInfo(responseInfo);
328 return;
329 }
330 reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
331 OnModemReport(requestInfo->slotId, reportInfo, (const uint8_t *)&voiceRadioInfo, sizeof(HRilVoiceRadioInfo));
332 FreeResponseInfo(responseInfo);
333 }
334