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