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