diff --git a/net/ieee802154/ieee802154_conn.c b/net/ieee802154/ieee802154_conn.c index b1cac1c3f5..6b5f1ee985 100644 --- a/net/ieee802154/ieee802154_conn.c +++ b/net/ieee802154/ieee802154_conn.c @@ -44,6 +44,7 @@ #include +#include #include #include #include @@ -150,6 +151,9 @@ FAR struct ieee802154_conn_s *ieee802154_conn_alloc(void) void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn) { + FAR struct ieee802154_container_s *container; + FAR struct ieee802154_container_s *next; + /* The free list is only accessed from user, non-interrupt level and * is protected by a semaphore (that behaves like a mutex). */ @@ -161,6 +165,29 @@ void ieee802154_conn_free(FAR struct ieee802154_conn_s *conn) net_lock(); dq_rem(&conn->node, &g_active_ieee802154_connections); + /* Check if there any any frames attached to the container */ + + for (container = conn->rxhead; + container != NULL; + container = container->ic_flink) + { + /* Remove the frame from the list */ + + next = container->ic_flink; + container->ic_flink = NULL; + + /* Free the contained frame data (should be only one in chain) */ + + if (container->ic_iob) + { + iob_free(container->ic_iob); + } + + /* And free the container itself */ + + ieee802154_container_free(container); + } + /* Free the connection */ dq_addlast(&conn->node, &g_free_ieee802154_connections); diff --git a/net/ieee802154/ieee802154_input.c b/net/ieee802154/ieee802154_input.c index 3e4846ffdd..6279d792b8 100644 --- a/net/ieee802154/ieee802154_input.c +++ b/net/ieee802154/ieee802154_input.c @@ -51,6 +51,77 @@ #ifdef CONFIG_NET_IEEE802154 +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ieee802154_queue_frame + * + * Description: + * Add one frame to the connection's RX queue. + * + * Parameters: + * conn - The socket connection structure. + * framel - A single frame to add to the RX queue. + * meta - Meta data characterizing the received frane. + * + * Return: + * Zero (OK) is returned on success; A negated errno value is returned on + * any failure. + * + ****************************************************************************/ + +int ieee802154_queue_frame(FAR struct ieee802154_conn_s *conn, + FAR struct iob_s *frame, + FAR struct ieee802154_data_ind_s *meta) +{ + FAR struct ieee802154_container_s *container; + + /* Allocate a container for the frame */ + + container = ieee802154_container_allocate(); + if (container == NULL) + { + nerr("ERROR: Failed to allocate a container\n"); + return -ENOMEM; + } + + /* Initialize the container */ + + memset(&container->ic_src, 0, sizeof(struct ieee802154_saddr_s)); + + DEBUGASSERT(meta->src.mode != IEEE802154_ADDRMODE_NONE); + container->ic_src.s_mode = meta->src.mode; + IEEE802154_PANIDCOPY(container->ic_src.s_panid, meta->src.panid); + + if (meta->src.mode == IEEE802154_ADDRMODE_SHORT) + { + IEEE802154_SADDRCOPY(container->ic_src.s_saddr, meta->src.saddr); + } + else if (meta->src.mode == IEEE802154_ADDRMODE_EXTENDED) + { + IEEE802154_EADDRCOPY(container->ic_src.s_eaddr, meta->src.eaddr); + } + + DEBUGASSERT(frame != NULL); + container->ic_iob = frame; + + /* Add the container to the tail of the list of incoming frames */ + + container->ic_flink = NULL; + if (conn->rxtail == NULL) + { + conn->rxhead = container; + } + else + { + conn->rxtail->ic_flink = container; + } + + return OK; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -101,8 +172,9 @@ int ieee802154_input(FAR struct radio_driver_s *radio, FAR struct iob_s *framelist, FAR struct ieee802154_data_ind_s *meta) { - FAR struct ieee802154_container_s *container; FAR struct ieee802154_conn_s *conn; + FAR struct iob_s *frame; + FAR struct iob_s *next; int ret = OK; /* Check if there is a connection that will accept this packet */ @@ -110,8 +182,6 @@ int ieee802154_input(FAR struct radio_driver_s *radio, conn = ieee802154_conn_active(meta); if (conn != NULL) { - uint16_t flags; - /* Setup for the application callback (NOTE: These should not be * used by PF_IEEE802154 sockets). */ @@ -120,72 +190,40 @@ int ieee802154_input(FAR struct radio_driver_s *radio, radio->r_dev.d_len = 0; radio->r_dev.d_sndlen = 0; - /* Allocate a container for the IOB */ - - container = ieee802154_container_allocate(); - if (container == NULL) - { - nerr("ERROR: Failed to allocate a container\n"); - return -ENOMEM; - } - - /* Initialize the container */ - - memset(&container->ic_src, 0, sizeof(struct ieee802154_saddr_s)); - - DEBUGASSERT(meta->src.mode != IEEE802154_ADDRMODE_NONE); - container->ic_src.s_mode = meta->src.mode; - IEEE802154_PANIDCOPY(container->ic_src.s_panid, meta->src.panid); - - if (meta->src.mode == IEEE802154_ADDRMODE_SHORT) - { - IEEE802154_SADDRCOPY(container->ic_src.s_saddr, meta->src.saddr); - } - else if (meta->src.mode == IEEE802154_ADDRMODE_EXTENDED) - { - IEEE802154_EADDRCOPY(container->ic_src.s_eaddr, meta->src.eaddr); - } - - DEBUGASSERT(framelist != NULL); - container->ic_iob = framelist; - - /* Add the container to the tail of the list of incoming frames */ - - container->ic_flink = NULL; - if (conn->rxtail == NULL) - { - conn->rxhead = container; - } - else - { - conn->rxtail->ic_flink = container; - } - - conn->rxtail = container; - - /* Perform the application callback */ - - flags = ieee802154_callback(radio, conn, IEEE802154_NEWDATA); - - /* If the operation was successful, the IEEE802154_NEWDATA flag is - * removed and thus the frame can be deleted (OK will be returned). + /* The framelist probably contains only a single frame, but we will + * process it as a list of frames. */ - if ((flags & IEEE802154_NEWDATA) != 0) + for (frame = framelist; frame != NULL; frame = next) { - /* No.. the frame was not processed now. Return ERROR so - * that the driver may retry again later. We still need to - * set d_len to zero so that the driver is aware that there - * is nothing to be sent. - */ + /* Remove the frame from the list */ - nwarn("WARNING: Frame not processed\n"); - ret = ERROR; + next = frame->io_flink; + frame->io_flink = NULL; + + /* Add the frame to the RX queue */ + + ret = ieee802154_queue_frame(conn, frame, meta); + if (ret < 0) + { + nerr("ERROR: Failed to queue frame: %d\n", ret); + iob_free(frame); + } } + + /* Perform the application callback. The frame may be processed now + * if there is a user wait for an incoming frame. Or it may pend in + * the RX queue until some user process reads the frame. NOTE: The + * return value from ieee802154_callback would distinguish these + * cases: IEEE802154_NEWDATA will still be processed if the frame + * was not consumed. + */ + + (void)ieee802154_callback(radio, conn, IEEE802154_NEWDATA); } else { - nerr("ERROR: No listener\n"); + nwarn("WARNING: No listener\n"); } return ret;