123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /****************************************************************************
- * net/bluetooth/bluetooth_input.c
- * Handle incoming Bluetooth frame input
- *
- * Copyright (C) 2018 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
- * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <string.h>
- #include <assert.h>
- #include <debug.h>
- #include <nuttx/mm/iob.h>
- #include <nuttx/net/radiodev.h>
- #include <nuttx/net/bluetooth.h>
- #include <nuttx/wireless/bluetooth/bt_hci.h>
- #include "devif/devif.h"
- #include "bluetooth/bluetooth.h"
- #ifdef CONFIG_NET_BLUETOOTH
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: bluetooth_count_frames
- *
- * Description:
- * Return the number of frames in the RX queue.
- *
- * Input Parameters:
- * conn - The socket connection structure.
- *
- * Returned Value:
- * The number of frames in the queue.
- *
- ****************************************************************************/
- #if defined(CONFIG_DEBUG_ASSERTIONS) && CONFIG_NET_BLUETOOTH_BACKLOG > 0
- static int bluetooth_count_frames(FAR struct bluetooth_conn_s *conn)
- {
- FAR struct bluetooth_container_s *container;
- int count;
- for (count = 0, container = conn->bc_rxhead;
- container != NULL;
- count++, container = container->bn_flink)
- {
- }
- return count;
- }
- #endif
- /****************************************************************************
- * Name: bluetooth_queue_frame
- *
- * Description:
- * Add one frame to the connection's RX queue.
- *
- * Input Parameters:
- * conn - The socket connection structure.
- * framel - A single frame to add to the RX queue.
- * meta - Meta data characterizing the received frane.
- *
- * Returned Value:
- * Zero (OK) is returned on success; A negated errno value is returned on
- * any failure.
- *
- ****************************************************************************/
- static int bluetooth_queue_frame(FAR struct bluetooth_conn_s *conn,
- FAR struct iob_s *frame,
- FAR struct bluetooth_frame_meta_s *meta)
- {
- FAR struct bluetooth_container_s *container;
- /* Allocate a container for the frame */
- container = bluetooth_container_allocate();
- if (container == NULL)
- {
- nerr("ERROR: Failed to allocate a container\n");
- return -ENOMEM;
- }
- /* Initialize the container */
- memset(&container->bn_raddr, 0, sizeof(bt_addr_t));
- container->bn_channel = meta->bm_channel;
- BLUETOOTH_ADDRCOPY(&container->bn_raddr, &meta->bm_raddr);
- DEBUGASSERT(frame != NULL);
- container->bn_iob = frame;
- /* Add the container to the tail of the list of incoming frames */
- container->bn_flink = NULL;
- if (conn->bc_rxtail == NULL)
- {
- conn->bc_rxhead = container;
- }
- else
- {
- conn->bc_rxtail->bn_flink = container;
- }
- #if CONFIG_NET_BLUETOOTH_BACKLOG > 0
- /* If incrementing the count would exceed the maximum bc_backlog value, then
- * delete the oldest frame from the head of the RX queue.
- */
- if (conn->bc_backlog >= CONFIG_NET_BLUETOOTH_BACKLOG)
- {
- DEBUGASSERT(conn->bc_backlog == CONFIG_NET_BLUETOOTH_BACKLOG);
- /* Remove the container from the tail RX input queue. */
- container = conn->bc_rxhead;
- DEBUGASSERT(container != NULL);
- conn->bc_rxhead = container->bn_flink;
- container->bn_flink = NULL;
- /* Did the RX queue become empty? */
- if (conn->bc_rxhead == NULL)
- {
- conn->bc_rxtail = NULL;
- }
- DEBUGASSERT(container != NULL && container->bn_iob != NULL);
- /* Free both the IOB and the container */
- iob_free(container->bn_iob, IOBUSER_NET_SOCK_BLUETOOTH);
- bluetooth_container_free(container);
- }
- else
- {
- /* Increment the count of frames in the queue. */
- conn->bc_backlog++;
- }
- DEBUGASSERT((int)conn->bc_backlog == bluetooth_count_frames(conn));
- #endif
- return OK;
- }
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: bluetooth_input
- *
- * Description:
- * Handle incoming Bluetooth input
- *
- * This function is called when the radio device driver has received an
- * frame from the network. The frame from the device driver must be
- * provided in by the IOB frame argument of the function call:
- *
- * - The frame data is in the IOB io_data[] buffer,
- * - The length of the frame is in the IOB io_len field, and
- * - The offset past and radio MAC header is provided in the io_offset
- * field.
- *
- * The frame argument may refer to a single frame (a list of length one)
- * or may it be the head of a list of multiple frames.
- *
- * - The io_flink field points to the next frame in the list (if enable)
- * - The last frame in the list will have io_flink == NULL.
- *
- * Input Parameters:
- * radio The radio network driver interface.
- * framelist - The head of an incoming list of frames. Normally this
- * would be a single frame. A list may be provided if
- * appropriate, however.
- * meta - Meta data characterizing the received frame.
- *
- * If there are multiple frames in the list, this metadata
- * must apply to all of the frames in the list.
- *
- * Returned Value:
- * OK The Bluetooth has been processed and can be deleted
- * ERROR Hold the Bluetooth and try again later. There is a listening
- * socket but no recv in place to catch the Bluetooth yet.
- * Useful when a packet arrives before a recv call is in place.
- *
- * Assumptions:
- * Called from the network diver with the network locked.
- *
- ****************************************************************************/
- int bluetooth_input(FAR struct radio_driver_s *radio,
- FAR struct iob_s *framelist,
- FAR struct bluetooth_frame_meta_s *meta)
- {
- FAR struct bluetooth_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 */
- conn = bluetooth_conn_active(meta);
- if (conn != NULL)
- {
- /* Setup for the application callback (NOTE: These should not be
- * used by PF_BLUETOOTH sockets).
- */
- radio->r_dev.d_appdata = radio->r_dev.d_buf;
- radio->r_dev.d_len = 0;
- radio->r_dev.d_sndlen = 0;
- /* The framelist probably contains only a single frame, but we will
- * process it as a list of frames.
- */
- for (frame = framelist; frame != NULL; frame = next)
- {
- /* Remove the frame from the list */
- next = frame->io_flink;
- frame->io_flink = NULL;
- /* Add the frame to the RX queue */
- ret = bluetooth_queue_frame(conn, frame, meta);
- if (ret < 0)
- {
- nerr("ERROR: Failed to queue frame: %d\n", ret);
- iob_free(frame, IOBUSER_NET_SOCK_BLUETOOTH);
- }
- }
- /* 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 bluetooth_callback would distinguish these
- * cases: BLUETOOTH_NEWDATA will still be processed if the frame
- * was not consumed.
- */
- (void)bluetooth_callback(radio, conn, BLUETOOTH_NEWDATA);
- }
- else
- {
- nwarn("WARNING: No listener\n");
- }
- return ret;
- }
- #endif /* CONFIG_NET_BLUETOOTH */
|