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 "vendor_util.h"
17
18 #include <stdlib.h>
19
20 #include "parameter.h"
21
22 #define NS_PER_S 1000000000
23 #define COUNT 1000
24
25 #define SUPPORT_SLOT_ID "persist.sys.support.slotid"
26 #define DEFAULT_SLOT_COUNT "1"
27 #define TEL_SIM_SLOT_COUNT "const.telephony.slotCount"
28 #define VIRTUAL_MODEM_SWITCH "const.booster.virtual_modem_switch"
29 #define VIRTUAL_MODEM_DEFAULT_SWITCH "false"
30 #define SYSPARA_SIZE 128
31
32 #define G_RESP_ERRORS 7
33 #define G_RESP_SUCCESS 2
34 #define G_RESP_SMS_NOTIFY 3
35 const int32_t G_CHAR_TO_INT = 10;
36 static const int32_t ERR = -1;
37 static const char *g_respErrors[G_RESP_ERRORS] = {
38 "ERROR", "NO ANSWER", "+CME ERROR:", "NO CARRIER", "NO DIALTONE", "+CMS ERROR:", "COMMAND NOT SUPPORT"};
39
40 static const char *g_respSuccess[G_RESP_SUCCESS] = {"OK", "CONNECT"};
41
42 static const char *g_respSmsNotify[G_RESP_SMS_NOTIFY] = {"+CMT:", "+CDS:", "+CBM:"};
43
44 enum CommonNumber {
45 HRIL_DEC = 10,
46 HRIL_HEX = 16,
47 };
48
GenerateCommand(char *buffer, size_t bufferLen, const char *fmt, ...)49 int32_t GenerateCommand(char *buffer, size_t bufferLen, const char *fmt, ...)
50 {
51 int32_t ret;
52 va_list va;
53
54 va_start(va, fmt);
55 ret = vsprintf_s(buffer, bufferLen, fmt, va);
56 va_end(va);
57
58 return ret;
59 }
60
ReportStrWith(const char *s, const char *prefix)61 int32_t ReportStrWith(const char *s, const char *prefix)
62 {
63 const char *source = s;
64 const char *dest = prefix;
65 if (prefix == NULL || s == NULL) {
66 TELEPHONY_LOGE("str or prefix parameter is null.");
67 return 0;
68 }
69 for (; *source != '\0' && *dest != '\0'; source++, dest++) {
70 if (*source != *dest) {
71 return 0;
72 }
73 }
74 return *dest == '\0';
75 }
76
IsResponseSuccess(const char *s)77 int32_t IsResponseSuccess(const char *s)
78 {
79 size_t i;
80 for (i = 0; i < G_RESP_SUCCESS; i++) {
81 if (ReportStrWith(s, g_respSuccess[i])) {
82 return 1;
83 }
84 }
85 return 0;
86 }
87
IsResponseError(const char *s)88 int32_t IsResponseError(const char *s)
89 {
90 size_t i;
91 for (i = 0; i < G_RESP_ERRORS; i++) {
92 if (ReportStrWith(s, g_respErrors[i])) {
93 return 1;
94 }
95 }
96 return 0;
97 }
98
IsSms(const char *s)99 int32_t IsSms(const char *s)
100 {
101 if (s == NULL) {
102 return 0;
103 }
104 if (s[0] == '>') {
105 return 1;
106 }
107 return 0;
108 }
109
IsSmsNotify(const char *s)110 int32_t IsSmsNotify(const char *s)
111 {
112 if (s == NULL) {
113 return 0;
114 }
115 size_t i;
116 for (i = 0; i < G_RESP_SMS_NOTIFY; i++) {
117 if (ReportStrWith(s, g_respSmsNotify[i])) {
118 return 1;
119 }
120 }
121 return 0;
122 }
123
SetWaitTimeout(struct timespec *time, long long msec)124 void SetWaitTimeout(struct timespec *time, long long msec)
125 {
126 if (time == NULL) {
127 return;
128 }
129 struct timeval now;
130 long def = 1000L;
131 gettimeofday(&now, (struct timezone *)NULL);
132 time->tv_nsec = (now.tv_usec + (msec % COUNT) * def) * def;
133 time->tv_sec = now.tv_sec + (msec / COUNT);
134 if (time->tv_nsec >= NS_PER_S) {
135 time->tv_nsec -= NS_PER_S;
136 time->tv_sec++;
137 }
138 }
139
SkipATPrefix(char **s)140 int32_t SkipATPrefix(char **s)
141 {
142 if (s == NULL || *s == NULL) {
143 TELEPHONY_LOGE("str parameter is null.");
144 return ERR;
145 }
146 *s = strchr(*s, ':');
147 if (*s == NULL) {
148 TELEPHONY_LOGE("str parameter is null.");
149 return ERR;
150 }
151 (*s)++;
152 return 0;
153 }
154
SkipSpace(char **s)155 void SkipSpace(char **s)
156 {
157 if (s == NULL || *s == NULL) {
158 TELEPHONY_LOGE("str parameter is null.");
159 return;
160 }
161 while (**s != '\0' && **s == ' ') {
162 (*s)++;
163 }
164 }
165
NextInt(char **s, int32_t *out)166 int32_t NextInt(char **s, int32_t *out)
167 {
168 char *ret = NULL;
169 char *end = NULL;
170 if (s == NULL || *s == NULL || out == NULL) {
171 TELEPHONY_LOGE("str parameter is null.");
172 return ERR;
173 }
174 SkipSpace(s);
175 if (*s == NULL) {
176 TELEPHONY_LOGE("str parameter is null, after skip space.");
177 return ERR;
178 }
179 ret = strsep(s, ",");
180 while (*s != NULL && **s == ',') {
181 (*s)++;
182 }
183 *out = (int32_t)strtol(ret, &end, HRIL_DEC);
184 if (ret == end) {
185 TELEPHONY_LOGE("strtol is fail, err:%{public}d", *out);
186 return ERR;
187 }
188 return 0;
189 }
190
NextInt64(char **s, int64_t *out)191 int64_t NextInt64(char **s, int64_t *out)
192 {
193 char *ret = NULL;
194 char *end = NULL;
195 if (s == NULL || *s == NULL || out == NULL) {
196 TELEPHONY_LOGE("str parameter is null.");
197 return ERR;
198 }
199 SkipSpace(s);
200 if (*s == NULL) {
201 TELEPHONY_LOGE("str parameter is null, after skip space.");
202 return ERR;
203 }
204 ret = strsep(s, ",");
205 while (*s != NULL && **s == ',') {
206 (*s)++;
207 }
208 *out = (int64_t)strtoll(ret, &end, HRIL_DEC);
209 if (ret == end) {
210 TELEPHONY_LOGE("NextInt64 strtoll is fail");
211 return ERR;
212 }
213 return 0;
214 }
215
NextIntNotSkipNextComma(char **s, int32_t *out)216 int32_t NextIntNotSkipNextComma(char **s, int32_t *out)
217 {
218 char *ret = NULL;
219 char *end = NULL;
220 if (s == NULL || *s == NULL || out == NULL) {
221 TELEPHONY_LOGE("str parameter is null.");
222 return ERR;
223 }
224 SkipSpace(s);
225 if (*s == NULL) {
226 TELEPHONY_LOGE("str parameter is null, after skip space.");
227 return ERR;
228 }
229 ret = strsep(s, ",");
230 *out = (int32_t)strtol(ret, &end, HRIL_DEC);
231 if (ret == end) {
232 TELEPHONY_LOGE("strtol is fail, err:%{public}d", *out);
233 return ERR;
234 }
235 return 0;
236 }
237
NextIntByRightBracket(char **s, int32_t *out)238 int32_t NextIntByRightBracket(char **s, int32_t *out)
239 {
240 char *ret = NULL;
241 char *end = NULL;
242 if (s == NULL || *s == NULL || out == NULL) {
243 TELEPHONY_LOGE("str parameter is null.");
244 return ERR;
245 }
246 SkipSpace(s);
247 if (*s == NULL) {
248 TELEPHONY_LOGE("str parameter is null, after skip space.");
249 return ERR;
250 }
251 ret = strsep(s, ")");
252 while (*s != NULL && **s == ')') {
253 (*s)++;
254 }
255 *out = (int32_t)strtol(ret, &end, HRIL_DEC);
256 if (ret == end) {
257 TELEPHONY_LOGE("strtol is fail, err:%{public}d", *out);
258 return ERR;
259 }
260 return 0;
261 }
262
SkipNextComma(char **s)263 void SkipNextComma(char **s)
264 {
265 if (s == NULL || *s == NULL) {
266 TELEPHONY_LOGE("str parameter is null.");
267 return;
268 }
269 while (**s != '\0' && **s != ',') {
270 (*s)++;
271 }
272 if (**s == ',') {
273 (*s)++;
274 }
275 }
276
NextIntFromHex(char **s, int32_t *out)277 int32_t NextIntFromHex(char **s, int32_t *out)
278 {
279 char *ret = NULL;
280 char *end = NULL;
281 if (s == NULL || *s == NULL || out == NULL) {
282 TELEPHONY_LOGE("str parameter is null.");
283 return ERR;
284 }
285 SkipSpace(s);
286 if (*s == NULL) {
287 TELEPHONY_LOGE("str parameter is null, after skip space.");
288 return ERR;
289 } else if (**s == '"') {
290 (*s)++;
291 ret = strsep(s, "\"");
292 SkipNextComma(s);
293 } else {
294 ret = strsep(s, ",");
295 }
296 *out = (int32_t)strtol(ret, &end, HRIL_HEX);
297 if (ret == end) {
298 TELEPHONY_LOGE("strtol is fail, err:%{public}d", *out);
299 return ERR;
300 }
301 return 0;
302 }
303
NextULongFromHex(char **s, uint64_t *out)304 int32_t NextULongFromHex(char **s, uint64_t *out)
305 {
306 char *ret = NULL;
307 char *end = NULL;
308 if (s == NULL || *s == NULL || out == NULL) {
309 TELEPHONY_LOGE("str parameter is null.");
310 return ERR;
311 }
312 SkipSpace(s);
313 if (*s == NULL) {
314 TELEPHONY_LOGE("str parameter is null, after skip space.");
315 return ERR;
316 } else if (**s == '"') {
317 (*s)++;
318 ret = strsep(s, "\"");
319 SkipNextComma(s);
320 } else {
321 ret = strsep(s, ",");
322 }
323 *out = (uint64_t)strtoul(ret, &end, HRIL_HEX);
324 if (ret == end) {
325 TELEPHONY_LOGE("strtoul is fail");
326 return ERR;
327 }
328 return 0;
329 }
330
NextStr(char **s, char **out)331 int32_t NextStr(char **s, char **out)
332 {
333 if (s == NULL || *s == NULL || out == NULL) {
334 TELEPHONY_LOGE("str parameter is null.");
335 return ERR;
336 }
337 SkipSpace(s);
338 if (*s == NULL) {
339 TELEPHONY_LOGE("str parameter is null, after skip space.");
340 return ERR;
341 } else if (**s == '"') {
342 (*s)++;
343 *out = strsep(s, "\"");
344 SkipNextComma(s);
345 } else {
346 *out = strsep(s, ",");
347 }
348 return 0;
349 }
350
351 /* +CRING: GPRS "IP","00.00.00.00",,"abc.com"
352 * get GPRS
353 */
NextTxtStr(char **s, char **out)354 int32_t NextTxtStr(char **s, char **out)
355 {
356 if (s == NULL || *s == NULL || out == NULL) {
357 TELEPHONY_LOGE("str parameter is null.");
358 return ERR;
359 }
360 SkipSpace(s);
361 if (*s == NULL) {
362 TELEPHONY_LOGE("str parameter is null, after skip space.");
363 return ERR;
364 } else {
365 *out = strsep(s, " ");
366 }
367 return 0;
368 }
369
NextBool(char **s, char *out)370 int32_t NextBool(char **s, char *out)
371 {
372 int32_t ret;
373 int32_t value;
374
375 if (*s == NULL) {
376 TELEPHONY_LOGE("str parameter is null.");
377 return ERR;
378 }
379 ret = NextInt(s, &value);
380 if (ret < 0) {
381 TELEPHONY_LOGE("NextInt is fail, ret:%{public}d", ret);
382 return ERR;
383 }
384 if (!(value == 0 || value == 1)) {
385 TELEPHONY_LOGE("Bool should be 0 or 1, value:%{public}d", value);
386 return ERR;
387 }
388 if (out != NULL) {
389 *out = (char)value;
390 }
391 return ret;
392 }
393
ParseReportError(char *str)394 int32_t ParseReportError(char *str)
395 {
396 int32_t ret = VENDOR_FAIL;
397 char *pStr = str;
398
399 if (pStr == NULL) {
400 TELEPHONY_LOGE("str parameter is null.");
401 return ret;
402 }
403 if (!SkipATPrefix(&pStr)) {
404 NextInt(&pStr, &ret);
405 }
406 return ret;
407 }
408
GetReportErrorInfo(const ResponseInfo *response)409 ModemReportErrorInfo GetReportErrorInfo(const ResponseInfo *response)
410 {
411 int32_t ret = VENDOR_FAIL;
412 ModemReportErrorInfo errInfo;
413
414 errInfo.errType = HRIL_REPORT_ERR_TYPE_GENERIC;
415 errInfo.errorNo = HRIL_ERR_GENERIC_FAILURE;
416 if ((response != NULL) && (!response->success)) {
417 char *pStr = response->result;
418 if (ReportStrWith(pStr, "+CME ERROR:")) {
419 errInfo.errType = HRIL_REPORT_ERR_TYPE_CME;
420 } else if (ReportStrWith(pStr, "+CMS ERROR:")) {
421 errInfo.errType = HRIL_REPORT_ERR_TYPE_CMS;
422 } else {
423 return errInfo;
424 }
425 ret = ParseReportError(pStr);
426 if (ret > 0) {
427 errInfo.errorNo = ret;
428 }
429 }
430 return errInfo;
431 }
432
InitModemReportErrorInfo(void)433 ModemReportErrorInfo InitModemReportErrorInfo(void)
434 {
435 ModemReportErrorInfo errInfo;
436
437 errInfo.errorNo = HRIL_ERR_SUCCESS;
438 errInfo.errType = HRIL_REPORT_ERR_TYPE_NONE;
439 return errInfo;
440 }
441
ConvertCharToInt32(const char *s)442 int32_t ConvertCharToInt32(const char *s)
443 {
444 if (s == NULL) {
445 return 0;
446 }
447 char *str = (char *)s;
448 int32_t ret = 0;
449 char firstChar = *str;
450 if ((firstChar == '+') || (firstChar == '-')) {
451 ++str;
452 }
453 while (*str == '0') {
454 ++str;
455 }
456 while (*str) {
457 char tmp = *str;
458 if ((*str < '0') || (*str > '9')) {
459 return ret;
460 } else {
461 int32_t val = (int32_t)(tmp - '0');
462 ret = (ret * G_CHAR_TO_INT) + val;
463 }
464 str++;
465 }
466 if (firstChar == '-') {
467 ret = -ret;
468 }
469 return ret;
470 }
471
FindCommaCharNum(const char *srcStr)472 int32_t FindCommaCharNum(const char *srcStr)
473 {
474 char *str = (char *)srcStr;
475 if (str == NULL) {
476 TELEPHONY_LOGE("srcStr parameter is null.");
477 return ERR;
478 }
479 if (*str == '\0') {
480 return ERR;
481 }
482 int32_t charNum = 0;
483 while (*str != '\0') {
484 if (*str == ',') {
485 charNum++;
486 }
487 str++;
488 }
489 return charNum;
490 }
491
GetSimSlotCount(void)492 int32_t GetSimSlotCount(void)
493 {
494 char simSlotCount[PARAMETER_SIZE] = {0};
495 GetParameter(TEL_SIM_SLOT_COUNT, DEFAULT_SLOT_COUNT, simSlotCount, PARAMETER_SIZE);
496 int32_t simSlotCountNumber = atoi(simSlotCount);
497 char virtualModemSwitch[SYSPARA_SIZE] = {0};
498 GetParameter(VIRTUAL_MODEM_SWITCH, VIRTUAL_MODEM_DEFAULT_SWITCH, virtualModemSwitch, SYSPARA_SIZE);
499 if (strcmp(virtualModemSwitch, "true") == 0 && simSlotCountNumber == 0) {
500 TELEPHONY_LOGI("virtualModemSwitch on. set simSlotCountNumber 1");
501 simSlotCountNumber = 1;
502 }
503 return simSlotCountNumber;
504 }
505
GetSlotId(const ReqDataInfo *requestInfo)506 int32_t GetSlotId(const ReqDataInfo *requestInfo)
507 {
508 int32_t slotId = HRIL_SIM_SLOT_0;
509 char strSlotId[PARAMETER_SIZE] = {0};
510
511 if (requestInfo != NULL) {
512 slotId = requestInfo->slotId;
513 } else { // proactive notification
514 if (GetParameter(SUPPORT_SLOT_ID, "", strSlotId, PARAMETER_SIZE) > 0) {
515 slotId = atoi(strSlotId);
516 }
517 }
518 if (slotId >= GetSimSlotCount()) {
519 slotId = HRIL_SIM_SLOT_0;
520 TELEPHONY_LOGE("slotId is invalid, slotId0 will be used. slotId:%{public}d", slotId);
521 }
522 return slotId;
523 }
524