MindSDK_MM32F5270/components/at/at_server.c

292 lines
7.2 KiB
C

/*
* Copyright 2022 MindMotion Microelectronics Co., Ltd.
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "at_server.h"
/*
* Macros.
*/
/*
* Declerations.
*/
/* at command parse. */
void at_parse(at_server_t * server);
/* get the at command name from at receive command buffer.*/
static bool at_cmd_get_name(char * cmd_buffer, char * cmd_name);
/* find the at command name from at command list. */
static at_cmd_t * at_find_cmd(at_server_t * server, char * cmd);
/* process the at command. */
static bool at_cmd_process(at_server_t * server, at_cmd_t * cmd, char * cmd_args);
/* check the ar command parameter format. */
static bool at_check_args(char * args, char * args_format);
/*
* Variables.
*/
/*
* Functions.
*/
void at_server_init(at_server_t * server,at_adapter_t * adapter)
{
adapter->init();
server->adapter = adapter;
server->remaining = adapter->buf_size;
memcpy(server->end_mark, AT_CMD_END_MARK_DEFAULT, sizeof(AT_CMD_END_MARK_DEFAULT));
}
void at_server_set_cmd_list(at_server_t * server, at_cmd_t * cmd_list[], uint32_t cmd_num)
{
server->cmd_list = cmd_list;
server->cmd_num = cmd_num;
}
void at_server_write(at_server_t * server, char * buf, uint32_t len)
{
server->adapter->write(buf, len);
}
uint32_t at_server_read(at_server_t * server, char * buf, uint32_t len)
{
return server->adapter->read(buf, len);
}
void at_server_task(at_server_t * server)
{
char * matchstr=NULL; /* Represents the string left after being returned using the strstr function. */
char * buf = &(server->adapter->buf[server->adapter->buf_size - server->remaining]);
uint32_t len = at_server_read(server, buf, server->remaining);
if (0u != len)
{
server->remaining -= len;
while(1) /* wait for all recipients in the received data to be compared. */
{
matchstr = strstr(server->adapter->buf, server->end_mark);
if (NULL != matchstr)
{
at_parse(server);
/* not copy the last matching terminator. */
memcpy(server->adapter->buf, matchstr+strlen(server->end_mark), strlen(server->adapter->buf));
server->remaining = server->adapter->buf_size - strlen(matchstr);
}
else
{
break;
}
}
}
}
/*parse the receive datas.*/
void at_parse(at_server_t * server)
{
char cur_cmd_name[AT_CMD_NAME_LEN] = { 0 };
at_cmd_t * cur_cmd = NULL;
char * cur_cmd_args = NULL;
char * buf = server->adapter->buf;
if (at_cmd_get_name(buf, cur_cmd_name) == false)
{
AT_LOG("ERROR CMD MATCH FAILED!\r\n");
return;
}
cur_cmd = at_find_cmd(server, cur_cmd_name);
if (cur_cmd == false)
{
AT_LOG("ERROR CMD MATCH FAILED!\r\n");
return;
}
cur_cmd_args = buf + strlen(cur_cmd_name);
if (at_cmd_process(server, cur_cmd, cur_cmd_args) == false)
{
AT_LOG("ERROR PARSE ARGS FAILED!\r\n");
return;
}
}
/* get at command name from at server receive buffer. */
static bool at_cmd_get_name(char * cmd_buffer, char * cmd_name)
{
uint32_t cmd_name_len = 0u;
for (uint32_t i = 0; i < strlen(cmd_buffer) + 1; i++)
{
if ( (*(cmd_buffer + i) == AT_CMD_QUESTION_MARK) || (*(cmd_buffer + i) == AT_CMD_EQUAL_MARK)
|| (*(cmd_buffer + i) == AT_CMD_CR)
|| ( (*(cmd_buffer + i) >= AT_CMD_CHAR_0) && (*(cmd_buffer + i) <= AT_CMD_CHAR_9) ) )
{
cmd_name_len = i;
memcpy(cmd_name, cmd_buffer, cmd_name_len);
*(cmd_name + cmd_name_len) = '\0';
return true;
}
}
return false;
}
/* find if the current at command name is in the at command list. */
static at_cmd_t * at_find_cmd(at_server_t * server, char * cmd)
{
for (uint32_t i = 0; i < server->cmd_num; i++)
{
if (!strcasecmp(cmd,server->cmd_list[i]->name))
{
return server->cmd_list[i];
}
}
return false;
}
/* parse command parameters and execute corresponding command functions. */
static bool at_cmd_process(at_server_t * server, at_cmd_t * cmd, char * cmd_args)
{
at_result_t result = AT_RESULT_OK;
if ( (cmd_args[0] == AT_CMD_EQUAL_MARK) && (cmd_args[1] == AT_CMD_QUESTION_MARK) && (cmd_args[2] == AT_CMD_CR) )
{
if (cmd->test == NULL)
{
AT_LOG("ERROR CHECK ARGS FORMAT FAILED!\r\n");
return false;
}
result = cmd->test(server->adapter->write);
}
else if ( (cmd_args[0] == AT_CMD_QUESTION_MARK) && (cmd_args[1] == AT_CMD_CR) )
{
if (cmd->query == NULL)
{
AT_LOG("ERROR CHECK ARGS FORMAT FAILED!\r\n");
return false;
}
result = cmd->query(server->adapter->write);
}
else if ( (cmd_args[0] == AT_CMD_EQUAL_MARK)
|| ( (cmd_args[0] >= AT_CMD_CHAR_0) && (cmd_args[0] <= AT_CMD_CHAR_9) && (cmd_args[1] == AT_CMD_CR) ) )
{
if (cmd->setup == NULL)
{
AT_LOG("ERROR CHECK ARGS FORMAT FAILED!\r\n");
return false;
}
if(at_check_args(cmd_args, cmd->args_expr) == false)
{
AT_LOG("ERROR CHECK ARGS FORMAT FAILED!\r\n");;
return false;
}
result = cmd->setup(server->adapter->write, cmd_args);
}
else if (cmd_args[0] == AT_CMD_CR)
{
if (cmd->exec == NULL)
{
return false;
}
result = cmd->exec(server->adapter->write);
}
else
{
return result;
}
return true;
}
/* check the ar command parameter format. */
static bool at_check_args(char * args, char * args_format)
{
uint32_t left_sq_bracket_num = 0, right_sq_bracket_num = 0;
uint32_t left_angle_bracket_num = 0, right_angle_bracket_num = 0;
uint32_t comma_mark_num = 0;
for (uint32_t i = 0; i < strlen(args_format); i++)
{
switch (args_format[i])
{
case AT_CMD_L_SQ_BRACKET:
left_sq_bracket_num++;
break;
case AT_CMD_R_SQ_BRACKET:
right_sq_bracket_num++;
break;
case AT_CMD_L_ANGLE_BRACKET:
left_angle_bracket_num++;
break;
case AT_CMD_R_ANGLE_BRACKET:
right_angle_bracket_num++;
break;
default:
break;
}
}
if ( (left_sq_bracket_num != right_sq_bracket_num) || (left_angle_bracket_num != right_angle_bracket_num)
|| (left_sq_bracket_num > left_angle_bracket_num) )
{
return -1;
}
for (uint32_t i = 0; i < strlen(args); i++)
{
if (args[i] == AT_CMD_COMMA_MARK)
{
comma_mark_num++;
}
}
if ( (comma_mark_num + 1 < left_angle_bracket_num - left_sq_bracket_num)
|| (comma_mark_num + 1 > left_angle_bracket_num) )
{
return false;
}
return true;
}
/* parse the number of arguments to the at request instruction. */
int at_req_parse_args(const char * req_args, const char * req_expr, ...)
{
va_list args;
int req_args_num = 0;
va_start(args, req_expr);
req_args_num = vsscanf(req_args, req_expr, args);
va_end(args);
return req_args_num;
}
/* EOF. */