[components][at] 优化AT组件,并解决内存泄露

1.优化at server endmark判断,支持自动识别'\r''\n'"\r\n"。
2.优化at_recvfrom,修复大数据量时sem多次释放造成的接收错误。
3.修复at组件中可能存在的内存泄露。
4.优化部分代码逻辑,减少冗余代码。
This commit is contained in:
yangpengya 2024-02-19 00:07:05 +08:00 committed by GitHub
parent 02eaf76d7b
commit a8d5a645f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 172 additions and 338 deletions

View File

@ -26,25 +26,6 @@ if RT_USING_AT
int "The maximum length of server commands buffer"
default 256
choice
prompt "The commands new line sign"
help
This end mark can used for AT server determine the end of commands ,
it can choose "\r", "\n" or "\r\n"
default AT_CMD_END_MARK_CRLF
config AT_CMD_END_MARK_CRLF
bool "\\r\\n"
config AT_CMD_END_MARK_CR
bool "\\r"
config AT_CMD_END_MARK_LF
bool "\\n"
endchoice
endif
config AT_USING_CLIENT

View File

@ -717,16 +717,13 @@ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
}
#ifdef AT_USING_SOCKET_SERVER
static int (*store_at_socket_temporary)(struct at_device *device, enum at_socket_type type);
static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
{
RT_ASSERT(buff);
RT_ASSERT(sock == RT_NULL);
RT_ASSERT(event == AT_SOCKET_EVT_CONNECTED);
extern struct netdev *netdev_default;
struct netdev *netdev = RT_NULL;
struct at_device *device = RT_NULL;
int new_socket;
struct at_socket *new_sock = RT_NULL;
rt_base_t level;
rt_slist_t *node = RT_NULL;
@ -734,51 +731,17 @@ static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event,
char *socket_info = RT_NULL;
int base_socket = 0;
if (netdev_default && netdev_is_up(netdev_default) &&
netdev_family_get(netdev_default) == AF_AT)
{
netdev = netdev_default;
}
else
{
/* get network interface device by protocol family AF_AT */
netdev = netdev_get_by_family(AF_AT);
if (netdev == RT_NULL)
{
return;
}
}
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
return;
}
/* avoid use bottom driver to alloc "socket" */
store_at_socket_temporary = device->class->socket_ops->at_socket;
device->class->socket_ops->at_socket = RT_NULL;
new_sock = alloc_socket_by_device(device, AT_SOCKET_TCP);
if (new_sock == RT_NULL)
new_socket = at_socket(AF_AT, SOCK_STREAM, 0);
if (new_socket == -1)
{
return;
}
new_sock->type = AT_SOCKET_TCP;
new_sock = at_get_socket(new_socket);
new_sock->state = AT_SOCKET_CONNECT;
/* set AT socket receive data callback function */
new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
new_sock->ops->at_set_event_cb(AT_SOCKET_EVT_CONNECTED, at_connect_notice_cb);
device->class->socket_ops->at_socket = store_at_socket_temporary;
/* put incoming "socket" to the listen socket receiver packet list */
sscanf(buff, "SOCKET:%d", &base_socket);
LOG_D("ACCEPT BASE SOCKET: %d", base_socket);
new_sock->user_data = (void *)base_socket;
socket_info = rt_malloc(AT_SOCKET_INFO_LEN);
rt_memset(socket_info, 0, AT_SOCKET_INFO_LEN);
rt_sprintf(socket_info, "SOCKET:%d", new_sock->socket);
/* find out the listen socket */
level = rt_hw_interrupt_disable();
@ -793,16 +756,23 @@ static void at_connect_notice_cb(struct at_socket *sock, at_socket_evt_t event,
}
rt_hw_interrupt_enable(level);
if(at_sock == RT_NULL)
if (at_sock == RT_NULL)
{
at_closesocket(new_socket);
return;
}
/* put incoming "socket" to the listen socket receiver packet list */
socket_info = rt_malloc(AT_SOCKET_INFO_LEN);
rt_memset(socket_info, 0, AT_SOCKET_INFO_LEN);
rt_sprintf(socket_info, "SOCKET:%d", new_sock->socket);
/* wakeup the "accept" function */
rt_mutex_take(at_sock->recv_lock, RT_WAITING_FOREVER);
if (at_recvpkt_put(&(at_sock->recvpkt_list), socket_info, AT_SOCKET_INFO_LEN) != RT_EOK)
{
rt_free((void *)buff);
at_closesocket(new_socket);
rt_free(socket_info);
rt_mutex_release(at_sock->recv_lock);
return;
}
@ -866,8 +836,7 @@ int at_listen(int socket, int backlog)
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
return -1;
}
if (sock->state != AT_SOCKET_OPEN)
@ -890,10 +859,7 @@ __exit:
if (result < 0)
{
if (sock != RT_NULL)
{
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
return result;
@ -911,8 +877,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
return -1;
}
if (sock->state != AT_SOCKET_OPEN)
@ -938,13 +903,9 @@ __exit:
if (result < 0)
{
if (sock != RT_NULL)
{
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
if (sock)
else
{
at_do_event_changes(sock, AT_EVENT_SEND, RT_TRUE);
}
@ -966,8 +927,7 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
return -1;
}
if (sock->state != AT_SOCKET_LISTEN)
@ -990,16 +950,11 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
at_recvpkt_get(&(sock->recvpkt_list), (char *) &receive_buff, AT_SOCKET_INFO_LEN);
rt_mutex_release(sock->recv_lock);
at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
}
sscanf(&receive_buff[0], "SOCKET:%d", &new_socket);
new_sock = at_get_socket(new_socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
}
new_sock->state = AT_SOCKET_CONNECT;
ip4_addr_set_any(&remote_addr);
ipaddr_port_to_socketaddr(name, &remote_addr, &remote_port);
LOG_D("Accept: [socket :%d, base_socket:%d]", new_socket, (int)new_sock->user_data);
@ -1007,10 +962,7 @@ int at_accept(int socket, struct sockaddr *name, socklen_t *namelen)
__exit:
if (result < 0)
{
if (sock != RT_NULL)
{
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
return new_sock->socket;
@ -1025,15 +977,14 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
if (mem == RT_NULL || len == 0)
{
LOG_E("AT recvfrom input data or length error!");
return -1;
/* if the requested number of bytes to receive from a stream socket was 0. */
return 0;
}
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
return -1;
}
/* if the socket type is UDP, need to connect socket first */
@ -1048,104 +999,66 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
{
result = -1;
goto __exit;
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
/* socket shutdown */
return 0;
}
sock->state = AT_SOCKET_CONNECT;
}
/* receive packet list last transmission of remaining data */
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
if((recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len)) > 0)
{
rt_mutex_release(sock->recv_lock);
goto __exit;
}
rt_mutex_release(sock->recv_lock);
/* socket passively closed, receive function return 0 */
if (sock->state == AT_SOCKET_CLOSED)
{
result = 0;
goto __exit;
}
else if (sock->state != AT_SOCKET_CONNECT && sock->state != AT_SOCKET_OPEN)
{
LOG_E("received data error, current socket (%d) state (%d) is error.", socket, sock->state);
result = -1;
goto __exit;
}
/* non-blocking sockets receive data */
if (flags & MSG_DONTWAIT)
{
goto __exit;
}
/* set AT socket receive timeout */
if ((timeout = sock->recv_timeout) == 0)
{
timeout = RT_WAITING_FOREVER;
}
else
{
timeout = rt_tick_from_millisecond(timeout);
}
while (1)
{
/* wait the receive semaphore */
if (rt_sem_take(sock->recv_notice, timeout) < 0)
if (sock->state == AT_SOCKET_CLOSED)
{
/* socket passively closed, receive function return 0 */
result = 0;
break;
}
rt_sem_control(sock->recv_notice, RT_IPC_CMD_RESET, RT_NULL);
/* receive packet list last transmission of remaining data */
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *)mem, len);
rt_mutex_release(sock->recv_lock);
if (recv_len > 0)
{
if (rt_slist_isempty(&sock->recvpkt_list))
{
at_do_event_clean(sock, AT_EVENT_RECV);
}
errno = 0;
result = recv_len;
break;
}
if (flags & MSG_DONTWAIT)
{
errno = EAGAIN;
result = -1;
break;
}
/* set AT socket receive timeout */
if (sock->recv_timeout == 0)
{
timeout = RT_WAITING_FOREVER;
}
else
{
timeout = rt_tick_from_millisecond(sock->recv_timeout);
}
if (rt_sem_take(sock->recv_notice, timeout) != RT_EOK)
{
LOG_D("AT socket (%d) receive timeout (%d)!", socket, timeout);
errno = EAGAIN;
result = -1;
goto __exit;
}
else
{
/* get receive buffer to receiver ring buffer */
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
recv_len = at_recvpkt_get(&(sock->recvpkt_list), (char *) mem, len);
rt_mutex_release(sock->recv_lock);
if (recv_len > 0)
{
break;
}
else
{
/* we have no data to receive but are woken up,
which means the socket have been closed. */
errno = EIO;
result = -1;
goto __exit;
}
break;
}
}
__exit:
if (sock != RT_NULL)
if (result <= 0)
{
if (recv_len > 0)
{
result = recv_len;
at_do_event_changes(sock, AT_EVENT_RECV, RT_FALSE);
errno = 0;
if (!rt_slist_isempty(&sock->recvpkt_list))
{
at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
}
else
{
at_do_event_clean(sock, AT_EVENT_RECV);
}
}
else
{
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
return result;
@ -1164,15 +1077,13 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct
if (data == RT_NULL || size == 0)
{
LOG_E("AT sendto input data or size error!");
result = -1;
goto __exit;
return -1;
}
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
result = -1;
goto __exit;
return -1;
}
switch (sock->type)
@ -1232,10 +1143,7 @@ __exit:
if (result < 0)
{
if (sock != RT_NULL)
{
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
}
else
{

View File

@ -22,20 +22,6 @@ extern "C" {
#define AT_SW_VERSION "1.3.1"
#define AT_CMD_NAME_LEN 16
#define AT_END_MARK_LEN 4
#ifndef AT_CMD_MAX_LEN
#define AT_CMD_MAX_LEN 128
#endif
/* the server AT commands new line sign */
#if defined(AT_CMD_END_MARK_CRLF)
#define AT_CMD_END_MARK "\r\n"
#elif defined(AT_CMD_END_MARK_CR)
#define AT_CMD_END_MARK "\r"
#elif defined(AT_CMD_END_MARK_LF)
#define AT_CMD_END_MARK "\n"
#endif
#ifndef AT_SERVER_RECV_BUFF_LEN
#define AT_SERVER_RECV_BUFF_LEN 256
@ -104,7 +90,6 @@ struct at_server
char recv_buffer[AT_SERVER_RECV_BUFF_LEN];
rt_size_t cur_recv_len;
rt_sem_t rx_notice;
char end_mark[AT_END_MARK_LEN];
rt_thread_t parser;
void (*parser_entry)(struct at_server *server);

View File

@ -114,7 +114,6 @@ static void server_cli_parser(void)
rt_base_t level;
static rt_device_t device_bak;
static rt_err_t (*getchar_bak)(struct at_server *server, char *ch, rt_int32_t timeout);
static char endmark_back[AT_END_MARK_LEN];
/* backup server device and getchar function */
{
@ -123,16 +122,10 @@ static void server_cli_parser(void)
device_bak = server->device;
getchar_bak = server->get_char;
rt_memset(endmark_back, 0x00, AT_END_MARK_LEN);
rt_memcpy(endmark_back, server->end_mark, strlen(server->end_mark));
/* setup server device as console device */
server->device = rt_console_get_device();
server->get_char = at_server_console_getchar;
rt_memset(server->end_mark, 0x00, AT_END_MARK_LEN);
server->end_mark[0] = '\r';
rt_hw_interrupt_enable(level);
}
@ -154,9 +147,6 @@ static void server_cli_parser(void)
server->device = device_bak;
server->get_char = getchar_bak;
rt_memset(server->end_mark, 0x00, AT_END_MARK_LEN);
rt_memcpy(server->end_mark, endmark_back, strlen(endmark_back));
rt_hw_interrupt_enable(level);
}
}
@ -223,6 +213,9 @@ static void client_cli_parser(at_client_t client)
client->status = AT_STATUS_CLI;
}
rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
/* backup client device RX indicate */
{
level = rt_hw_interrupt_disable();
@ -231,9 +224,6 @@ static void client_cli_parser(at_client_t client)
rt_hw_interrupt_enable(level);
}
rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
at_client = rt_thread_create("at_cli", at_client_entry, RT_NULL, 512, 8, 8);
if (client_rx_fifo && at_client)
{

View File

@ -146,7 +146,6 @@ at_response_t at_resp_set_info(at_response_t resp, rt_size_t buf_size, rt_size_t
const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
{
char *resp_buf = resp->buf;
char *resp_line_buf = RT_NULL;
rt_size_t line_num = 1;
RT_ASSERT(resp);
@ -161,9 +160,7 @@ const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
{
if (resp_line == line_num)
{
resp_line_buf = resp_buf;
return resp_line_buf;
return resp_buf;
}
resp_buf += strlen(resp_buf) + 1;
@ -184,7 +181,6 @@ const char *at_resp_get_line(at_response_t resp, rt_size_t resp_line)
const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword)
{
char *resp_buf = resp->buf;
char *resp_line_buf = RT_NULL;
rt_size_t line_num = 1;
RT_ASSERT(resp);
@ -194,9 +190,7 @@ const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword)
{
if (strstr(resp_buf, keyword))
{
resp_line_buf = resp_buf;
return resp_line_buf;
return resp_buf;
}
resp_buf += strlen(resp_buf) + 1;
@ -332,17 +326,14 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr
LOG_W("execute command (%.*s) timeout (%d ticks)!", client->last_cmd_len, client->send_buf, resp->timeout);
client->resp_status = AT_RESP_TIMEOUT;
result = -RT_ETIMEOUT;
goto __exit;
}
if (client->resp_status != AT_RESP_OK)
else if (client->resp_status != AT_RESP_OK)
{
LOG_E("execute command (%.*s) failed!", client->last_cmd_len, client->send_buf);
result = -RT_ERROR;
goto __exit;
}
}
__exit:
client->resp = RT_NULL;
rt_mutex_release(client->lock);
@ -401,9 +392,7 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
resp->line_counts = 0;
at_utils_send(client->device, 0, "AT\r\n", 4);
if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK)
continue;
else
if (rt_sem_take(client->resp_notice, resp->timeout) == RT_EOK)
break;
}
@ -494,25 +483,23 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
return 0;
}
while (1)
while (size)
{
rt_size_t read_len;
rt_sem_control(client->rx_notice, RT_IPC_CMD_RESET, RT_NULL);
read_len = rt_device_read(client->device, 0, buf + len, size);
if(read_len > 0)
if (read_len > 0)
{
len += read_len;
size -= read_len;
if(size == 0)
break;
continue;
}
if(rt_sem_take(client->rx_notice, rt_tick_from_millisecond(timeout)) != RT_EOK)
break;
else
{
if (rt_sem_take(client->rx_notice, rt_tick_from_millisecond(timeout)) != RT_EOK)
break;
}
}
#ifdef AT_PRINT_RAW_CMD
@ -676,7 +663,6 @@ static const struct at_urc *get_urc_obj(at_client_t client)
static int at_recv_readline(at_client_t client)
{
rt_size_t read_len = 0;
char ch = 0, last_ch = 0;
rt_bool_t is_full = RT_FALSE;
@ -687,10 +673,9 @@ static int at_recv_readline(at_client_t client)
{
at_client_getchar(client, &ch, RT_WAITING_FOREVER);
if (read_len < client->recv_bufsz)
if (client->recv_line_len < client->recv_bufsz)
{
client->recv_line_buf[read_len++] = ch;
client->recv_line_len = read_len;
client->recv_line_buf[client->recv_line_len++] = ch;
}
else
{
@ -714,10 +699,10 @@ static int at_recv_readline(at_client_t client)
}
#ifdef AT_PRINT_RAW_CMD
at_print_raw_cmd("recvline", client->recv_line_buf, read_len);
at_print_raw_cmd("recvline", client->recv_line_buf, client->recv_line_len);
#endif
return read_len;
return client->recv_line_len;
}
static void client_parser(at_client_t client)
@ -882,7 +867,6 @@ static int at_client_para_init(at_client_t client)
if (client->parser == RT_NULL)
{
result = -RT_ENOMEM;
goto __exit;
}
__exit:
@ -903,16 +887,16 @@ __exit:
rt_sem_delete(client->resp_notice);
}
if (client->device)
{
rt_device_close(client->device);
}
if (client->recv_line_buf)
{
rt_free(client->recv_line_buf);
}
if (client->send_buf)
{
rt_free(client->send_buf);
}
rt_memset(client, 0x00, sizeof(struct at_client));
}
else
@ -928,6 +912,7 @@ __exit:
*
* @param dev_name AT client device name
* @param recv_bufsz the maximum number of receive buffer length
* @param send_bufsz the maximum number of send command length
*
* @return 0 : initialize success
* -1 : initialize failed
@ -974,6 +959,7 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
{
RT_ASSERT(client->device->type == RT_Device_Class_Char);
rt_device_set_rx_indicate(client->device, at_client_rx_ind);
/* using DMA mode first */
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@ -982,14 +968,11 @@ int at_client_init(const char *dev_name, rt_size_t recv_bufsz, rt_size_t send_bu
open_result = rt_device_open(client->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
RT_ASSERT(open_result == RT_EOK);
rt_device_set_rx_indicate(client->device, at_client_rx_ind);
}
else
{
LOG_E("AT client initialize failed! Not find the device(%s).", dev_name);
result = -RT_ERROR;
goto __exit;
}
__exit:

View File

@ -311,70 +311,59 @@ static rt_err_t at_check_args(const char *args, const char *args_format)
return RT_EOK;
}
static rt_err_t at_cmd_process(at_cmd_t cmd, const char *cmd_args)
static at_result_t at_cmd_process(at_cmd_t cmd, const char *cmd_args)
{
at_result_t result = AT_RESULT_OK;
RT_ASSERT(cmd);
RT_ASSERT(cmd_args);
if (cmd_args[0] == AT_CMD_EQUAL_MARK && cmd_args[1] == AT_CMD_QUESTION_MARK && cmd_args[2] == AT_CMD_CR)
/* AT+TEST=? */
if (cmd_args[0] == AT_CMD_EQUAL_MARK && cmd_args[1] == AT_CMD_QUESTION_MARK)
{
if (cmd->test == RT_NULL)
{
at_server_print_result(AT_RESULT_CMD_ERR);
return -RT_ERROR;
return AT_RESULT_CMD_ERR;
}
result = cmd->test();
at_server_print_result(result);
return cmd->test();
}
else if (cmd_args[0] == AT_CMD_QUESTION_MARK && cmd_args[1] == AT_CMD_CR)
/* AT+TEST? */
else if (cmd_args[0] == AT_CMD_QUESTION_MARK)
{
if (cmd->query == RT_NULL)
{
at_server_print_result(AT_RESULT_CMD_ERR);
return -RT_ERROR;
return AT_RESULT_CMD_ERR;
}
result = cmd->query();
at_server_print_result(result);
return cmd->query();
}
/* AT+TEST=1 or ATE1 */
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))
|| (cmd_args[0] >= AT_CMD_CHAR_0 && cmd_args[0] <= AT_CMD_CHAR_9 && (cmd_args[1] == AT_CMD_CR || cmd_args[1] == AT_CMD_LF)))
{
if (cmd->setup == RT_NULL)
{
at_server_print_result(AT_RESULT_CMD_ERR);
return -RT_ERROR;
return AT_RESULT_CMD_ERR;
}
if(at_check_args(cmd_args, cmd->args_expr) < 0)
{
at_server_print_result(AT_RESULT_CHECK_FAILE);
return -RT_ERROR;
return AT_RESULT_CHECK_FAILE;
}
result = cmd->setup(cmd_args);
at_server_print_result(result);
return cmd->setup(cmd_args);
}
else if (cmd_args[0] == AT_CMD_CR)
/* AT+TEST */
else if (cmd_args[0] == AT_CMD_CR || cmd_args[0] == AT_CMD_LF)
{
if (cmd->exec == RT_NULL)
{
at_server_print_result(AT_RESULT_CMD_ERR);
return -RT_ERROR;
return AT_RESULT_CMD_ERR;
}
result = cmd->exec();
at_server_print_result(result);
}
else
{
return -RT_ERROR;
return cmd->exec();
}
return RT_EOK;
return AT_RESULT_FAILE;
}
static at_cmd_t at_find_cmd(const char *cmd)
@ -400,10 +389,10 @@ static rt_err_t at_cmd_get_name(const char *cmd_buffer, char *cmd_name)
RT_ASSERT(cmd_name);
RT_ASSERT(cmd_buffer);
for (i = 0; i < strlen(cmd_buffer); i++)
for (i = 0; i < strlen(cmd_buffer) && i < AT_CMD_NAME_LEN; 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_CR || *(cmd_buffer + i) == AT_CMD_LF
|| (*(cmd_buffer + i) >= AT_CMD_CHAR_0 && *(cmd_buffer + i) <= AT_CMD_CHAR_9))
{
cmd_name_len = i;
@ -443,6 +432,7 @@ static void server_parser(at_server_t server)
char cur_cmd_name[AT_CMD_NAME_LEN] = { 0 };
at_cmd_t cur_cmd = RT_NULL;
char *cur_cmd_args = RT_NULL, ch, last_ch;
at_result_t result;
RT_ASSERT(server);
RT_ASSERT(server->status != AT_STATUS_UNINITIALIZED);
@ -455,66 +445,54 @@ static void server_parser(at_server_t server)
break;
}
if (server->echo_mode)
if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
{
if (ch == AT_CMD_CR || (ch == AT_CMD_LF && last_ch != AT_CMD_CR))
if (server->cur_recv_len)
server->cur_recv_len--;
if (server->echo_mode)
at_server_printf("\b \b");
}
else if (ch == AT_CMD_LF && last_ch == AT_CMD_CR)
{
/* skip '\n' if we get "\r\n" */
}
else
{
if (server->cur_recv_len < sizeof(server->recv_buffer) - 1)
{
at_server_printf("%c%c", AT_CMD_CR, AT_CMD_LF);
}
else if (ch == AT_CMD_LF)
{
// skip the end sign check
}
else if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
{
if (server->cur_recv_len)
server->recv_buffer[server->cur_recv_len++] = ch;
if (ch == AT_CMD_CR || ch == AT_CMD_LF)
{
server->recv_buffer[--server->cur_recv_len] = 0;
at_server_printf("\b \b");
}
if (server->echo_mode)
at_server_printf("%c%c", AT_CMD_CR, AT_CMD_LF);
server->recv_buffer[server->cur_recv_len] = '\0';
result = AT_RESULT_FAILE;
if (at_cmd_get_name(server->recv_buffer, cur_cmd_name) == RT_EOK)
{
cur_cmd = at_find_cmd(cur_cmd_name);
if (cur_cmd)
{
cur_cmd_args = server->recv_buffer + strlen(cur_cmd_name);
result = at_cmd_process(cur_cmd, cur_cmd_args);
}
}
continue;
}
else if (ch == AT_CMD_NULL)
{
continue;
at_server_print_result(result);
server->cur_recv_len = 0;
}
else
{
if (server->echo_mode)
at_server_printf("%c", ch);
}
last_ch = ch;
}
else
{
at_server_printf("%c", ch);
/* server receive buffer overflow!!! */
server->cur_recv_len = 0;
}
}
server->recv_buffer[server->cur_recv_len++] = ch;
last_ch = ch;
if(!strstr(server->recv_buffer, server->end_mark))
{
continue;
}
if (at_cmd_get_name(server->recv_buffer, cur_cmd_name) < 0)
{
at_server_print_result(AT_RESULT_CMD_ERR);
goto __retry;
}
cur_cmd = at_find_cmd(cur_cmd_name);
if (!cur_cmd)
{
at_server_print_result(AT_RESULT_CMD_ERR);
goto __retry;
}
cur_cmd_args = server->recv_buffer + strlen(cur_cmd_name);
if (at_cmd_process(cur_cmd, cur_cmd_args) < 0)
{
goto __retry;
}
__retry:
rt_memset(server->recv_buffer, 0x00, AT_SERVER_RECV_BUFF_LEN);
server->cur_recv_len = 0;
}
}
@ -586,6 +564,7 @@ int at_server_init(void)
{
RT_ASSERT(at_server_local->device->type == RT_Device_Class_Char);
rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
/* using DMA mode first */
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_DMA_RX);
/* using interrupt mode when DMA mode not supported */
@ -594,8 +573,6 @@ int at_server_init(void)
open_result = rt_device_open(at_server_local->device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
}
RT_ASSERT(open_result == RT_EOK);
rt_device_set_rx_indicate(at_server_local->device, at_rx_ind);
}
else
{
@ -605,7 +582,6 @@ int at_server_init(void)
}
at_server_local->get_char = at_server_getchar;
rt_memcpy(at_server_local->end_mark, AT_CMD_END_MARK, sizeof(AT_CMD_END_MARK));
at_server_local->parser_entry = server_parser;
at_server_local->parser = rt_thread_create("at_svr",
@ -617,7 +593,6 @@ int at_server_init(void)
if (at_server_local->parser == RT_NULL)
{
result = -RT_ENOMEM;
goto __exit;
}
__exit:
@ -633,7 +608,16 @@ __exit:
{
if (at_server_local)
{
if (at_server_local->rx_notice)
{
rt_sem_delete(at_server_local->rx_notice);
}
if (at_server_local->device)
{
rt_device_close(at_server_local->device);
}
rt_free(at_server_local);
at_server_local = RT_NULL;
}
LOG_E("RT-Thread AT server (V%s) initialize failed(%d).", AT_SW_VERSION, result);

View File

@ -81,6 +81,8 @@ static const struct sal_socket_ops at_socket_ops =
NULL,
#endif
at_sendto,
NULL,
NULL,
at_recvfrom,
at_getsockopt,
at_setsockopt,
@ -88,6 +90,7 @@ static const struct sal_socket_ops at_socket_ops =
NULL,
NULL,
NULL,
NULL,
#ifdef SAL_USING_POSIX
at_poll,
#endif /* SAL_USING_POSIX */