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