11bd4fe43Sopenharmony_ci/*
21bd4fe43Sopenharmony_ci * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License.
51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at
61bd4fe43Sopenharmony_ci *
71bd4fe43Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81bd4fe43Sopenharmony_ci *
91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and
131bd4fe43Sopenharmony_ci * limitations under the License.
141bd4fe43Sopenharmony_ci */
151bd4fe43Sopenharmony_ci
161bd4fe43Sopenharmony_ci#include <hi_stdlib.h>
171bd4fe43Sopenharmony_ci#include <at.h>
181bd4fe43Sopenharmony_ci#include <at_cmd.h>
191bd4fe43Sopenharmony_ci#include <at_parse.h>
201bd4fe43Sopenharmony_ci#include "hi_config.h"
211bd4fe43Sopenharmony_ci
221bd4fe43Sopenharmony_ci#include "stdio.h"
231bd4fe43Sopenharmony_ci#include "string.h"
241bd4fe43Sopenharmony_ci#include "malloc.h"
251bd4fe43Sopenharmony_ci#include "stdarg.h"
261bd4fe43Sopenharmony_ci#include "securec.h"
271bd4fe43Sopenharmony_ci
281bd4fe43Sopenharmony_ci#ifdef __cplusplus
291bd4fe43Sopenharmony_ci#if __cplusplus
301bd4fe43Sopenharmony_ciextern "C" {
311bd4fe43Sopenharmony_ci#endif
321bd4fe43Sopenharmony_ci#endif
331bd4fe43Sopenharmony_ci
341bd4fe43Sopenharmony_ci#define AT_SSID_MAX_LEN 32
351bd4fe43Sopenharmony_ci
361bd4fe43Sopenharmony_ciat_cmd_ctrl g_at_ctrl = {
371bd4fe43Sopenharmony_ci    .at_state = AT_IDLE,
381bd4fe43Sopenharmony_ci    .send_len = 0,
391bd4fe43Sopenharmony_ci    .trans_len = 0,
401bd4fe43Sopenharmony_ci    .is_first_recv_data = HI_TRUE,
411bd4fe43Sopenharmony_ci    .is_first_over_data = HI_TRUE,
421bd4fe43Sopenharmony_ci    .is_recv_end_char_flag = 0,
431bd4fe43Sopenharmony_ci};
441bd4fe43Sopenharmony_ci
451bd4fe43Sopenharmony_cihi_u32 at_cmd_excute(const at_cmd_func *cmd_func, at_cmd_attr *cmd_parsed)
461bd4fe43Sopenharmony_ci{
471bd4fe43Sopenharmony_ci    hi_u32 ret;
481bd4fe43Sopenharmony_ci
491bd4fe43Sopenharmony_ci    if (cmd_func == HI_NULL || cmd_parsed == HI_NULL) {
501bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
511bd4fe43Sopenharmony_ci    }
521bd4fe43Sopenharmony_ci
531bd4fe43Sopenharmony_ci    if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_TEST) {
541bd4fe43Sopenharmony_ci        if (cmd_func->at_test_cmd) {
551bd4fe43Sopenharmony_ci            ret = cmd_func->at_test_cmd((hi_s32)cmd_parsed->at_param_cnt,
561bd4fe43Sopenharmony_ci                (const hi_char **)&cmd_parsed->param_array[0]);
571bd4fe43Sopenharmony_ci        } else {
581bd4fe43Sopenharmony_ci            at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
591bd4fe43Sopenharmony_ci            ret = HI_ERR_FAILURE;
601bd4fe43Sopenharmony_ci            at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
611bd4fe43Sopenharmony_ci        }
621bd4fe43Sopenharmony_ci    } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_QUERY) {
631bd4fe43Sopenharmony_ci        if (cmd_func->at_query_cmd) {
641bd4fe43Sopenharmony_ci            ret = cmd_func->at_query_cmd((hi_s32)cmd_parsed->at_param_cnt,
651bd4fe43Sopenharmony_ci                (const hi_char **)&cmd_parsed->param_array[0]);
661bd4fe43Sopenharmony_ci        } else {
671bd4fe43Sopenharmony_ci            at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
681bd4fe43Sopenharmony_ci            ret = HI_ERR_FAILURE;
691bd4fe43Sopenharmony_ci            at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
701bd4fe43Sopenharmony_ci        }
711bd4fe43Sopenharmony_ci    } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_SETUP) {
721bd4fe43Sopenharmony_ci        if (cmd_func->at_setup_cmd) {
731bd4fe43Sopenharmony_ci            ret = cmd_func->at_setup_cmd((hi_s32)cmd_parsed->at_param_cnt,
741bd4fe43Sopenharmony_ci                (const hi_char **)&cmd_parsed->param_array[0]);
751bd4fe43Sopenharmony_ci        } else {
761bd4fe43Sopenharmony_ci            at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
771bd4fe43Sopenharmony_ci            ret = HI_ERR_FAILURE;
781bd4fe43Sopenharmony_ci            at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
791bd4fe43Sopenharmony_ci        }
801bd4fe43Sopenharmony_ci    } else if (cmd_parsed->at_cmd_type == AT_CMD_TYPE_EXE) {
811bd4fe43Sopenharmony_ci        if (cmd_func->at_exe_cmd) {
821bd4fe43Sopenharmony_ci            ret = cmd_func->at_exe_cmd((hi_s32)cmd_parsed->at_param_cnt,
831bd4fe43Sopenharmony_ci                (const hi_char **)&cmd_parsed->param_array[0]);
841bd4fe43Sopenharmony_ci        } else {
851bd4fe43Sopenharmony_ci            at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
861bd4fe43Sopenharmony_ci            ret = HI_ERR_FAILURE;
871bd4fe43Sopenharmony_ci            at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
881bd4fe43Sopenharmony_ci        }
891bd4fe43Sopenharmony_ci    } else {
901bd4fe43Sopenharmony_ci        at_printf("COMMAND TYPE NOT SUPPORT!\r\n");
911bd4fe43Sopenharmony_ci        ret = HI_ERR_FAILURE;
921bd4fe43Sopenharmony_ci        at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
931bd4fe43Sopenharmony_ci    }
941bd4fe43Sopenharmony_ci
951bd4fe43Sopenharmony_ci    return ret;
961bd4fe43Sopenharmony_ci}
971bd4fe43Sopenharmony_ci
981bd4fe43Sopenharmony_cistatic hi_void at_get_cmd_name(hi_char *cmd_line, at_cmd_attr *cmd_parsed)
991bd4fe43Sopenharmony_ci{
1001bd4fe43Sopenharmony_ci    hi_s8 n = 0;
1011bd4fe43Sopenharmony_ci
1021bd4fe43Sopenharmony_ci    for (hi_u8 i = AT_CMD_MAX_LEN; i > 0; i--) {
1031bd4fe43Sopenharmony_ci        if ((*cmd_line == '\0') || (*cmd_line == '=') || (*cmd_line == '?')) {
1041bd4fe43Sopenharmony_ci            cmd_parsed->at_cmd_len = n;
1051bd4fe43Sopenharmony_ci            return;
1061bd4fe43Sopenharmony_ci        } else {
1071bd4fe43Sopenharmony_ci            cmd_parsed->cmd_name[n] = *cmd_line;
1081bd4fe43Sopenharmony_ci            cmd_line++;
1091bd4fe43Sopenharmony_ci            n++;
1101bd4fe43Sopenharmony_ci        }
1111bd4fe43Sopenharmony_ci    }
1121bd4fe43Sopenharmony_ci
1131bd4fe43Sopenharmony_ci    cmd_parsed->at_cmd_len = -1;
1141bd4fe43Sopenharmony_ci    memset_s(cmd_parsed->cmd_name, AT_CMD_MAX_LEN, 0, AT_CMD_MAX_LEN);
1151bd4fe43Sopenharmony_ci}
1161bd4fe43Sopenharmony_ci
1171bd4fe43Sopenharmony_cihi_u32 at_func_process(hi_char *out_cmd_line, at_cmd_attr *cmd_parsed)
1181bd4fe43Sopenharmony_ci{
1191bd4fe43Sopenharmony_ci    hi_u32 ret;
1201bd4fe43Sopenharmony_ci    at_cmd_func *cmd_func = HI_NULL;
1211bd4fe43Sopenharmony_ci    at_get_cmd_name(out_cmd_line, cmd_parsed);
1221bd4fe43Sopenharmony_ci    if (cmd_parsed->at_cmd_len != (-1)) {
1231bd4fe43Sopenharmony_ci        cmd_func = at_find_proc_func(cmd_parsed);
1241bd4fe43Sopenharmony_ci    }
1251bd4fe43Sopenharmony_ci
1261bd4fe43Sopenharmony_ci    if (cmd_func != HI_NULL) {
1271bd4fe43Sopenharmony_ci        ret = at_cmd_parse(out_cmd_line, cmd_parsed);
1281bd4fe43Sopenharmony_ci        if (ret != HI_ERR_SUCCESS) {
1291bd4fe43Sopenharmony_ci            at_printf("%s line: %d PARSE CMD FAIL!\r\n", __FUNCTION__, __LINE__);
1301bd4fe43Sopenharmony_ci            return ret;
1311bd4fe43Sopenharmony_ci        }
1321bd4fe43Sopenharmony_ci
1331bd4fe43Sopenharmony_ci        ret = at_cmd_excute(cmd_func, cmd_parsed);
1341bd4fe43Sopenharmony_ci    } else {
1351bd4fe43Sopenharmony_ci        ret = HI_ERR_FAILURE;
1361bd4fe43Sopenharmony_ci        at_printf("%s line: %d COMMAND NOT SUPPORT!\r\n", __FUNCTION__, __LINE__);
1371bd4fe43Sopenharmony_ci    }
1381bd4fe43Sopenharmony_ci
1391bd4fe43Sopenharmony_ci    return ret;
1401bd4fe43Sopenharmony_ci}
1411bd4fe43Sopenharmony_ci
1421bd4fe43Sopenharmony_cihi_u32 at_cmd_process(const hi_char *at_cmd_line)
1431bd4fe43Sopenharmony_ci{
1441bd4fe43Sopenharmony_ci    hi_u32 at_cmd_line_len;
1451bd4fe43Sopenharmony_ci    hi_char *out_cmd_line = HI_NULL;
1461bd4fe43Sopenharmony_ci    at_cmd_attr cmd_parsed = {0};
1471bd4fe43Sopenharmony_ci    hi_u32 ret;
1481bd4fe43Sopenharmony_ci
1491bd4fe43Sopenharmony_ci    AT_ENTER;
1501bd4fe43Sopenharmony_ci    if (at_cmd_line == HI_NULL) {
1511bd4fe43Sopenharmony_ci        at_printf("INVALID NULL CMD!\r\n");
1521bd4fe43Sopenharmony_ci        AT_RESPONSE_ERROR;
1531bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
1541bd4fe43Sopenharmony_ci    }
1551bd4fe43Sopenharmony_ci
1561bd4fe43Sopenharmony_ci    at_cmd_line_len = (hi_u32)strlen(at_cmd_line) + 1;
1571bd4fe43Sopenharmony_ci    out_cmd_line = (hi_char *)hi_malloc(HI_MOD_ID_SAL_DFX, at_cmd_line_len);
1581bd4fe43Sopenharmony_ci    if (out_cmd_line == HI_NULL) {
1591bd4fe43Sopenharmony_ci        at_printf("%s line%d NO ENOUGH MEMORY!\r\n", __FUNCTION__, __LINE__);
1601bd4fe43Sopenharmony_ci        AT_RESPONSE_ERROR;
1611bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
1621bd4fe43Sopenharmony_ci    }
1631bd4fe43Sopenharmony_ci    memset_s(out_cmd_line, at_cmd_line_len, 0, at_cmd_line_len);
1641bd4fe43Sopenharmony_ci
1651bd4fe43Sopenharmony_ci    ret = (hi_u32)strncpy_s(out_cmd_line, at_cmd_line_len, at_cmd_line, at_cmd_line_len - 1);
1661bd4fe43Sopenharmony_ci    if (ret != EOK) {
1671bd4fe43Sopenharmony_ci        at_printf("%s,%d strncpy_s failed, err:%d!\n", __FUNCTION__, __LINE__, ret);
1681bd4fe43Sopenharmony_ci        AT_RESPONSE_ERROR;
1691bd4fe43Sopenharmony_ci        hi_free(HI_MOD_ID_SAL_DFX, out_cmd_line);
1701bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
1711bd4fe43Sopenharmony_ci    }
1721bd4fe43Sopenharmony_ci    out_cmd_line[at_cmd_line_len - 1] = '\0';
1731bd4fe43Sopenharmony_ci
1741bd4fe43Sopenharmony_ci    ret = at_func_process(out_cmd_line, &cmd_parsed);
1751bd4fe43Sopenharmony_ci    if (ret != HI_ERR_SUCCESS && ret != HI_ERR_RECVING) {
1761bd4fe43Sopenharmony_ci        at_printf("err at %s line: %d\n", __FUNCTION__, __LINE__);
1771bd4fe43Sopenharmony_ci        AT_RESPONSE_ERROR;
1781bd4fe43Sopenharmony_ci    } else if (ret == HI_ERR_RECVING) {
1791bd4fe43Sopenharmony_ci        g_at_ctrl.at_state = AT_DATA_RECVING;
1801bd4fe43Sopenharmony_ci    } else {
1811bd4fe43Sopenharmony_ci        g_at_ctrl.at_state = AT_IDLE;
1821bd4fe43Sopenharmony_ci    }
1831bd4fe43Sopenharmony_ci
1841bd4fe43Sopenharmony_ci    hi_free(HI_MOD_ID_SAL_DFX, out_cmd_line);
1851bd4fe43Sopenharmony_ci    out_cmd_line = HI_NULL;
1861bd4fe43Sopenharmony_ci
1871bd4fe43Sopenharmony_ci    return ret;
1881bd4fe43Sopenharmony_ci}
1891bd4fe43Sopenharmony_ci
1901bd4fe43Sopenharmony_cihi_u32 at_param_null_check(hi_s32 argc, const hi_char **argv)
1911bd4fe43Sopenharmony_ci{
1921bd4fe43Sopenharmony_ci    for (hi_s32 i = 0; i < argc; i++) {
1931bd4fe43Sopenharmony_ci        if (argv[i] == HI_NULL) {
1941bd4fe43Sopenharmony_ci            return HI_ERR_FAILURE;
1951bd4fe43Sopenharmony_ci        }
1961bd4fe43Sopenharmony_ci    }
1971bd4fe43Sopenharmony_ci    return HI_ERR_SUCCESS;
1981bd4fe43Sopenharmony_ci}
1991bd4fe43Sopenharmony_ci
2001bd4fe43Sopenharmony_cihi_u32 integer_check(const hi_char *val)
2011bd4fe43Sopenharmony_ci{
2021bd4fe43Sopenharmony_ci    hi_u32 len;
2031bd4fe43Sopenharmony_ci    hi_u32 i;
2041bd4fe43Sopenharmony_ci    hi_char *buf = (hi_char *)val;
2051bd4fe43Sopenharmony_ci    if (buf == HI_NULL) {
2061bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
2071bd4fe43Sopenharmony_ci    }
2081bd4fe43Sopenharmony_ci    len = strlen(buf);
2091bd4fe43Sopenharmony_ci    if ((*buf == '0') && (len != 1)) {
2101bd4fe43Sopenharmony_ci        return HI_ERR_FAILURE;
2111bd4fe43Sopenharmony_ci    }
2121bd4fe43Sopenharmony_ci    for (i = 0; i < len; i++) {
2131bd4fe43Sopenharmony_ci        if ((*buf < '0') || (*buf > '9')) {
2141bd4fe43Sopenharmony_ci            return HI_ERR_FAILURE;
2151bd4fe43Sopenharmony_ci        }
2161bd4fe43Sopenharmony_ci        buf++;
2171bd4fe43Sopenharmony_ci    }
2181bd4fe43Sopenharmony_ci    return HI_ERR_SUCCESS;
2191bd4fe43Sopenharmony_ci}
2201bd4fe43Sopenharmony_ci
2211bd4fe43Sopenharmony_cistatic hi_u32 at_check_mac_elem(const hi_char elem)
2221bd4fe43Sopenharmony_ci{
2231bd4fe43Sopenharmony_ci    if (elem >= '0' && elem <= '9') {
2241bd4fe43Sopenharmony_ci        return HI_ERR_SUCCESS;
2251bd4fe43Sopenharmony_ci    } else if (elem >= 'A' && elem <= 'F') {
2261bd4fe43Sopenharmony_ci        return HI_ERR_SUCCESS;
2271bd4fe43Sopenharmony_ci    } else if (elem >= 'a' && elem <= 'f') {
2281bd4fe43Sopenharmony_ci        return HI_ERR_SUCCESS;
2291bd4fe43Sopenharmony_ci    } else if (elem == ':') {
2301bd4fe43Sopenharmony_ci        return HI_ERR_SUCCESS;
2311bd4fe43Sopenharmony_ci    }
2321bd4fe43Sopenharmony_ci
2331bd4fe43Sopenharmony_ci    return HI_ERR_FAILURE;
2341bd4fe43Sopenharmony_ci}
2351bd4fe43Sopenharmony_ci
2361bd4fe43Sopenharmony_cihi_u32 cmd_strtoaddr(const hi_char *param, hi_uchar *mac_addr, hi_u32 addr_len)
2371bd4fe43Sopenharmony_ci{
2381bd4fe43Sopenharmony_ci    hi_u32 cnt;
2391bd4fe43Sopenharmony_ci    hi_char *tmp1 = (hi_char *)param;
2401bd4fe43Sopenharmony_ci    hi_char *tmp2 = NULL;
2411bd4fe43Sopenharmony_ci    hi_char *tmp3 = NULL;
2421bd4fe43Sopenharmony_ci
2431bd4fe43Sopenharmony_ci    for (cnt = 0; cnt < 17; cnt++) {    /* 17 */
2441bd4fe43Sopenharmony_ci        if (at_check_mac_elem(param[cnt]) != HI_ERR_SUCCESS) {
2451bd4fe43Sopenharmony_ci            return HI_ERR_FAILURE;
2461bd4fe43Sopenharmony_ci        }
2471bd4fe43Sopenharmony_ci    }
2481bd4fe43Sopenharmony_ci
2491bd4fe43Sopenharmony_ci    for (cnt = 0; cnt < (addr_len - 1); cnt++) {
2501bd4fe43Sopenharmony_ci        tmp2 = (char*)strsep(&tmp1, ":");
2511bd4fe43Sopenharmony_ci        if (tmp2 == NULL) {
2521bd4fe43Sopenharmony_ci            return HI_ERR_APP_INVALID_PARAMETER;
2531bd4fe43Sopenharmony_ci        }
2541bd4fe43Sopenharmony_ci        mac_addr[cnt] = (hi_uchar)strtoul(tmp2, &tmp3, 16); /* 16 */
2551bd4fe43Sopenharmony_ci    }
2561bd4fe43Sopenharmony_ci
2571bd4fe43Sopenharmony_ci    if (tmp1 == NULL) {
2581bd4fe43Sopenharmony_ci        return HI_ERR_APP_INVALID_PARAMETER;
2591bd4fe43Sopenharmony_ci    }
2601bd4fe43Sopenharmony_ci    mac_addr[cnt] = (hi_uchar)strtoul(tmp1, &tmp3, 16); /* 16 */
2611bd4fe43Sopenharmony_ci    return HI_ERR_SUCCESS;
2621bd4fe43Sopenharmony_ci}
2631bd4fe43Sopenharmony_ci
2641bd4fe43Sopenharmony_cichar *at_strrchr(const char *src, int c)
2651bd4fe43Sopenharmony_ci{
2661bd4fe43Sopenharmony_ci    return strrchr(src, c);
2671bd4fe43Sopenharmony_ci}
2681bd4fe43Sopenharmony_ci
2691bd4fe43Sopenharmony_civoid *at_malloc(size_t size)
2701bd4fe43Sopenharmony_ci{
2711bd4fe43Sopenharmony_ci    if (size > 4096) {  /* max alloc mem 4096 */
2721bd4fe43Sopenharmony_ci        return NULL;
2731bd4fe43Sopenharmony_ci    }
2741bd4fe43Sopenharmony_ci    void *ptr = malloc(size);
2751bd4fe43Sopenharmony_ci    return ptr;
2761bd4fe43Sopenharmony_ci}
2771bd4fe43Sopenharmony_ci
2781bd4fe43Sopenharmony_civoid at_free(char *ptr)
2791bd4fe43Sopenharmony_ci{
2801bd4fe43Sopenharmony_ci    if (ptr) {
2811bd4fe43Sopenharmony_ci        free(ptr);
2821bd4fe43Sopenharmony_ci    }
2831bd4fe43Sopenharmony_ci}
2841bd4fe43Sopenharmony_ci
2851bd4fe43Sopenharmony_cisize_t at_strlen(const char *src)
2861bd4fe43Sopenharmony_ci{
2871bd4fe43Sopenharmony_ci    return strlen(src);
2881bd4fe43Sopenharmony_ci}
2891bd4fe43Sopenharmony_ci
2901bd4fe43Sopenharmony_ciint at_pading(char *str, size_t size, const char *format, ...)
2911bd4fe43Sopenharmony_ci{
2921bd4fe43Sopenharmony_ci    va_list ap = NULL;
2931bd4fe43Sopenharmony_ci    int ret;
2941bd4fe43Sopenharmony_ci
2951bd4fe43Sopenharmony_ci    va_start(ap, format);
2961bd4fe43Sopenharmony_ci    ret = vsnprintf_s(str, AT_SSID_MAX_LEN * 4 + 1, size, format, ap); /* 4 length */
2971bd4fe43Sopenharmony_ci    va_end(ap);
2981bd4fe43Sopenharmony_ci    if (size > 0) {
2991bd4fe43Sopenharmony_ci        str[size - 1] = '\0';
3001bd4fe43Sopenharmony_ci    }
3011bd4fe43Sopenharmony_ci    return ret;
3021bd4fe43Sopenharmony_ci}
3031bd4fe43Sopenharmony_ci
3041bd4fe43Sopenharmony_cichar* at_dup_binstr(const char *src, size_t len)
3051bd4fe43Sopenharmony_ci{
3061bd4fe43Sopenharmony_ci    char *res = NULL;
3071bd4fe43Sopenharmony_ci    int ret;
3081bd4fe43Sopenharmony_ci
3091bd4fe43Sopenharmony_ci    if (src == NULL) {
3101bd4fe43Sopenharmony_ci        return NULL;
3111bd4fe43Sopenharmony_ci    }
3121bd4fe43Sopenharmony_ci    res = at_malloc(len + 1);
3131bd4fe43Sopenharmony_ci    if (res == NULL) {
3141bd4fe43Sopenharmony_ci        return NULL;
3151bd4fe43Sopenharmony_ci    }
3161bd4fe43Sopenharmony_ci    ret = memcpy_s(res, len, src, len);
3171bd4fe43Sopenharmony_ci    if (ret != EOK) {
3181bd4fe43Sopenharmony_ci        at_free(res);
3191bd4fe43Sopenharmony_ci        res = NULL;
3201bd4fe43Sopenharmony_ci        return NULL;
3211bd4fe43Sopenharmony_ci    }
3221bd4fe43Sopenharmony_ci    res[len] = '\0';
3231bd4fe43Sopenharmony_ci
3241bd4fe43Sopenharmony_ci    return res;
3251bd4fe43Sopenharmony_ci}
3261bd4fe43Sopenharmony_ci
3271bd4fe43Sopenharmony_cistatic int at_hex2num(char c)
3281bd4fe43Sopenharmony_ci{
3291bd4fe43Sopenharmony_ci    if (c >= '0' && c <= '9') {
3301bd4fe43Sopenharmony_ci        return c - '0';
3311bd4fe43Sopenharmony_ci    }
3321bd4fe43Sopenharmony_ci    if (c >= 'a' && c <= 'f') {
3331bd4fe43Sopenharmony_ci        return c - 'a' + 10;    /* add 10 */
3341bd4fe43Sopenharmony_ci    }
3351bd4fe43Sopenharmony_ci    if (c >= 'A' && c <= 'F') {
3361bd4fe43Sopenharmony_ci        return c - 'A' + 10;    /* add 10 */
3371bd4fe43Sopenharmony_ci    }
3381bd4fe43Sopenharmony_ci    return -1;
3391bd4fe43Sopenharmony_ci}
3401bd4fe43Sopenharmony_ci
3411bd4fe43Sopenharmony_ciint at_hex2byte(const char *hex)
3421bd4fe43Sopenharmony_ci{
3431bd4fe43Sopenharmony_ci    int a, b;
3441bd4fe43Sopenharmony_ci    a = at_hex2num(*hex++);
3451bd4fe43Sopenharmony_ci    if (a < 0) {
3461bd4fe43Sopenharmony_ci        return -1;
3471bd4fe43Sopenharmony_ci    }
3481bd4fe43Sopenharmony_ci    b = at_hex2num(*hex++);
3491bd4fe43Sopenharmony_ci    if (b < 0) {
3501bd4fe43Sopenharmony_ci        return -1;
3511bd4fe43Sopenharmony_ci    }
3521bd4fe43Sopenharmony_ci    return ((hi_u32)a << 4) | (hi_u32)b;    /* 4 */
3531bd4fe43Sopenharmony_ci}
3541bd4fe43Sopenharmony_ci
3551bd4fe43Sopenharmony_ci/**
3561bd4fe43Sopenharmony_ci * at_hexstr2bin - Convert ASCII hex string into binary data
3571bd4fe43Sopenharmony_ci * @hex: ASCII hex string (e.g., "01ab")
3581bd4fe43Sopenharmony_ci * @buf: Buffer for the binary data
3591bd4fe43Sopenharmony_ci * @len: Length of the text to convert in bytes (of buf); hex will be double
3601bd4fe43Sopenharmony_ci * this size
3611bd4fe43Sopenharmony_ci * Returns: 0 on success, -1 on failure (invalid hex string)
3621bd4fe43Sopenharmony_ci */
3631bd4fe43Sopenharmony_ciint at_hexstr2bin(const char *hex, hi_u8 *buf, size_t len)
3641bd4fe43Sopenharmony_ci{
3651bd4fe43Sopenharmony_ci    size_t i;
3661bd4fe43Sopenharmony_ci    const char *ipos = hex;
3671bd4fe43Sopenharmony_ci    hi_u8 *opos = buf;
3681bd4fe43Sopenharmony_ci
3691bd4fe43Sopenharmony_ci    for (i = 0; i < len; i++) {
3701bd4fe43Sopenharmony_ci        int a = at_hex2byte(ipos);
3711bd4fe43Sopenharmony_ci        if (a < 0) {
3721bd4fe43Sopenharmony_ci            return -1;
3731bd4fe43Sopenharmony_ci        }
3741bd4fe43Sopenharmony_ci        *opos++ = a;
3751bd4fe43Sopenharmony_ci        ipos += 2;  /* add 2 */
3761bd4fe43Sopenharmony_ci    }
3771bd4fe43Sopenharmony_ci    return 0;
3781bd4fe43Sopenharmony_ci}
3791bd4fe43Sopenharmony_ci
3801bd4fe43Sopenharmony_civoid at_printf_encode(char *txt, size_t maxlen, const hi_u8 *data, size_t len)
3811bd4fe43Sopenharmony_ci{
3821bd4fe43Sopenharmony_ci    char *end = txt + maxlen;
3831bd4fe43Sopenharmony_ci    size_t i;
3841bd4fe43Sopenharmony_ci
3851bd4fe43Sopenharmony_ci    for (i = 0; i < len; i++) {
3861bd4fe43Sopenharmony_ci        if (txt + 4 >= end) {   /* add 4 */
3871bd4fe43Sopenharmony_ci            break;
3881bd4fe43Sopenharmony_ci        }
3891bd4fe43Sopenharmony_ci
3901bd4fe43Sopenharmony_ci        switch (data[i]) {
3911bd4fe43Sopenharmony_ci            case '\"':
3921bd4fe43Sopenharmony_ci                *txt++ = '\\';
3931bd4fe43Sopenharmony_ci                *txt++ = '\"';
3941bd4fe43Sopenharmony_ci                break;
3951bd4fe43Sopenharmony_ci            case '\\':
3961bd4fe43Sopenharmony_ci                *txt++ = '\\';
3971bd4fe43Sopenharmony_ci                *txt++ = '\\';
3981bd4fe43Sopenharmony_ci                break;
3991bd4fe43Sopenharmony_ci            case '\033':
4001bd4fe43Sopenharmony_ci                *txt++ = '\\';
4011bd4fe43Sopenharmony_ci                *txt++ = 'e';
4021bd4fe43Sopenharmony_ci                break;
4031bd4fe43Sopenharmony_ci            case '\n':
4041bd4fe43Sopenharmony_ci                *txt++ = '\\';
4051bd4fe43Sopenharmony_ci                *txt++ = 'n';
4061bd4fe43Sopenharmony_ci                break;
4071bd4fe43Sopenharmony_ci            case '\r':
4081bd4fe43Sopenharmony_ci                *txt++ = '\\';
4091bd4fe43Sopenharmony_ci                *txt++ = 'r';
4101bd4fe43Sopenharmony_ci                break;
4111bd4fe43Sopenharmony_ci            case '\t':
4121bd4fe43Sopenharmony_ci                *txt++ = '\\';
4131bd4fe43Sopenharmony_ci                *txt++ = 't';
4141bd4fe43Sopenharmony_ci                break;
4151bd4fe43Sopenharmony_ci            default:
4161bd4fe43Sopenharmony_ci                if (data[i] >= 32 && data[i] <= 126) {  /* range [32,126] */
4171bd4fe43Sopenharmony_ci                    *txt++ = data[i];
4181bd4fe43Sopenharmony_ci                } else {
4191bd4fe43Sopenharmony_ci                    txt += at_pading(txt, end - txt, "\\x%02x", data[i]);
4201bd4fe43Sopenharmony_ci                }
4211bd4fe43Sopenharmony_ci                break;
4221bd4fe43Sopenharmony_ci        }
4231bd4fe43Sopenharmony_ci    }
4241bd4fe43Sopenharmony_ci
4251bd4fe43Sopenharmony_ci    *txt = '\0';
4261bd4fe43Sopenharmony_ci}
4271bd4fe43Sopenharmony_ci
4281bd4fe43Sopenharmony_cihi_void at_printf_decode_slash(hi_u8 *buf, const char **str_pos, size_t *str_len)
4291bd4fe43Sopenharmony_ci{
4301bd4fe43Sopenharmony_ci    const char *pos = *str_pos;
4311bd4fe43Sopenharmony_ci    size_t len = *str_len;
4321bd4fe43Sopenharmony_ci    int val;
4331bd4fe43Sopenharmony_ci
4341bd4fe43Sopenharmony_ci    pos++;
4351bd4fe43Sopenharmony_ci    switch (*pos) {
4361bd4fe43Sopenharmony_ci        case '\\':
4371bd4fe43Sopenharmony_ci            buf[len++] = '\\';
4381bd4fe43Sopenharmony_ci            pos++;
4391bd4fe43Sopenharmony_ci            break;
4401bd4fe43Sopenharmony_ci        case '"':
4411bd4fe43Sopenharmony_ci            buf[len++] = '"';
4421bd4fe43Sopenharmony_ci            pos++;
4431bd4fe43Sopenharmony_ci            break;
4441bd4fe43Sopenharmony_ci        case 'n':
4451bd4fe43Sopenharmony_ci            buf[len++] = '\n';
4461bd4fe43Sopenharmony_ci            pos++;
4471bd4fe43Sopenharmony_ci            break;
4481bd4fe43Sopenharmony_ci        case 'r':
4491bd4fe43Sopenharmony_ci            buf[len++] = '\r';
4501bd4fe43Sopenharmony_ci            pos++;
4511bd4fe43Sopenharmony_ci            break;
4521bd4fe43Sopenharmony_ci        case 't':
4531bd4fe43Sopenharmony_ci            buf[len++] = '\t';
4541bd4fe43Sopenharmony_ci            pos++;
4551bd4fe43Sopenharmony_ci            break;
4561bd4fe43Sopenharmony_ci        case 'e':
4571bd4fe43Sopenharmony_ci            buf[len++] = '\033';
4581bd4fe43Sopenharmony_ci            pos++;
4591bd4fe43Sopenharmony_ci            break;
4601bd4fe43Sopenharmony_ci        case 'x':
4611bd4fe43Sopenharmony_ci            pos++;
4621bd4fe43Sopenharmony_ci            val = at_hex2byte(pos);
4631bd4fe43Sopenharmony_ci            if (val < 0) {
4641bd4fe43Sopenharmony_ci                val = at_hex2num(*pos);
4651bd4fe43Sopenharmony_ci                if (val < 0) {
4661bd4fe43Sopenharmony_ci                    break;
4671bd4fe43Sopenharmony_ci                }
4681bd4fe43Sopenharmony_ci                buf[len++] = val;
4691bd4fe43Sopenharmony_ci                pos++;
4701bd4fe43Sopenharmony_ci            } else {
4711bd4fe43Sopenharmony_ci                buf[len++] = val;
4721bd4fe43Sopenharmony_ci                pos += 2;   /* add 2 */
4731bd4fe43Sopenharmony_ci            }
4741bd4fe43Sopenharmony_ci            break;
4751bd4fe43Sopenharmony_ci        case '0':
4761bd4fe43Sopenharmony_ci        case '1':
4771bd4fe43Sopenharmony_ci        case '2':
4781bd4fe43Sopenharmony_ci        case '3':
4791bd4fe43Sopenharmony_ci        case '4':
4801bd4fe43Sopenharmony_ci        case '5':
4811bd4fe43Sopenharmony_ci        case '6':
4821bd4fe43Sopenharmony_ci        case '7':
4831bd4fe43Sopenharmony_ci            val = *pos++ - '0';
4841bd4fe43Sopenharmony_ci            if (*pos >= '0' && *pos <= '7') {
4851bd4fe43Sopenharmony_ci                val = val * 8 + (*pos++ - '0'); /* 8 */
4861bd4fe43Sopenharmony_ci            }
4871bd4fe43Sopenharmony_ci            if (*pos >= '0' && *pos <= '7') {
4881bd4fe43Sopenharmony_ci                val = val * 8 + (*pos++ - '0'); /* 8 */
4891bd4fe43Sopenharmony_ci            }
4901bd4fe43Sopenharmony_ci            buf[len++] = val;
4911bd4fe43Sopenharmony_ci            break;
4921bd4fe43Sopenharmony_ci        default:
4931bd4fe43Sopenharmony_ci            break;
4941bd4fe43Sopenharmony_ci    }
4951bd4fe43Sopenharmony_ci
4961bd4fe43Sopenharmony_ci    *str_pos = pos;
4971bd4fe43Sopenharmony_ci    *str_len = len;
4981bd4fe43Sopenharmony_ci}
4991bd4fe43Sopenharmony_ci
5001bd4fe43Sopenharmony_cisize_t at_printf_decode(hi_u8 *buf, size_t maxlen, const char *str)
5011bd4fe43Sopenharmony_ci{
5021bd4fe43Sopenharmony_ci    const char *pos = str;
5031bd4fe43Sopenharmony_ci    size_t len = 0;
5041bd4fe43Sopenharmony_ci
5051bd4fe43Sopenharmony_ci    while (*pos) {
5061bd4fe43Sopenharmony_ci        if (len + 1 >= maxlen) {
5071bd4fe43Sopenharmony_ci            break;
5081bd4fe43Sopenharmony_ci        }
5091bd4fe43Sopenharmony_ci        switch (*pos) {
5101bd4fe43Sopenharmony_ci            case '\\':
5111bd4fe43Sopenharmony_ci                at_printf_decode_slash(buf, &pos, &len);
5121bd4fe43Sopenharmony_ci                break;
5131bd4fe43Sopenharmony_ci            default:
5141bd4fe43Sopenharmony_ci                buf[len++] = *pos++;
5151bd4fe43Sopenharmony_ci                break;
5161bd4fe43Sopenharmony_ci        }
5171bd4fe43Sopenharmony_ci    }
5181bd4fe43Sopenharmony_ci    if (maxlen > len) {
5191bd4fe43Sopenharmony_ci        buf[len] = '\0';
5201bd4fe43Sopenharmony_ci    }
5211bd4fe43Sopenharmony_ci
5221bd4fe43Sopenharmony_ci    return len;
5231bd4fe43Sopenharmony_ci}
5241bd4fe43Sopenharmony_ci
5251bd4fe43Sopenharmony_cichar* at_parse_string_normal(const char *value, size_t *len)
5261bd4fe43Sopenharmony_ci{
5271bd4fe43Sopenharmony_ci    const char *pos = NULL;
5281bd4fe43Sopenharmony_ci    char *str = NULL;
5291bd4fe43Sopenharmony_ci
5301bd4fe43Sopenharmony_ci    value++;
5311bd4fe43Sopenharmony_ci    pos = at_strrchr(value, '"');
5321bd4fe43Sopenharmony_ci    if (pos == NULL || pos[1] != '\0') {
5331bd4fe43Sopenharmony_ci        return NULL;
5341bd4fe43Sopenharmony_ci    }
5351bd4fe43Sopenharmony_ci    *len = pos - value;
5361bd4fe43Sopenharmony_ci    str = at_dup_binstr(value, *len);
5371bd4fe43Sopenharmony_ci    if (str == NULL) {
5381bd4fe43Sopenharmony_ci        return NULL;
5391bd4fe43Sopenharmony_ci    }
5401bd4fe43Sopenharmony_ci    return str;
5411bd4fe43Sopenharmony_ci}
5421bd4fe43Sopenharmony_ci
5431bd4fe43Sopenharmony_cichar* at_parse_string_with_p(const char *value, size_t *len)
5441bd4fe43Sopenharmony_ci{
5451bd4fe43Sopenharmony_ci    const char *pos = NULL;
5461bd4fe43Sopenharmony_ci    char *tstr = NULL;
5471bd4fe43Sopenharmony_ci    char *str = NULL;
5481bd4fe43Sopenharmony_ci    size_t tlen;
5491bd4fe43Sopenharmony_ci
5501bd4fe43Sopenharmony_ci    value += 2;     /* add 2 */
5511bd4fe43Sopenharmony_ci    pos = at_strrchr(value, '"');
5521bd4fe43Sopenharmony_ci    if (pos == NULL || pos[1] != '\0') {
5531bd4fe43Sopenharmony_ci        return NULL;
5541bd4fe43Sopenharmony_ci    }
5551bd4fe43Sopenharmony_ci    tlen = pos - value;
5561bd4fe43Sopenharmony_ci    tstr = at_dup_binstr(value, tlen);
5571bd4fe43Sopenharmony_ci    if (tstr == NULL) {
5581bd4fe43Sopenharmony_ci        return NULL;
5591bd4fe43Sopenharmony_ci    }
5601bd4fe43Sopenharmony_ci
5611bd4fe43Sopenharmony_ci    str = at_malloc(tlen + 1);
5621bd4fe43Sopenharmony_ci    if (str == NULL) {
5631bd4fe43Sopenharmony_ci        at_free(tstr);
5641bd4fe43Sopenharmony_ci        return NULL;
5651bd4fe43Sopenharmony_ci    }
5661bd4fe43Sopenharmony_ci
5671bd4fe43Sopenharmony_ci    *len = at_printf_decode((hi_u8 *) str, tlen + 1, tstr);
5681bd4fe43Sopenharmony_ci    at_free(tstr);
5691bd4fe43Sopenharmony_ci
5701bd4fe43Sopenharmony_ci    return str;
5711bd4fe43Sopenharmony_ci}
5721bd4fe43Sopenharmony_ci
5731bd4fe43Sopenharmony_cichar* at_parse_string_other(const char *value, size_t *len)
5741bd4fe43Sopenharmony_ci{
5751bd4fe43Sopenharmony_ci    hi_u8 *str = NULL;
5761bd4fe43Sopenharmony_ci    size_t tlen;
5771bd4fe43Sopenharmony_ci    size_t hlen = at_strlen(value);
5781bd4fe43Sopenharmony_ci    if (hlen & 1) {
5791bd4fe43Sopenharmony_ci        return NULL;
5801bd4fe43Sopenharmony_ci    }
5811bd4fe43Sopenharmony_ci    tlen = hlen / 2;    /* 2 */
5821bd4fe43Sopenharmony_ci    str = at_malloc(tlen + 1);
5831bd4fe43Sopenharmony_ci    if (str == NULL) {
5841bd4fe43Sopenharmony_ci        return NULL;
5851bd4fe43Sopenharmony_ci    }
5861bd4fe43Sopenharmony_ci    if (at_hexstr2bin(value, str, tlen)) {
5871bd4fe43Sopenharmony_ci        at_free((char*)str);
5881bd4fe43Sopenharmony_ci        return NULL;
5891bd4fe43Sopenharmony_ci    }
5901bd4fe43Sopenharmony_ci    str[tlen] = '\0';
5911bd4fe43Sopenharmony_ci    *len = tlen;
5921bd4fe43Sopenharmony_ci    return (char *) str;
5931bd4fe43Sopenharmony_ci}
5941bd4fe43Sopenharmony_ci
5951bd4fe43Sopenharmony_ci
5961bd4fe43Sopenharmony_cichar* at_parse_string(const char *value, size_t *len)
5971bd4fe43Sopenharmony_ci{
5981bd4fe43Sopenharmony_ci    if (len == HI_NULL) {
5991bd4fe43Sopenharmony_ci        return HI_NULL;
6001bd4fe43Sopenharmony_ci    }
6011bd4fe43Sopenharmony_ci    if (*value == '"') {
6021bd4fe43Sopenharmony_ci        return at_parse_string_normal(value, len);
6031bd4fe43Sopenharmony_ci    } else if (*value == 'P' && value[1] == '"') {
6041bd4fe43Sopenharmony_ci        return at_parse_string_with_p(value, len);
6051bd4fe43Sopenharmony_ci    } else {
6061bd4fe43Sopenharmony_ci        return at_parse_string_other(value, len);
6071bd4fe43Sopenharmony_ci    }
6081bd4fe43Sopenharmony_ci}
6091bd4fe43Sopenharmony_ci
6101bd4fe43Sopenharmony_ci/**
6111bd4fe43Sopenharmony_ci * at_ssid_txt - Convert SSID to a printable string
6121bd4fe43Sopenharmony_ci * @ssid: SSID (32-octet string)
6131bd4fe43Sopenharmony_ci * @ssid_len: Length of ssid in octets
6141bd4fe43Sopenharmony_ci * Returns: Pointer to a printable string
6151bd4fe43Sopenharmony_ci *
6161bd4fe43Sopenharmony_ci * This function can be used to convert SSIDs into printable form. In most
6171bd4fe43Sopenharmony_ci * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
6181bd4fe43Sopenharmony_ci * does not limit the used character set, so anything could be used in an SSID.
6191bd4fe43Sopenharmony_ci *
6201bd4fe43Sopenharmony_ci * This function uses a static buffer, so only one call can be used at the
6211bd4fe43Sopenharmony_ci * time, i.e., this is not re-entrant and the returned buffer must be used
6221bd4fe43Sopenharmony_ci * before calling this again.
6231bd4fe43Sopenharmony_ci */
6241bd4fe43Sopenharmony_ciconst char* at_ssid_txt(const hi_u8 *ssid, size_t ssid_len)
6251bd4fe43Sopenharmony_ci{
6261bd4fe43Sopenharmony_ci    static char ssid_txt[AT_SSID_MAX_LEN * 4 + 1]; /* 4 */
6271bd4fe43Sopenharmony_ci
6281bd4fe43Sopenharmony_ci    if (ssid == NULL) {
6291bd4fe43Sopenharmony_ci        ssid_txt[0] = '\0';
6301bd4fe43Sopenharmony_ci        return ssid_txt;
6311bd4fe43Sopenharmony_ci    }
6321bd4fe43Sopenharmony_ci
6331bd4fe43Sopenharmony_ci    at_printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
6341bd4fe43Sopenharmony_ci    return ssid_txt;
6351bd4fe43Sopenharmony_ci}
6361bd4fe43Sopenharmony_ci
6371bd4fe43Sopenharmony_ci#ifdef __cplusplus
6381bd4fe43Sopenharmony_ci#if __cplusplus
6391bd4fe43Sopenharmony_ci    }
6401bd4fe43Sopenharmony_ci#endif
6411bd4fe43Sopenharmony_ci#endif
642