[components][at] 优化AT组件,并解决内存泄露
1.优化at server endmark判断,支持自动识别'\r''\n'"\r\n"。 2.优化at_recvfrom,修复大数据量时sem多次释放造成的接收错误。 3.修复at组件中可能存在的内存泄露。 4.优化部分代码逻辑,减少冗余代码。
This commit is contained in:
parent
02eaf76d7b
commit
a8d5a645f2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue