[net][at] update AT component V1.3.0, change as follows:

- AT Socket feature supports multi-client connections;
- Fix `send data error, current socket (0) state (0) is error` issue when the socket is closed;
- Improve dirty data processing when AT device hard reset;
- Improve `at_obj_set_urc_table()` fucntion, Support for setting multiple URC tables;
- Improve RAW data print format;
This commit is contained in:
chenyong 2019-05-27 11:49:23 +08:00
parent 3d960cc178
commit b5ad12573f
6 changed files with 406 additions and 224 deletions

View File

@ -83,7 +83,7 @@ if RT_USING_AT
config AT_SW_VERSION_NUM config AT_SW_VERSION_NUM
hex hex
default 0x10200 default 0x10300
help help
sfotware module version number sfotware module version number

View File

@ -15,11 +15,15 @@
#include <sys/time.h> #include <sys/time.h>
#include <at_socket.h> #include <at_socket.h>
#include <at_device.h>
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
#include <dfs_poll.h> #include <dfs_poll.h>
#endif #endif
#include <arpa/inet.h>
#include <netdev.h>
#define LOG_TAG "at.skt" #define LOG_TAG "at.skt"
#include <at_log.h> #include <at_log.h>
@ -32,10 +36,6 @@
((unsigned char *)&addr)[2], \ ((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3] ((unsigned char *)&addr)[3]
#if !defined(AT_DEVICE_SOCKETS_NUM) || defined(AT_DEVICE_NOT_SELECTED)
#error The AT socket device is not selected, please select it through the env menuconfig.
#endif
/* The maximum number of sockets structure */ /* The maximum number of sockets structure */
#ifndef AT_SOCKETS_NUM #ifndef AT_SOCKETS_NUM
#define AT_SOCKETS_NUM AT_DEVICE_SOCKETS_NUM #define AT_SOCKETS_NUM AT_DEVICE_SOCKETS_NUM
@ -47,31 +47,41 @@ typedef enum {
AT_EVENT_ERROR, AT_EVENT_ERROR,
} at_event_t; } at_event_t;
/* the global array of available sockets */
static struct at_socket sockets[AT_SOCKETS_NUM] = { 0 }; /* the global of sockets list */
/* AT device socket options */ static rt_slist_t _socket_list = RT_SLIST_OBJECT_INIT(_socket_list);
static struct at_device_ops *at_dev_ops = RT_NULL;
struct at_socket *at_get_socket(int socket) struct at_socket *at_get_socket(int socket)
{ {
if (socket < 0 || socket >= AT_SOCKETS_NUM) rt_base_t level;
{ size_t list_num = 0;
return RT_NULL; rt_slist_t *node = RT_NULL;
} struct at_socket *at_sock = RT_NULL;
/* check socket structure valid or not */ level = rt_hw_interrupt_disable();
if (sockets[socket].magic != AT_SOCKET_MAGIC)
{
return RT_NULL;
}
return &sockets[socket]; rt_slist_for_each(node, &_socket_list)
{
if (socket == (list_num++))
{
at_sock = rt_slist_entry(node, struct at_socket, list);
if (at_sock && at_sock->magic == AT_SOCKET_MAGIC)
{
rt_hw_interrupt_enable(level);
return at_sock;
}
}
}
rt_hw_interrupt_enable(level);
return RT_NULL;
} }
/* get a block to the AT socket receive list*/ /* get a block to the AT socket receive list*/
static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length) static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length)
{ {
at_recv_pkt_t pkt; at_recv_pkt_t pkt = RT_NULL;
pkt = (at_recv_pkt_t) rt_calloc(1, sizeof(struct at_recv_pkt)); pkt = (at_recv_pkt_t) rt_calloc(1, sizeof(struct at_recv_pkt));
if (pkt == RT_NULL) if (pkt == RT_NULL)
@ -92,11 +102,13 @@ static size_t at_recvpkt_put(rt_slist_t *rlist, const char *ptr, size_t length)
/* delete and free all receive buffer list */ /* delete and free all receive buffer list */
static int at_recvpkt_all_delete(rt_slist_t *rlist) static int at_recvpkt_all_delete(rt_slist_t *rlist)
{ {
at_recv_pkt_t pkt; at_recv_pkt_t pkt = RT_NULL;
rt_slist_t *node; rt_slist_t *node = RT_NULL;
if(rt_slist_isempty(rlist)) if (rt_slist_isempty(rlist))
{
return 0; return 0;
}
for(node = rt_slist_first(rlist); node; node = rt_slist_next(node)) for(node = rt_slist_first(rlist); node; node = rt_slist_next(node))
{ {
@ -105,7 +117,7 @@ static int at_recvpkt_all_delete(rt_slist_t *rlist)
{ {
rt_free(pkt->buff); rt_free(pkt->buff);
} }
if(pkt) if (pkt)
{ {
rt_free(pkt); rt_free(pkt);
pkt = RT_NULL; pkt = RT_NULL;
@ -118,14 +130,16 @@ static int at_recvpkt_all_delete(rt_slist_t *rlist)
/* delete and free specified list block */ /* delete and free specified list block */
static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node) static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node)
{ {
at_recv_pkt_t pkt; at_recv_pkt_t pkt = RT_NULL;
if(rt_slist_isempty(rlist)) if (rt_slist_isempty(rlist))
{
return 0; return 0;
}
rt_slist_remove(rlist, node); rt_slist_remove(rlist, node);
pkt= rt_slist_entry(node, struct at_recv_pkt, list); pkt = rt_slist_entry(node, struct at_recv_pkt, list);
if (pkt->buff) if (pkt->buff)
{ {
rt_free(pkt->buff); rt_free(pkt->buff);
@ -139,15 +153,17 @@ static int at_recvpkt_node_delete(rt_slist_t *rlist, rt_slist_t *node)
return 0; return 0;
} }
/* get a block from AT socket receive list */ /* get a block from AT socket receive buffer list */
static size_t at_recvpkt_get(rt_slist_t *rlist, char *mem, size_t len) static size_t at_recvpkt_get(rt_slist_t *rlist, char *mem, size_t len)
{ {
rt_slist_t *node; rt_slist_t *node = RT_NULL;
at_recv_pkt_t pkt; at_recv_pkt_t pkt = RT_NULL;
size_t content_pos = 0, page_pos = 0; size_t content_pos = 0, page_pos = 0;
if(rt_slist_isempty(rlist)) if (rt_slist_isempty(rlist))
{
return 0; return 0;
}
for (node = rt_slist_first(rlist); node; node = rt_slist_next(node)) for (node = rt_slist_first(rlist); node; node = rt_slist_next(node))
{ {
@ -191,7 +207,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
rt_wqueue_wakeup(&sock->wait_head, (void*) POLLOUT); rt_wqueue_wakeup(&sock->wait_head, (void*) POLLOUT);
#endif #endif
} }
else if (sock->sendevent) else if (sock->sendevent)
{ {
@ -208,7 +223,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
rt_wqueue_wakeup(&sock->wait_head, (void*) POLLIN); rt_wqueue_wakeup(&sock->wait_head, (void*) POLLIN);
#endif #endif
} }
else if (sock->rcvevent) else if (sock->rcvevent)
{ {
@ -225,7 +239,6 @@ static void at_do_event_changes(struct at_socket *sock, at_event_t event, rt_boo
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
rt_wqueue_wakeup(&sock->wait_head, (void*) POLLERR); rt_wqueue_wakeup(&sock->wait_head, (void*) POLLERR);
#endif #endif
} }
else if (sock->errevent) else if (sock->errevent)
{ {
@ -262,20 +275,20 @@ static void at_do_event_clean(struct at_socket *sock, at_event_t event)
} }
} }
static struct at_socket *alloc_socket(void) static struct at_socket *alloc_socket_by_device(struct at_device *device)
{ {
static rt_mutex_t at_slock = RT_NULL; static rt_mutex_t at_slock = RT_NULL;
char name[RT_NAME_MAX]; struct at_socket *sock = RT_NULL;
struct at_socket *sock; char name[RT_NAME_MAX] = {0};
int idx; int idx = 0;
if(at_slock == RT_NULL) if (at_slock == RT_NULL)
{ {
/* create AT socket lock */ /* create AT socket lock */
at_slock = rt_mutex_create("at_s", RT_IPC_FLAG_FIFO); at_slock = rt_mutex_create("at_slock", RT_IPC_FLAG_FIFO);
if (at_slock == RT_NULL) if (at_slock == RT_NULL)
{ {
LOG_E("No memory for AT socket lock!"); LOG_E("No memory for socket allocation lock!");
return RT_NULL; return RT_NULL;
} }
} }
@ -283,34 +296,58 @@ static struct at_socket *alloc_socket(void)
rt_mutex_take(at_slock, RT_WAITING_FOREVER); rt_mutex_take(at_slock, RT_WAITING_FOREVER);
/* find an empty at socket entry */ /* find an empty at socket entry */
for (idx = 0; idx < AT_SOCKETS_NUM && sockets[idx].magic; idx++); for (idx = 0; idx < device->class->socket_num && device->sockets[idx].magic; idx++);
/* can't find an empty protocol family entry */ /* can't find an empty protocol family entry */
if (idx == AT_SOCKETS_NUM) if (idx == device->class->socket_num)
{ {
goto __err; goto __err;
} }
sock = &(sockets[idx]); /* add device socket to global socket list */
{
rt_base_t level;
level = rt_hw_interrupt_disable();
rt_slist_init(&(device->sockets[idx].list));
rt_slist_append(&_socket_list, &(device->sockets[idx].list));
rt_hw_interrupt_enable(level);
}
sock = &(device->sockets[idx]);
/* the socket descriptor is the number of sockte lists */
sock->socket = rt_slist_len(&_socket_list) - 1;
/* the socket operations is the specify operations of the device */
sock->ops = device->class->socket_ops;
/* the user-data is the at device socket descriptor */
sock->user_data = (void *) idx;
sock->device = (void *) device;
sock->magic = AT_SOCKET_MAGIC; sock->magic = AT_SOCKET_MAGIC;
sock->socket = idx;
sock->state = AT_SOCKET_NONE; sock->state = AT_SOCKET_NONE;
sock->rcvevent = RT_NULL; sock->rcvevent = RT_NULL;
sock->sendevent = RT_NULL; sock->sendevent = RT_NULL;
sock->errevent = RT_NULL; sock->errevent = RT_NULL;
rt_slist_init(&sock->recvpkt_list); rt_slist_init(&sock->recvpkt_list);
#ifdef SAL_USING_POSIX
rt_wqueue_init(&sock->wait_head);
#endif
rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx); rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx);
/* create AT socket receive mailbox */ /* create AT socket receive mailbox */
if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL) if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL)
{ {
LOG_E("No memory socket receive notic semaphore create.");
goto __err; goto __err;
} }
rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_sr", idx); rt_snprintf(name, RT_NAME_MAX, "%s%d", "at_skt", idx);
/* create AT socket receive ring buffer lock */ /* create AT socket receive ring buffer lock */
if((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL) if((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL)
{ {
LOG_E("No memory for socket receive mutex create.");
rt_sem_delete(sock->recv_notice);
goto __err; goto __err;
} }
@ -322,13 +359,42 @@ __err:
return RT_NULL; return RT_NULL;
} }
static struct at_socket *alloc_socket(int domain)
{
extern struct netdev *netdev_default;
struct netdev *netdev = RT_NULL;
struct at_device *device = RT_NULL;
if (netdev_default && netdev_is_up(netdev_default))
{
netdev = netdev_default;
}
else
{
/* get network interface device by protocol family */
netdev = netdev_get_by_family(domain);
if (netdev == RT_NULL)
{
return RT_NULL;
}
}
device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
if (device == RT_NULL)
{
return RT_NULL;
}
return alloc_socket_by_device(device);
}
int at_socket(int domain, int type, int protocol) int at_socket(int domain, int type, int protocol)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
enum at_socket_type socket_type; enum at_socket_type socket_type;
/* check socket family protocol */ /* check socket family protocol */
RT_ASSERT(domain == AF_AT||domain == AF_INET); RT_ASSERT(domain == AF_AT || domain == AF_INET);
//TODO check protocol //TODO check protocol
@ -348,17 +414,13 @@ int at_socket(int domain, int type, int protocol)
} }
/* allocate and initialize a new AT socket */ /* allocate and initialize a new AT socket */
sock = alloc_socket(); sock = alloc_socket(domain);
if(sock == RT_NULL) if (sock == RT_NULL)
{ {
LOG_E("Allocate a new AT socket failed!"); return -1;
return RT_NULL;
} }
sock->type = socket_type; sock->type = socket_type;
sock->state = AT_SOCKET_OPEN;
#ifdef SAL_USING_POSIX
rt_wqueue_init(&sock->wait_head);
#endif
return sock->socket; return sock->socket;
} }
@ -380,21 +442,41 @@ static int free_socket(struct at_socket *sock)
at_recvpkt_all_delete(&sock->recvpkt_list); at_recvpkt_all_delete(&sock->recvpkt_list);
} }
memset(sock, 0x00, sizeof(struct at_socket)); /* delect socket from socket list */
{
rt_base_t level;
int list_num = 0;
rt_slist_t *node = RT_NULL;
struct at_socket *at_sock = RT_NULL;
level = rt_hw_interrupt_disable();
rt_slist_for_each(node, &_socket_list)
{
if (sock->socket == (list_num++))
{
at_sock = rt_slist_entry(node, struct at_socket, list);
if (at_sock)
{
rt_slist_remove(&_socket_list, &at_sock->list);
break;
}
}
}
rt_hw_interrupt_enable(level);
}
rt_memset(sock, 0x00, sizeof(struct at_socket));
return 0; return 0;
} }
int at_closesocket(int socket) int at_closesocket(int socket)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
enum at_socket_state last_state; enum at_socket_state last_state;
if (at_dev_ops == RT_NULL)
{
return -1;
}
/* deal with TCP server actively disconnect */ /* deal with TCP server actively disconnect */
rt_thread_delay(rt_tick_from_millisecond(100)); rt_thread_delay(rt_tick_from_millisecond(100));
@ -409,9 +491,9 @@ int at_closesocket(int socket)
/* the rt_at_socket_close is need some time, so change state in advance */ /* the rt_at_socket_close is need some time, so change state in advance */
sock->state = AT_SOCKET_CLOSED; sock->state = AT_SOCKET_CLOSED;
if (last_state == AT_SOCKET_CONNECT) if (last_state != AT_SOCKET_CLOSED)
{ {
if (at_dev_ops->at_closesocket(socket) != 0) if (sock->ops->at_closesocket(sock) != 0)
{ {
free_socket(sock); free_socket(sock);
return -1; return -1;
@ -424,12 +506,8 @@ int at_closesocket(int socket)
int at_shutdown(int socket, int how) int at_shutdown(int socket, int how)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
enum at_socket_state last_state;
if (at_dev_ops == RT_NULL)
{
return -1;
}
sock = at_get_socket(socket); sock = at_get_socket(socket);
if (sock == RT_NULL) if (sock == RT_NULL)
@ -437,9 +515,14 @@ int at_shutdown(int socket, int how)
return -1; return -1;
} }
if (sock->state == AT_SOCKET_CONNECT) last_state = sock->state;
/* the rt_at_socket_close is need some time, so change state in advance */
sock->state = AT_SOCKET_CLOSED;
if (last_state != AT_SOCKET_CLOSED)
{ {
if (at_dev_ops->at_closesocket(socket) != 0) if (sock->ops->at_closesocket(sock) != 0)
{ {
free_socket(sock); free_socket(sock);
return -1; return -1;
@ -450,17 +533,6 @@ int at_shutdown(int socket, int how)
return 0; return 0;
} }
int at_bind(int socket, const struct sockaddr *name, socklen_t namelen)
{
if (at_get_socket(socket) == RT_NULL)
{
return -1;
}
return 0;
}
/* get IP address and port by socketaddr structure information */ /* get IP address and port by socketaddr structure information */
static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port) static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *addr, uint16_t *port)
{ {
@ -479,6 +551,59 @@ static int socketaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t
return 0; return 0;
} }
int at_bind(int socket, const struct sockaddr *name, socklen_t namelen)
{
struct at_socket *sock = RT_NULL;
struct at_device *device = RT_NULL;
ip_addr_t input_ipaddr, local_ipaddr;
uint16_t port = 0;
sock = at_get_socket(socket);
if (sock == RT_NULL)
{
return -1;
}
/* get current device ip address */
device = (struct at_device *) sock->device;
ip_addr_copy(local_ipaddr, device->netdev->ip_addr);
/* prase ip address and port from sockaddr structure */
socketaddr_to_ipaddr_port(name, &input_ipaddr, &port);
/* input ip address is different from device ip address */
if (ip_addr_cmp(&input_ipaddr, &local_ipaddr) == 0)
{
struct at_socket *new_sock = RT_NULL;
struct at_device *new_device = RT_NULL;
enum at_socket_type type = sock->type;
/* close old socket */
if (at_closesocket(socket) < 0)
{
return -1;
}
extern struct at_device *at_device_get_by_ipaddr(ip_addr_t *ip_addr);
new_device = at_device_get_by_ipaddr(&input_ipaddr);
if (new_device == RT_NULL)
{
return -1;
}
/* allocate new socket */
new_sock = alloc_socket_by_device(new_device);
if (new_sock == RT_NULL)
{
return -1;
}
new_sock->type = type;
new_sock->state = AT_SOCKET_OPEN;
}
return 0;
}
/* ipaddr structure change to IP address */ /* ipaddr structure change to IP address */
static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr) static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
{ {
@ -490,17 +615,16 @@ static int ipaddr_to_ipstr(const struct sockaddr *sockaddr, char *ipstr)
return 0; return 0;
} }
static void at_recv_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz) static void at_recv_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
{ {
struct at_socket *sock;
RT_ASSERT(buff); RT_ASSERT(buff);
RT_ASSERT(bfsz);
RT_ASSERT(event == AT_SOCKET_EVT_RECV); RT_ASSERT(event == AT_SOCKET_EVT_RECV);
sock = at_get_socket(socket); /* check the socket object status */
if (sock == RT_NULL) if (sock->magic != AT_SOCKET_MAGIC)
return ; {
return;
}
/* put receive buffer to receiver packet list */ /* put receive buffer to receiver packet list */
rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER); rt_mutex_take(sock->recv_lock, RT_WAITING_FOREVER);
@ -512,15 +636,16 @@ static void at_recv_notice_cb(int socket, at_socket_evt_t event, const char *buf
at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE); at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
} }
static void at_closed_notice_cb(int socket, at_socket_evt_t event, const char *buff, size_t bfsz) static void at_closed_notice_cb(struct at_socket *sock, at_socket_evt_t event, const char *buff, size_t bfsz)
{ {
struct at_socket *sock;
RT_ASSERT(event == AT_SOCKET_EVT_CLOSED); RT_ASSERT(event == AT_SOCKET_EVT_CLOSED);
if ((sock = at_get_socket(socket)) == RT_NULL) /* check the socket object status */
return ; if (sock->magic != AT_SOCKET_MAGIC)
{
return;
}
at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE); at_do_event_changes(sock, AT_EVENT_RECV, RT_TRUE);
at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE); at_do_event_changes(sock, AT_EVENT_ERROR, RT_TRUE);
@ -530,17 +655,12 @@ static void at_closed_notice_cb(int socket, at_socket_evt_t event, const char *b
int at_connect(int socket, const struct sockaddr *name, socklen_t namelen) int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
ip_addr_t remote_addr; ip_addr_t remote_addr;
uint16_t remote_port; uint16_t remote_port = 0;
char ipstr[16] = { 0 }; char ipstr[16] = { 0 };
int result = 0; int result = 0;
if (at_dev_ops == RT_NULL)
{
return -1;
}
sock = at_get_socket(socket); sock = at_get_socket(socket);
if (sock == RT_NULL) if (sock == RT_NULL)
{ {
@ -548,7 +668,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
goto __exit; goto __exit;
} }
if (sock->state != AT_SOCKET_NONE) if (sock->state != AT_SOCKET_OPEN)
{ {
LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state); LOG_E("Socket(%d) connect state is %d.", sock->socket, sock->state);
result = -1; result = -1;
@ -559,7 +679,7 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
socketaddr_to_ipaddr_port(name, &remote_addr, &remote_port); socketaddr_to_ipaddr_port(name, &remote_addr, &remote_port);
ipaddr_to_ipstr(name, ipstr); ipaddr_to_ipstr(name, ipstr);
if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
{ {
result = -1; result = -1;
goto __exit; goto __exit;
@ -568,8 +688,8 @@ int at_connect(int socket, const struct sockaddr *name, socklen_t namelen)
sock->state = AT_SOCKET_CONNECT; sock->state = AT_SOCKET_CONNECT;
/* set AT socket receive data callback function */ /* set AT socket receive data callback function */
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
__exit: __exit:
@ -591,9 +711,8 @@ __exit:
int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
int timeout; int timeout, result = 0;
int result = 0;
size_t recv_len = 0; size_t recv_len = 0;
if (mem == RT_NULL || len == 0) if (mem == RT_NULL || len == 0)
@ -602,11 +721,6 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
return -1; return -1;
} }
if (at_dev_ops == RT_NULL)
{
return -1;
}
sock = at_get_socket(socket); sock = at_get_socket(socket);
if (sock == RT_NULL) if (sock == RT_NULL)
{ {
@ -615,24 +729,24 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
} }
/* if the socket type is UDP, nead to connect socket first */ /* if the socket type is UDP, nead to connect socket first */
if (from && sock->type == AT_SOCKET_UDP && sock->state == AT_SOCKET_NONE) if (from && sock->type == AT_SOCKET_UDP && sock->state == AT_SOCKET_OPEN)
{ {
ip_addr_t remote_addr; ip_addr_t remote_addr;
uint16_t remote_port; uint16_t remote_port = 0;
char ipstr[16] = { 0 }; char ipstr[16] = { 0 };
socketaddr_to_ipaddr_port(from, &remote_addr, &remote_port); socketaddr_to_ipaddr_port(from, &remote_addr, &remote_port);
ipaddr_to_ipstr(from, ipstr); ipaddr_to_ipstr(from, ipstr);
if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
{ {
result = -1; result = -1;
goto __exit; goto __exit;
} }
sock->state = AT_SOCKET_CONNECT; sock->state = AT_SOCKET_CONNECT;
/* set AT socket receive data callback function */ /* set AT socket receive data callback function */
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
} }
/* receive packet list last transmission of remaining data */ /* receive packet list last transmission of remaining data */
@ -650,7 +764,7 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
result = 0; result = 0;
goto __exit; goto __exit;
} }
else if (sock->state != AT_SOCKET_CONNECT) 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); LOG_E("received data error, current socket (%d) state (%d) is error.", socket, sock->state);
result = -1; result = -1;
@ -664,7 +778,7 @@ int at_recvfrom(int socket, void *mem, size_t len, int flags, struct sockaddr *f
} }
/* set AT socket receive timeout */ /* set AT socket receive timeout */
if((timeout = sock->recv_timeout) == 0) if ((timeout = sock->recv_timeout) == 0)
{ {
timeout = RT_WAITING_FOREVER; timeout = RT_WAITING_FOREVER;
} }
@ -739,15 +853,9 @@ int at_recv(int s, void *mem, size_t len, int flags)
int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen) int at_sendto(int socket, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)
{ {
struct at_socket *sock; struct at_socket *sock = RT_NULL;
int len, result = 0; int len, result = 0;
if (at_dev_ops == RT_NULL)
{
result = -1;
goto __exit;
}
if (data == RT_NULL || size == 0) if (data == RT_NULL || size == 0)
{ {
LOG_E("AT sendto input data or size error!"); LOG_E("AT sendto input data or size error!");
@ -765,14 +873,19 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct
switch (sock->type) switch (sock->type)
{ {
case AT_SOCKET_TCP: case AT_SOCKET_TCP:
if (sock->state != AT_SOCKET_CONNECT) if (sock->state == AT_SOCKET_CLOSED)
{
result = 0;
goto __exit;
}
else if (sock->state != AT_SOCKET_CONNECT && sock->state != AT_SOCKET_OPEN)
{ {
LOG_E("send data error, current socket (%d) state (%d) is error.", socket, sock->state); LOG_E("send data error, current socket (%d) state (%d) is error.", socket, sock->state);
result = -1; result = -1;
goto __exit; goto __exit;
} }
if ((len = at_dev_ops->at_send(sock->socket, (const char *) data, size, sock->type)) < 0) if ((len = sock->ops->at_send(sock, (const char *) data, size, sock->type)) < 0)
{ {
result = -1; result = -1;
goto __exit; goto __exit;
@ -780,27 +893,27 @@ int at_sendto(int socket, const void *data, size_t size, int flags, const struct
break; break;
case AT_SOCKET_UDP: case AT_SOCKET_UDP:
if (to && sock->state == AT_SOCKET_NONE) if (to && sock->state == AT_SOCKET_OPEN)
{ {
ip_addr_t remote_addr; ip_addr_t remote_addr;
uint16_t remote_port; uint16_t remote_port = 0;
char ipstr[16] = { 0 }; char ipstr[16] = { 0 };
socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port); socketaddr_to_ipaddr_port(to, &remote_addr, &remote_port);
ipaddr_to_ipstr(to, ipstr); ipaddr_to_ipstr(to, ipstr);
if (at_dev_ops->at_connect(socket, ipstr, remote_port, sock->type, RT_TRUE) < 0) if (sock->ops->at_connect(sock, ipstr, remote_port, sock->type, RT_TRUE) < 0)
{ {
result = -1; result = -1;
goto __exit; goto __exit;
} }
sock->state = AT_SOCKET_CONNECT; sock->state = AT_SOCKET_CONNECT;
/* set AT socket receive data callback function */ /* set AT socket receive data callback function */
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_RECV, at_recv_notice_cb);
at_dev_ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb); sock->ops->at_set_event_cb(AT_SOCKET_EVT_CLOSED, at_closed_notice_cb);
} }
if ((len = at_dev_ops->at_send(sock->socket, (char *) data, size, sock->type)) < 0) if ((len = sock->ops->at_send(sock, (char *) data, size, sock->type)) < 0)
{ {
result = -1; result = -1;
goto __exit; goto __exit;
@ -973,6 +1086,7 @@ static uint32_t ipstr_to_u32(char *ipstr)
struct hostent *at_gethostbyname(const char *name) struct hostent *at_gethostbyname(const char *name)
{ {
struct at_device *device = RT_NULL;
ip_addr_t addr; ip_addr_t addr;
char ipstr[16] = { 0 }; char ipstr[16] = { 0 };
/* buffer variables for at_gethostbyname() */ /* buffer variables for at_gethostbyname() */
@ -989,7 +1103,8 @@ struct hostent *at_gethostbyname(const char *name)
return RT_NULL; return RT_NULL;
} }
if (at_dev_ops == RT_NULL) device = at_device_get_first_initialized();
if (device == RT_NULL)
{ {
return RT_NULL; return RT_NULL;
} }
@ -998,7 +1113,7 @@ struct hostent *at_gethostbyname(const char *name)
if (idx < strlen(name)) if (idx < strlen(name))
{ {
if (at_dev_ops->at_domain_resolve(name, ipstr) < 0) if (device->class->socket_ops->at_domain_resolve(name, ipstr) < 0)
{ {
return RT_NULL; return RT_NULL;
} }
@ -1042,6 +1157,7 @@ int at_getaddrinfo(const char *nodename, const char *servname,
size_t total_size = 0; size_t total_size = 0;
size_t namelen = 0; size_t namelen = 0;
int ai_family = 0; int ai_family = 0;
struct at_device *device = RT_NULL;
if (res == RT_NULL) if (res == RT_NULL)
{ {
@ -1049,7 +1165,8 @@ int at_getaddrinfo(const char *nodename, const char *servname,
} }
*res = RT_NULL; *res = RT_NULL;
if (at_dev_ops == RT_NULL) device = at_device_get_first_initialized();
if (device == RT_NULL)
{ {
return EAI_FAIL; return EAI_FAIL;
} }
@ -1103,7 +1220,7 @@ int at_getaddrinfo(const char *nodename, const char *servname,
if(idx < strlen(nodename)) if(idx < strlen(nodename))
{ {
if (at_dev_ops->at_domain_resolve((char *) nodename, ip_str) != 0) if (device->class->socket_ops->at_domain_resolve((char *) nodename, ip_str) != 0)
{ {
return EAI_FAIL; return EAI_FAIL;
} }
@ -1201,15 +1318,4 @@ void at_freeaddrinfo(struct addrinfo *ai)
} }
} }
void at_socket_device_register(const struct at_device_ops *ops)
{
RT_ASSERT(ops);
RT_ASSERT(ops->at_connect);
RT_ASSERT(ops->at_closesocket);
RT_ASSERT(ops->at_send);
RT_ASSERT(ops->at_domain_resolve);
RT_ASSERT(ops->at_set_event_cb);
at_dev_ops = (struct at_device_ops *) ops;
}
#endif /* AT_USING_SOCKET */ #endif /* AT_USING_SOCKET */

View File

@ -36,6 +36,7 @@ extern "C" {
enum at_socket_state enum at_socket_state
{ {
AT_SOCKET_NONE, AT_SOCKET_NONE,
AT_SOCKET_OPEN,
AT_SOCKET_LISTEN, AT_SOCKET_LISTEN,
AT_SOCKET_CONNECT, AT_SOCKET_CONNECT,
AT_SOCKET_CLOSED AT_SOCKET_CLOSED
@ -54,18 +55,19 @@ typedef enum
AT_SOCKET_EVT_CLOSED, AT_SOCKET_EVT_CLOSED,
} at_socket_evt_t; } at_socket_evt_t;
typedef void (*at_evt_cb_t)(int socket, at_socket_evt_t event, const char *buff, size_t bfsz);
struct at_socket; struct at_socket;
typedef void (*at_evt_cb_t)(struct at_socket *socket, at_socket_evt_t event, const char *buff, size_t bfsz);
/* A callback prototype to inform about events for AT socket */ /* A callback prototype to inform about events for AT socket */
typedef void (* at_socket_callback)(struct at_socket *conn, int event, uint16_t len); typedef void (* at_socket_callback)(struct at_socket *conn, int event, uint16_t len);
/* AT device socket options function */ /* AT socket operations function */
struct at_device_ops struct at_socket_ops
{ {
int (*at_connect)(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client); int (*at_connect)(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client);
int (*at_closesocket)(int socket); int (*at_closesocket)(struct at_socket *socket);
int (*at_send)(int socket, const char *buff, size_t bfsz, enum at_socket_type type); int (*at_send)(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type);
int (*at_domain_resolve)(const char *name, char ip[16]); int (*at_domain_resolve)(const char *name, char ip[16]);
void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb); void (*at_set_event_cb)(at_socket_evt_t event, at_evt_cb_t cb);
}; };
@ -86,10 +88,14 @@ struct at_socket
uint32_t magic; uint32_t magic;
int socket; int socket;
/* device releated information for the socket */
void *device;
/* type of the AT socket (TCP, UDP or RAW) */ /* type of the AT socket (TCP, UDP or RAW) */
enum at_socket_type type; enum at_socket_type type;
/* current state of the AT socket */ /* current state of the AT socket */
enum at_socket_state state; enum at_socket_state state;
/* sockets operations */
const struct at_socket_ops *ops;
/* receive semaphore, received data release semaphore */ /* receive semaphore, received data release semaphore */
rt_sem_t recv_notice; rt_sem_t recv_notice;
rt_mutex_t recv_lock; rt_mutex_t recv_lock;
@ -111,6 +117,10 @@ struct at_socket
#ifdef SAL_USING_POSIX #ifdef SAL_USING_POSIX
rt_wqueue_t wait_head; rt_wqueue_t wait_head;
#endif #endif
rt_slist_t list;
/* user-specific data */
void *user_data;
}; };
int at_socket(int domain, int type, int protocol); int at_socket(int domain, int type, int protocol);
@ -129,7 +139,6 @@ int at_getaddrinfo(const char *nodename, const char *servname, const struct addr
void at_freeaddrinfo(struct addrinfo *ai); void at_freeaddrinfo(struct addrinfo *ai);
struct at_socket *at_get_socket(int socket); struct at_socket *at_get_socket(int socket);
void at_socket_device_register(const struct at_device_ops *ops);
#ifndef RT_USING_SAL #ifndef RT_USING_SAL

View File

@ -18,7 +18,7 @@
extern "C" { extern "C" {
#endif #endif
#define AT_SW_VERSION "1.2.0" #define AT_SW_VERSION "1.3.0"
#define AT_CMD_NAME_LEN 16 #define AT_CMD_NAME_LEN 16
#define AT_END_MARK_LEN 4 #define AT_END_MARK_LEN 4
@ -124,9 +124,11 @@ struct at_response
{ {
/* response buffer */ /* response buffer */
char *buf; char *buf;
/* the maximum response buffer size */ /* the maximum response buffer size, it set by `at_create_resp()` function */
rt_size_t buf_size; rt_size_t buf_size;
/* the number of setting response lines /* the length of current response buffer */
rt_size_t buf_len;
/* the number of setting response lines, it set by `at_create_resp()` function
* == 0: the response data will auto return when received 'OK' or 'ERROR' * == 0: the response data will auto return when received 'OK' or 'ERROR'
* != 0: the response data will return when received setting lines number data */ * != 0: the response data will return when received setting lines number data */
rt_size_t line_num; rt_size_t line_num;
@ -138,15 +140,24 @@ struct at_response
typedef struct at_response *at_response_t; typedef struct at_response *at_response_t;
struct at_client;
/* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */ /* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */
struct at_urc struct at_urc
{ {
const char *cmd_prefix; const char *cmd_prefix;
const char *cmd_suffix; const char *cmd_suffix;
void (*func)(const char *data, rt_size_t size); void (*func)(struct at_client *client, const char *data, rt_size_t size);
}; };
typedef struct at_urc *at_urc_t; typedef struct at_urc *at_urc_t;
struct at_urc_table
{
size_t urc_size;
const struct at_urc *urc;
};
typedef struct at_urc *at_urc_table_t;
struct at_client struct at_client
{ {
rt_device_t device; rt_device_t device;
@ -154,9 +165,12 @@ struct at_client
at_status_t status; at_status_t status;
char end_sign; char end_sign;
char *recv_buffer; /* the current received one line data buffer */
char *recv_line_buf;
/* The length of the currently received one line data */
rt_size_t recv_line_len;
/* The maximum supported receive data length */
rt_size_t recv_bufsz; rt_size_t recv_bufsz;
rt_size_t cur_recv_len;
rt_sem_t rx_notice; rt_sem_t rx_notice;
rt_mutex_t lock; rt_mutex_t lock;
@ -164,7 +178,7 @@ struct at_client
rt_sem_t resp_notice; rt_sem_t resp_notice;
at_resp_status_t resp_status; at_resp_status_t resp_status;
const struct at_urc *urc_table; struct at_urc_table *urc_table;
rt_size_t urc_table_size; rt_size_t urc_table_size;
rt_thread_t parser; rt_thread_t parser;
@ -207,7 +221,7 @@ rt_size_t at_client_obj_recv(at_client_t client, char *buf, rt_size_t size, rt_i
void at_obj_set_end_sign(at_client_t client, char ch); void at_obj_set_end_sign(at_client_t client, char ch);
/* Set URC(Unsolicited Result Code) table */ /* Set URC(Unsolicited Result Code) table */
void at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size); int at_obj_set_urc_table(at_client_t client, const struct at_urc * table, rt_size_t size);
/* AT client send commands to AT server and waiter response */ /* AT client send commands to AT server and waiter response */
int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr, ...); int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr, ...);

View File

@ -301,13 +301,18 @@ int at_obj_exec_cmd(at_client_t client, at_response_t resp, const char *cmd_expr
client->resp_status = AT_RESP_OK; client->resp_status = AT_RESP_OK;
client->resp = resp; client->resp = resp;
if (resp != RT_NULL)
{
resp->buf_len = 0;
resp->line_counts = 0;
}
va_start(args, cmd_expr); va_start(args, cmd_expr);
at_vprintfln(client->device, cmd_expr, args); at_vprintfln(client->device, cmd_expr, args);
va_end(args); va_end(args);
if (resp != RT_NULL) if (resp != RT_NULL)
{ {
resp->line_counts = 0;
if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK) if (rt_sem_take(client->resp_notice, resp->timeout) != RT_EOK)
{ {
cmd = at_get_last_cmd(&cmd_size); cmd = at_get_last_cmd(&cmd_size);
@ -348,17 +353,18 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
rt_err_t result = RT_EOK; rt_err_t result = RT_EOK;
at_response_t resp = RT_NULL; at_response_t resp = RT_NULL;
rt_tick_t start_time = 0; rt_tick_t start_time = 0;
char *client_name = client->device->parent.name;
if (client == RT_NULL) if (client == RT_NULL)
{ {
LOG_E("input AT Client object is NULL, please create or get AT Client object!"); LOG_E("input AT client object is NULL, please create or get AT Client object!");
return -RT_ERROR; return -RT_ERROR;
} }
resp = at_create_resp(16, 0, rt_tick_from_millisecond(500)); resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
if (resp == RT_NULL) if (resp == RT_NULL)
{ {
LOG_E("No memory for response object!"); LOG_E("no memory for AT client(%s) response object.", client_name);
return -RT_ENOMEM; return -RT_ENOMEM;
} }
@ -372,12 +378,13 @@ int at_client_obj_wait_connect(at_client_t client, rt_uint32_t timeout)
/* Check whether it is timeout */ /* Check whether it is timeout */
if (rt_tick_get() - start_time > rt_tick_from_millisecond(timeout)) if (rt_tick_get() - start_time > rt_tick_from_millisecond(timeout))
{ {
LOG_E("wait connect timeout (%d millisecond)!", timeout); LOG_E("wait AT client(%s) connect timeout(%d tick).", client_name, timeout);
result = -RT_ETIMEOUT; result = -RT_ETIMEOUT;
break; break;
} }
/* Check whether it is already connected */ /* Check whether it is already connected */
resp->buf_len = 0;
resp->line_counts = 0; resp->line_counts = 0;
rt_device_write(client->device, 0, "AT\r\n", 4); rt_device_write(client->device, 0, "AT\r\n", 4);
@ -417,7 +424,7 @@ rt_size_t at_client_obj_send(at_client_t client, const char *buf, rt_size_t size
} }
#ifdef AT_PRINT_RAW_CMD #ifdef AT_PRINT_RAW_CMD
at_print_raw_cmd("send", buf, size); at_print_raw_cmd("sendline", buf, size);
#endif #endif
return rt_device_write(client->device, 0, buf, size); return rt_device_write(client->device, 0, buf, size);
@ -518,14 +525,14 @@ void at_obj_set_end_sign(at_client_t client, char ch)
* @param table URC table * @param table URC table
* @param size table size * @param size table size
*/ */
void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz) int at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt_size_t table_sz)
{ {
rt_size_t idx; rt_size_t idx;
if (client == RT_NULL) if (client == RT_NULL)
{ {
LOG_E("input AT Client object is NULL, please create or get AT Client object!"); LOG_E("input AT Client object is NULL, please create or get AT Client object!");
return; return -RT_ERROR;
} }
for (idx = 0; idx < table_sz; idx++) for (idx = 0; idx < table_sz; idx++)
@ -534,8 +541,47 @@ void at_obj_set_urc_table(at_client_t client, const struct at_urc *urc_table, rt
RT_ASSERT(urc_table[idx].cmd_suffix); RT_ASSERT(urc_table[idx].cmd_suffix);
} }
client->urc_table = urc_table; if (client->urc_table_size == 0)
client->urc_table_size = table_sz; {
client->urc_table = (struct at_urc_table *) rt_calloc(1, sizeof(struct at_urc_table));
if (client->urc_table == RT_NULL)
{
return -RT_ENOMEM;
}
client->urc_table[0].urc = urc_table;
client->urc_table[0].urc_size = table_sz;
client->urc_table_size++;
}
else
{
struct at_urc_table *old_urc_table = RT_NULL;
size_t old_table_size = client->urc_table_size * sizeof(struct at_urc_table);
old_urc_table = (struct at_urc_table *) rt_malloc(old_table_size);
if (old_urc_table == RT_NULL)
{
return -RT_ENOMEM;
}
rt_memcpy(old_urc_table, client->urc_table, old_table_size);
/* realloc urc table space */
client->urc_table = (struct at_urc_table *) rt_realloc(client->urc_table,
old_table_size + sizeof(struct at_urc_table));
if (client->urc_table == RT_NULL)
{
rt_free(old_urc_table);
return -RT_ENOMEM;
}
rt_memcpy(client->urc_table, old_urc_table, old_table_size);
client->urc_table[client->urc_table_size].urc = urc_table;
client->urc_table[client->urc_table_size].urc_size = table_sz;
client->urc_table_size++;
rt_free(old_urc_table);
}
return RT_EOK;
} }
/** /**
@ -579,30 +625,38 @@ at_client_t at_client_get_first(void)
static const struct at_urc *get_urc_obj(at_client_t client) static const struct at_urc *get_urc_obj(at_client_t client)
{ {
rt_size_t i, prefix_len, suffix_len; rt_size_t i, j, prefix_len, suffix_len;
rt_size_t buf_sz; rt_size_t bufsz;
char *buffer = RT_NULL; char *buffer = RT_NULL;
const struct at_urc *urc = RT_NULL;
struct at_urc_table *urc_table = RT_NULL;
if (client->urc_table == RT_NULL) if (client->urc_table == RT_NULL)
{ {
return RT_NULL; return RT_NULL;
} }
buffer = client->recv_buffer; buffer = client->recv_line_buf;
buf_sz = client->cur_recv_len; bufsz = client->recv_line_len;
for (i = 0; i < client->urc_table_size; i++) for (i = 0; i < client->urc_table_size; i++)
{ {
prefix_len = strlen(client->urc_table[i].cmd_prefix); for (j = 0; j < client->urc_table[i].urc_size; j++)
suffix_len = strlen(client->urc_table[i].cmd_suffix);
if (buf_sz < prefix_len + suffix_len)
{ {
continue; urc_table = client->urc_table + i;
} urc = urc_table->urc + j;
if ((prefix_len ? !strncmp(buffer, client->urc_table[i].cmd_prefix, prefix_len) : 1)
&& (suffix_len ? !strncmp(buffer + buf_sz - suffix_len, client->urc_table[i].cmd_suffix, suffix_len) : 1)) prefix_len = rt_strlen(urc->cmd_prefix);
{ suffix_len = rt_strlen(urc->cmd_suffix);
return &client->urc_table[i]; if (bufsz < prefix_len + suffix_len)
{
continue;
}
if ((prefix_len ? !rt_strncmp(buffer, urc->cmd_prefix, prefix_len) : 1)
&& (suffix_len ? !rt_strncmp(buffer + bufsz - suffix_len, urc->cmd_suffix, suffix_len) : 1))
{
return urc;
}
} }
} }
@ -615,8 +669,8 @@ static int at_recv_readline(at_client_t client)
char ch = 0, last_ch = 0; char ch = 0, last_ch = 0;
rt_bool_t is_full = RT_FALSE; rt_bool_t is_full = RT_FALSE;
memset(client->recv_buffer, 0x00, client->recv_bufsz); rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz);
client->cur_recv_len = 0; client->recv_line_len = 0;
while (1) while (1)
{ {
@ -624,8 +678,8 @@ static int at_recv_readline(at_client_t client)
if (read_len < client->recv_bufsz) if (read_len < client->recv_bufsz)
{ {
client->recv_buffer[read_len++] = ch; client->recv_line_buf[read_len++] = ch;
client->cur_recv_len = read_len; client->recv_line_len = read_len;
} }
else else
{ {
@ -639,8 +693,8 @@ static int at_recv_readline(at_client_t client)
if (is_full) if (is_full)
{ {
LOG_E("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz); LOG_E("read line failed. The line data length is out of buffer size(%d)!", client->recv_bufsz);
memset(client->recv_buffer, 0x00, client->recv_bufsz); rt_memset(client->recv_line_buf, 0x00, client->recv_bufsz);
client->cur_recv_len = 0; client->recv_line_len = 0;
return -RT_EFULL; return -RT_EFULL;
} }
break; break;
@ -649,7 +703,7 @@ static int at_recv_readline(at_client_t client)
} }
#ifdef AT_PRINT_RAW_CMD #ifdef AT_PRINT_RAW_CMD
at_print_raw_cmd("recvline", client->recv_buffer, read_len); at_print_raw_cmd("recvline", client->recv_line_buf, read_len);
#endif #endif
return read_len; return read_len;
@ -657,9 +711,7 @@ static int at_recv_readline(at_client_t client)
static void client_parser(at_client_t client) static void client_parser(at_client_t client)
{ {
int resp_buf_len = 0;
const struct at_urc *urc; const struct at_urc *urc;
rt_size_t line_counts = 0;
while(1) while(1)
{ {
@ -670,39 +722,42 @@ static void client_parser(at_client_t client)
/* current receive is request, try to execute related operations */ /* current receive is request, try to execute related operations */
if (urc->func != RT_NULL) if (urc->func != RT_NULL)
{ {
urc->func(client->recv_buffer, client->cur_recv_len); urc->func(client, client->recv_line_buf, client->recv_line_len);
} }
} }
else if (client->resp != RT_NULL) else if (client->resp != RT_NULL)
{ {
at_response_t resp = client->resp;
/* current receive is response */ /* current receive is response */
client->recv_buffer[client->cur_recv_len - 1] = '\0'; client->recv_line_buf[client->recv_line_len - 1] = '\0';
if (resp_buf_len + client->cur_recv_len < client->resp->buf_size) if (resp->buf_len + client->recv_line_len < resp->buf_size)
{ {
/* copy response lines, separated by '\0' */ /* copy response lines, separated by '\0' */
memcpy(client->resp->buf + resp_buf_len, client->recv_buffer, client->cur_recv_len); rt_memcpy(resp->buf + resp->buf_len, client->recv_line_buf, client->recv_line_len);
resp_buf_len += client->cur_recv_len;
line_counts++; /* update the current response information */
resp->buf_len += client->recv_line_len;
resp->line_counts++;
} }
else else
{ {
client->resp_status = AT_RESP_BUFF_FULL; client->resp_status = AT_RESP_BUFF_FULL;
LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", client->resp->buf_size); LOG_E("Read response buffer failed. The Response buffer size is out of buffer size(%d)!", resp->buf_size);
} }
/* check response result */ /* check response result */
if (memcmp(client->recv_buffer, AT_RESP_END_OK, strlen(AT_RESP_END_OK)) == 0 if (rt_memcmp(client->recv_line_buf, AT_RESP_END_OK, rt_strlen(AT_RESP_END_OK)) == 0
&& client->resp->line_num == 0) && resp->line_num == 0)
{ {
/* get the end data by response result, return response state END_OK. */ /* get the end data by response result, return response state END_OK. */
client->resp_status = AT_RESP_OK; client->resp_status = AT_RESP_OK;
} }
else if (strstr(client->recv_buffer, AT_RESP_END_ERROR) else if (rt_strstr(client->recv_line_buf, AT_RESP_END_ERROR)
|| (memcmp(client->recv_buffer, AT_RESP_END_FAIL, strlen(AT_RESP_END_FAIL)) == 0)) || (rt_memcmp(client->recv_line_buf, AT_RESP_END_FAIL, rt_strlen(AT_RESP_END_FAIL)) == 0))
{ {
client->resp_status = AT_RESP_ERROR; client->resp_status = AT_RESP_ERROR;
} }
else if (line_counts == client->resp->line_num && client->resp->line_num) else if (resp->line_counts == resp->line_num && resp->line_num)
{ {
/* get the end data by response line, return response state END_OK.*/ /* get the end data by response line, return response state END_OK.*/
client->resp_status = AT_RESP_OK; client->resp_status = AT_RESP_OK;
@ -711,15 +766,13 @@ static void client_parser(at_client_t client)
{ {
continue; continue;
} }
client->resp->line_counts = line_counts;
client->resp = RT_NULL; client->resp = RT_NULL;
rt_sem_release(client->resp_notice); rt_sem_release(client->resp_notice);
resp_buf_len = 0, line_counts = 0;
} }
else else
{ {
// log_d("unrecognized line: %.*s", client->cur_recv_len, client->recv_buffer); // log_d("unrecognized line: %.*s", client->recv_line_len, client->recv_line_buf);
} }
} }
} }
@ -754,9 +807,9 @@ static int at_client_para_init(at_client_t client)
client->status = AT_STATUS_UNINITIALIZED; client->status = AT_STATUS_UNINITIALIZED;
client->cur_recv_len = 0; client->recv_line_len = 0;
client->recv_buffer = (char *) rt_calloc(1, client->recv_bufsz); client->recv_line_buf = (char *) rt_calloc(1, client->recv_bufsz);
if (client->recv_buffer == RT_NULL) if (client->recv_line_buf == RT_NULL)
{ {
LOG_E("AT client initialize failed! No memory for receive buffer."); LOG_E("AT client initialize failed! No memory for receive buffer.");
result = -RT_ENOMEM; result = -RT_ENOMEM;
@ -829,9 +882,9 @@ __exit:
rt_device_close(client->device); rt_device_close(client->device);
} }
if (client->recv_buffer) if (client->recv_line_buf)
{ {
rt_free(client->recv_buffer); rt_free(client->recv_line_buf);
} }
rt_memset(client, 0x00, sizeof(struct at_client)); rt_memset(client, 0x00, sizeof(struct at_client));

View File

@ -70,7 +70,7 @@ rt_size_t at_vprintf(rt_device_t device, const char *format, va_list args)
last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args); last_cmd_len = vsnprintf(send_buf, sizeof(send_buf), format, args);
#ifdef AT_PRINT_RAW_CMD #ifdef AT_PRINT_RAW_CMD
at_print_raw_cmd("send", send_buf, last_cmd_len); at_print_raw_cmd("sendline", send_buf, last_cmd_len);
#endif #endif
return rt_device_write(device, 0, send_buf, last_cmd_len); return rt_device_write(device, 0, send_buf, last_cmd_len);