Skip to content
......@@ -294,6 +294,7 @@ source "net/pkt/Kconfig"
source "net/local/Kconfig"
source "net/tcp/Kconfig"
source "net/udp/Kconfig"
source "net/bluetooth/Kconfig"
source "net/ieee802154/Kconfig"
source "net/icmp/Kconfig"
source "net/icmpv6/Kconfig"
......
############################################################################
# net/Makefile
#
# Copyright (C) 2007, 2008, 2011-2017 Gregory Nutt. All rights reserved.
# Copyright (C) 2007, 2008, 2011-2018 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
......@@ -68,6 +68,7 @@ include local/Make.defs
include tcp/Make.defs
include udp/Make.defs
include sixlowpan/Make.defs
include bluetooth/Make.defs
include ieee802154/Make.defs
include devif/Make.defs
include ipforward/Make.defs
......
......@@ -9,6 +9,7 @@ Directory Structure
`- net/
|
+- arp - Address resolution protocol (IPv4)
+- bluetooth - PF_BLUETOOTH socket interface
+- devif - Stack/device interface layer
+- icmp - Internet Control Message Protocol (IPv4)
+- icmpv6 - Internet Control Message Protocol (IPv6)
......@@ -28,7 +29,6 @@ Directory Structure
+- usrsock - User socket API for user-space networking stack
`- utils - Miscellaneous utility functions
+-------------------------------------------------------------------++------------------------+
| Application layer || usrsock daemon |
+-------------------------------------------------------------------++------------------------+
......
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
menu "Bluetooth socket support"
config NET_BLUETOOTH
bool "Bluetooth socket support"
default n
depends on WIRELESS_BLUETOOTH
select NETDEV_IOCTL
---help---
Enable support for raw, Bluetooth sockets.
Raw sockets allow receiving and transmitting Bluetooth radio
frames without a layer2 protocol such as 6LoWPAN in between. Frames
received are copied into a Bluetooth socket tap before they
enter the network. Frames written into a Bluetooth socket will
bypass the network altogether and will be sent directly to the
Bluetooth MAC network interface driver outgoing frame queue.
if NET_BLUETOOTH
config NET_BLUETOOTH_NCONNS
int "Max Bluetooth sockets"
default 4
config NET_BLUETOOTH_NCONTAINERS
int "Number of pre-allocated frame containers"
default 8
---help---
This specifies the total number of preallocated frame containers.
One must be allocated with each incoming frame.
config NET_BLUETOOTH_BACKLOG
int "Maximum frame backlog"
default 8
range 0 255
---help---
As frames are received, then are help in an RX queue. They remain
in the RX queue until application logic reads the queue frames. To
prevent overrun, the maximum backlog may be set to a nonzero value.
What the backlog of queue frames reaches that count, the olds frame
will be freed, preventing overrun at the cost of losing the oldest
frames.
NOTE: The special value of zero will disable all backlog checkes.
endif # NET_BLUETOOTH
endmenu # Bluetooth Socket Support
############################################################################
# net/bluetooth/Make.defs
#
# 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. Neither the name NuttX nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "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
# COPYRIGHT OWNER OR CONTRIBUTORS 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.
#
############################################################################
# Packet socket support
ifeq ($(CONFIG_NET_BLUETOOTH),y)
# Initialization / resource managment
NET_CSRCS += bluetooth_initialize.c
NET_CSRCS += bluetooth_conn.c
NET_CSRCS += bluetooth_container.c
# Socket layer
SOCK_CSRCS += bluetooth_sockif.c
SOCK_CSRCS += bluetooth_sendto.c
SOCK_CSRCS += bluetooth_recvfrom.c
# Device interface
NET_CSRCS += bluetooth_input.c
NET_CSRCS += bluetooth_callback.c
NET_CSRCS += bluetooth_poll.c
NET_CSRCS += bluetooth_finddev.c
# Include packet socket build support
DEPPATH += --dep-path bluetooth
VPATH += :bluetooth
endif # CONFIG_NET_BLUETOOTH
/****************************************************************************
* net/bluetooth/bluetooth.h
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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.
*
****************************************************************************/
#ifndef _NET_BLUETOOTH_BLUETOOTH_H
#define _NET_BLUETOOTH_BLUETOOTH_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <queue.h>
#include <nuttx/wireless/bt_hci.h>
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Allocate a new Bluetooth socket data callback */
#define bluetooth_callback_alloc(dev,conn) \
devif_callback_alloc(dev, &conn->list)
#define bluetooth_callback_free(dev,conn,cb) \
devif_conn_callback_free(dev, cb, &conn->list)
/* Memory Pools */
#define BLUETOOTH_POOL_PREALLOCATED 0
#define BLUETOOTH_POOL_DYNAMIC 1
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* Used for containing and queuing IOBs along with information about the
* source of the frame.
*/
struct iob_s; /* Forward reference */
struct bluetooth_container_s
{
FAR struct bluetooth_container_s *bn_flink; /* Supports a singly linked list */
FAR struct iob_s *bn_iob; /* Contained IOB */
bt_addr_t bn_raddr; /* Source address of the packet */
uint8_t bn_channel; /* Source channel of the packet */
uint8_t bn_pool; /* See BLUETOOTH_POOL_* definitions */
};
/* Representation of a Bluetooth socket connection */
struct devif_callback_s; /* Forward reference */
struct bluetooth_conn_s
{
dq_entry_t bc_node; /* Supports a double linked list */
bt_addr_t bc_laddr; /* Locally bound / source address.
* Necessary only to support multiple
* Bluetooth devices */
bt_addr_t bc_raddr; /* Connected remote address */
uint8_t bc_channel; /* Connection channel */
uint8_t bc_crefs; /* Reference counts on this instance */
#if CONFIG_NET_BLUETOOTH_BACKLOG > 0
uint8_t bc_backlog; /* Number of frames in RX queue */
#endif
/* Queue of incoming packets */
FAR struct bluetooth_container_s *bc_rxhead;
FAR struct bluetooth_container_s *bc_rxtail;
/* This is a list of Bluetooth callbacks. Each callback represents
* a thread that is stalled, waiting for a device-specific event.
*/
FAR struct devif_callback_s *list;
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
# define EXTERN extern "C"
extern "C"
{
#else
# define EXTERN extern
#endif
/* The Bluetooth socket interface */
EXTERN const struct sock_intf_s g_bluetooth_sockif;
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
struct bluetooth_frame_meta_s; /* Forward reference */
struct radio_driver_s; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
/****************************************************************************
* Name: bluetooth_initialize()
*
* Description:
* Initialize the Bluetooth socket support. Called once and only
* from the network initialization logic.
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_initialize(void);
/****************************************************************************
* Name: bluetooth_conn_initialize
*
* Description:
* Initialize the Bluetooth connection structure allocator. Called
* once and only from bluetooth_initialize().
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_conn_initialize(void);
/****************************************************************************
* Name: bluetooth_conn_alloc()
*
* Description:
* Allocate a new, uninitialized Bluetooth socket connection
* structure. This is normally something done by the implementation of
* the socket() API
*
****************************************************************************/
FAR struct bluetooth_conn_s *bluetooth_conn_alloc(void);
/****************************************************************************
* Name: bluetooth_conn_free()
*
* Description:
* Free a Bluetooth socket connection structure that is no longer in
* use. This should be done by the implementation of close().
*
****************************************************************************/
void bluetooth_conn_free(FAR struct bluetooth_conn_s *conn);
/****************************************************************************
* Name: bluetooth_conn_active()
*
* Description:
* Find a connection structure that is the appropriate
* connection to be used with the provided Ethernet header
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
FAR struct bluetooth_conn_s *
bluetooth_conn_active(FAR const struct bluetooth_frame_meta_s *meta);
/****************************************************************************
* Name: bluetooth_conn_next()
*
* Description:
* Traverse the list of allocated Bluetooth connections
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
FAR struct bluetooth_conn_s *
bluetooth_conn_next(FAR struct bluetooth_conn_s *conn);
/****************************************************************************
* 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.
*
****************************************************************************/
/* bluetooth_input() is prototyped in include/nuttx/net/bluetooth.h */
/****************************************************************************
* Name: bluetooth_callback
*
* Description:
* Inform the application holding the Bluetooth socket of a change in state.
*
* Returned Value:
* OK if Bluetooth has been processed, otherwise ERROR.
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
uint16_t bluetooth_callback(FAR struct radio_driver_s *radio,
FAR struct bluetooth_conn_s *conn,
uint16_t flags);
/****************************************************************************
* Name: bluetooth_recvfrom
*
* Description:
* Implements the socket recvfrom interface for the case of the AF_INET
* and AF_INET6 address families. bluetooth_recvfrom() receives messages from
* a socket, and may be used to receive data on a socket whether or not it
* is connection-oriented.
*
* If 'from' is not NULL, and the underlying protocol provides the source
* address, this source address is filled in. The argument 'fromlen' is
* initialized to the size of the buffer associated with from, and
* modified on return to indicate the actual size of the address stored
* there.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* flags Receive flags
* from Address of source (may be NULL)
* fromlen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters received. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on errors, a negated errno value is
* returned (see recvfrom() for the list of appropriate error values).
*
****************************************************************************/
ssize_t bluetooth_recvfrom(FAR struct socket *psock, FAR void *buf,
size_t len, int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen);
/****************************************************************************
* Name: bluetooth_find_device
*
* Description:
* Select the network driver to use with the Bluetooth transaction.
*
* Input Parameters:
* conn - Bluetooth connection structure (not currently used).
* addr - The address to match the devices assigned address
*
* Returned Value:
* A pointer to the network driver to use. NULL is returned on any
* failure.
*
****************************************************************************/
FAR struct radio_driver_s *
bluetooth_find_device(FAR struct bluetooth_conn_s *conn,
FAR const bt_addr_t *addr);
/****************************************************************************
* Name: bluetooth_poll
*
* Description:
* Poll a Bluetooth "connection" structure for availability of TX data
*
* Input Parameters:
* dev - The device driver structure to use in the send operation
* conn - The Bluetooth "connection" to poll for TX data
*
* Returned Value:
* None
*
* Assumptions:
* Called from the network device interface (devif) with the network
* locked.
*
****************************************************************************/
void bluetooth_poll(FAR struct net_driver_s *dev,
FAR struct bluetooth_conn_s *conn);
/****************************************************************************
* Name: psock_bluetooth_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is retruend. See sendto() for the complete list
* of return values.
*
****************************************************************************/
ssize_t psock_bluetooth_sendto(FAR struct socket *psock,
FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen);
/****************************************************************************
* Name: bluetooth_container_initialize
*
* Description:
* This function initializes the container allocator. This function must
* be called early in the initialization sequence before any socket
* activity.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_container_initialize(void);
/****************************************************************************
* Name: bluetooth_container_allocate
*
* Description:
* The bluetooth_container_allocate function will get a free continer
* for use by the recvfrom() logic.
*
* This function will first attempt to allocate from the g_free_container
* list. If that the list is empty, then the meta-data structure will be
* allocated from the dynamic memory pool.
*
* Input Parameters:
* None
*
* Returned Value:
* A reference to the allocated container structure. All user fields in this
* structure have been zeroed. On a failure to allocate, NULL is
* returned.
*
* Assumptions:
* The caller has locked the network.
*
****************************************************************************/
FAR struct bluetooth_container_s *bluetooth_container_allocate(void);
/****************************************************************************
* Name: bluetooth_container_free
*
* Description:
* The bluetooth_container_free function will return a container structure
* to the free list of containers if it was a pre-allocated container
* structure. If the container structure was allocated dynamically it will
* be deallocated.
*
* Input Parameters:
* container - container structure to free
*
* Returned Value:
* None
*
* Assumptions:
* The caller has locked the network.
*
****************************************************************************/
void bluetooth_container_free(FAR struct bluetooth_container_s *container);
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_NET_BLUETOOTH */
#endif /* _NET_BLUETOOTH_BLUETOOTH_H */
/****************************************************************************
* net/bluetooth/bluetooth_callback.c
* Forward events to waiting PF_BLUETOOTH sockets.
*
* 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 <debug.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include "devif/devif.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_callback
*
* Description:
* Inform the application holding the packet socket of a change in state.
*
* Returned Value:
* OK if packet has been processed, otherwise ERROR.
*
* Assumptions:
* This function is called at the interrupt level with interrupts disabled.
*
****************************************************************************/
uint16_t bluetooth_callback(FAR struct radio_driver_s *radio,
FAR struct bluetooth_conn_s *conn,
uint16_t flags)
{
ninfo("flags: %04x\n", flags);
/* Some sanity checking */
if (conn != NULL)
{
/* Perform the callback */
flags = devif_conn_event(&radio->r_dev, conn, flags, conn->list);
}
return flags;
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* net/bluetooth/bluetooth_conn.c
*
* 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 <semaphore.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <netpacket/bluetooth.h>
#include <arch/irq.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/net.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/bluetooth.h>
#include "devif/devif.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Private Data
****************************************************************************/
/* The array containing all packet socket connections. Protected via the
* network lock.
*/
static struct bluetooth_conn_s
g_bluetooth_connections[CONFIG_NET_BLUETOOTH_NCONNS];
/* A list of all free packet socket connections */
static dq_queue_t g_free_bluetooth_connections;
/* A list of all allocated packet socket connections */
static dq_queue_t g_active_bluetooth_connections;
static const bt_addr_t g_any_addr =
{
BT_ADDR_ANY
};
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_conn_initialize
*
* Description:
* Initialize the Bluetooth connection structure allocator. Called
* once and only from bluetooth_initialize().
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_conn_initialize(void)
{
int i;
/* Initialize the queues */
dq_init(&g_free_bluetooth_connections);
dq_init(&g_active_bluetooth_connections);
for (i = 0; i < CONFIG_NET_BLUETOOTH_NCONNS; i++)
{
/* Link each pre-allocated connection structure into the free list. */
dq_addlast(&g_bluetooth_connections[i].bc_node,
&g_free_bluetooth_connections);
}
}
/****************************************************************************
* Name: bluetooth_conn_alloc()
*
* Description:
* Allocate a new, uninitialized packet socket connection structure. This
* is normally something done by the implementation of the socket() API
*
****************************************************************************/
FAR struct bluetooth_conn_s *bluetooth_conn_alloc(void)
{
FAR struct bluetooth_conn_s *conn;
/* The free list is only accessed from user, non-interrupt level and
* is protected by a semaphore (that behaves like a mutex).
*/
net_lock();
conn = (FAR struct bluetooth_conn_s *)
dq_remfirst(&g_free_bluetooth_connections);
if (conn)
{
/* Enqueue the connection into the active list */
memset(conn, 0, sizeof(struct bluetooth_conn_s));
dq_addlast(&conn->bc_node, &g_active_bluetooth_connections);
}
net_unlock();
return conn;
}
/****************************************************************************
* Name: bluetooth_conn_free()
*
* Description:
* Free a packet socket connection structure that is no longer in use.
* This should be done by the implementation of close().
*
****************************************************************************/
void bluetooth_conn_free(FAR struct bluetooth_conn_s *conn)
{
FAR struct bluetooth_container_s *container;
FAR struct bluetooth_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).
*/
DEBUGASSERT(conn->bc_crefs == 0);
/* Remove the connection from the active list */
net_lock();
dq_rem(&conn->bc_node, &g_active_bluetooth_connections);
/* Check if there any any frames attached to the container */
for (container = conn->bc_rxhead; container != NULL; container = next)
{
/* Remove the frame from the list */
next = container->bn_flink;
container->bn_flink = NULL;
/* Free the contained frame data (should be only one in chain) */
if (container->bn_iob)
{
iob_free(container->bn_iob);
}
/* And free the container itself */
bluetooth_container_free(container);
}
/* Free the connection */
dq_addlast(&conn->bc_node, &g_free_bluetooth_connections);
net_unlock();
}
/****************************************************************************
* Name: bluetooth_conn_active()
*
* Description:
* Find a connection structure that is the appropriate
* connection to be used with the provided Bluetooth header
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
FAR struct bluetooth_conn_s *
bluetooth_conn_active(FAR const struct bluetooth_frame_meta_s *meta)
{
FAR struct bluetooth_conn_s *conn;
DEBUGASSERT(meta != NULL);
for (conn = (FAR struct bluetooth_conn_s *)g_active_bluetooth_connections.head;
conn != NULL;
conn = (FAR struct bluetooth_conn_s *)conn->bc_node.flink)
{
/* Does the destination address match the bound address of the socket. */
if ((BLUETOOTH_ADDRCMP(&conn->bc_raddr, &meta->bm_raddr) ||
BLUETOOTH_ADDRCMP(&conn->bc_raddr, &g_any_addr)) &&
(meta->bm_channel == conn->bc_channel ||
BT_CHANNEL_ANY == conn->bc_channel))
{
continue;
}
}
return conn;
}
/****************************************************************************
* Name: bluetooth_conn_next()
*
* Description:
* Traverse the list of allocated packet connections
*
* Assumptions:
* This function is called from network logic at with the network locked.
*
****************************************************************************/
FAR struct bluetooth_conn_s *
bluetooth_conn_next(FAR struct bluetooth_conn_s *conn)
{
if (!conn)
{
return (FAR struct bluetooth_conn_s *)
g_active_bluetooth_connections.head;
}
else
{
return (FAR struct bluetooth_conn_s *)conn->bc_node.flink;
}
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* net/bluetooth/bluetooth_container.c
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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 <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mm/iob.h>
#include "bluetooth/bluetooth.h"
/****************************************************************************
* Private Data
****************************************************************************/
/* The g_free_container is a list of IOB container structures that are
* available for general use. The number of messages in this list is a
* system configuration item.
*
* Mutually exclusive access to this list is managed via the network lock:
* i.e., the network must be locked beffore accessing this free list.
*/
static FAR struct bluetooth_container_s *g_free_container;
/* Pool of pre-allocated meta-data stuctures */
static struct bluetooth_container_s
g_container_pool[CONFIG_NET_BLUETOOTH_NCONTAINERS];
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_container_initialize
*
* Description:
* This function initializes the container allocator. This function must
* be called early in the initialization sequence before any socket
* activity.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_container_initialize(void)
{
FAR struct bluetooth_container_s *container;
int i;
/* Initialize g_free_container, the list of meta-data structures that
* are available for allocation.
*/
g_free_container = NULL;
for (i = 0, container = g_container_pool;
i < CONFIG_NET_BLUETOOTH_NCONTAINERS;
i++, container++)
{
/* Add the next meta data structure from the pool to the list of
* general structures.
*/
container->bn_flink = g_free_container;
g_free_container = container;
}
}
/****************************************************************************
* Name: bluetooth_container_allocate
*
* Description:
* The bluetooth_container_allocate function will get a free continer
* for use by the recvfrom() logic.
*
* This function will first attempt to allocate from the g_free_container
* list. If that the list is empty, then the meta-data structure will be
* allocated from the dynamic memory pool.
*
* Input Parameters:
* None
*
* Returned Value:
* A reference to the allocated container structure. All user fields in this
* structure have been zeroed. On a failure to allocate, NULL is
* returned.
*
* Assumptions:
* The caller has locked the network.
*
****************************************************************************/
FAR struct bluetooth_container_s *bluetooth_container_allocate(void)
{
FAR struct bluetooth_container_s *container;
uint8_t pool;
/* Try the free list first */
net_lock();
if (g_free_container != NULL)
{
container = g_free_container;
g_free_container = container->bn_flink;
pool = BLUETOOTH_POOL_PREALLOCATED;
net_unlock();
}
else
{
net_unlock();
container = (FAR struct bluetooth_container_s *)
kmm_malloc((sizeof (struct bluetooth_container_s)));
pool = BLUETOOTH_POOL_DYNAMIC;
}
/* We have successfully allocated memory from some source? */
if (container != NULL)
{
/* Zero and tag the allocated meta-data structure. */
memset(container, 0, sizeof(struct bluetooth_container_s));
container->bn_pool = pool;
}
return container;
}
/****************************************************************************
* Name: bluetooth_container_free
*
* Description:
* The bluetooth_container_free function will return a container structure
* to the free list of containers if it was a pre-allocated container
* structure. If the container structure was allocated dynamically it will
* be deallocated.
*
* Input Parameters:
* container - container structure to free
*
* Returned Value:
* None
*
* Assumptions:
* The caller has locked the network.
*
****************************************************************************/
void bluetooth_container_free(FAR struct bluetooth_container_s *container)
{
/* If this is a pre-allocated meta-data structure, then just put it back
* in the free list.
*/
net_lock();
if (container->bn_pool == BLUETOOTH_POOL_PREALLOCATED)
{
container->bn_flink = g_free_container;
g_free_container = container;
net_unlock();
}
else
{
DEBUGASSERT(container->bn_pool == BLUETOOTH_POOL_DYNAMIC);
/* Otherwise, deallocate it. */
net_unlock();
sched_kfree(container);
}
}
/****************************************************************************
* net/bluetooth/bluetooth_finddev.c
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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 <assert.h>
#include <nuttx/net/net.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bt_hci.h>
#include "netdev/netdev.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Private Types
****************************************************************************/
struct bluetooth_finddev_s
{
FAR const bt_addr_t *bf_addr;
FAR struct radio_driver_s *bf_radio;
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_dev_callback
*
* Description:
* Check if this device matches the connections local address.
*
* Input Parameters:
* dev - The next network device in the enumeration
*
* Returned Value:
* 0 if there is no match (meaning to continue looking); 1 if there is a
* match (meaning to stop the search).
*
****************************************************************************/
static int bluetooth_dev_callback(FAR struct net_driver_s *dev, FAR void *arg)
{
FAR struct bluetooth_finddev_s *match =
(FAR struct bluetooth_finddev_s *)arg;
DEBUGASSERT(dev != NULL && match != NULL && match->bf_addr != NULL);
/* First, check if this network device is an Bluetooth radio and that
* it has an assigned Bluetooth address.
*/
if (dev->d_lltype == NET_LL_BLUETOOTH && dev->d_mac.radio.nv_addrlen > 0)
{
DEBUGASSERT(dev->d_mac.radio.nv_addrlen == BLUETOOTH_ADDRSIZE);
/* Does the device address match */
if (BLUETOOTH_ADDRCMP(dev->d_mac.radio.nv_addr, match->bf_addr))
{
/* Yes.. save the match and return 1 to stop the search */
match->bf_radio = (FAR struct radio_driver_s *)dev;
return 1;
}
}
/* Keep looking */
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_find_device
*
* Description:
* Select the network driver to use with the Bluetooth transaction.
*
* Input Parameters:
* conn - Bluetooth connection structure (not currently used).
* addr - The address to match the devices assigned address
*
* Returned Value:
* A pointer to the network driver to use. NULL is returned on any
* failure.
*
****************************************************************************/
FAR struct radio_driver_s *
bluetooth_find_device(FAR struct bluetooth_conn_s *conn,
FAR const bt_addr_t *addr)
{
struct bluetooth_finddev_s match;
int ret;
DEBUGASSERT(conn != NULL);
match.bf_addr = addr;
match.bf_radio = NULL;
/* Search for the Bluetooth network device whose MAC is equal to the
* sockets bound local address.
*/
ret = netdev_foreach(bluetooth_dev_callback, (FAR void *)&match);
if (ret == 1)
{
DEBUGASSERT(match.bf_radio != NULL);
return match.bf_radio;
}
return NULL;
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* net/bluetooth/bluetooth_initialize.c
*
* 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 "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_initialize()
*
* Description:
* Initialize the Bluetooth socket support. Called once and only
* from the network initialization logic.
*
* Assumptions:
* Called early in the initialization sequence
*
****************************************************************************/
void bluetooth_initialize(void)
{
/* Initialize connection structions */
bluetooth_conn_initialize();
/* Initialize the container allocator */
bluetooth_container_initialize();
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* 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/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);
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);
}
}
/* 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 */
/****************************************************************************
* net/bluetooth/bluetooth_poll.c
* Poll for the availability of ougoing Bluetooth frames
*
* 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 <assert.h>
#include <debug.h>
#include <nuttx/net/netconfig.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include "devif/devif.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_poll
*
* Description:
* Poll a packet "connection" structure for availability of TX data
*
* Input Parameters:
* dev - The device driver structure to use in the send operation
* conn - The packet "connection" to poll for TX data
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void bluetooth_poll(FAR struct net_driver_s *dev,
FAR struct bluetooth_conn_s *conn)
{
FAR struct radio_driver_s *radio;
DEBUGASSERT(dev != NULL && conn != NULL);
radio = (FAR struct radio_driver_s *)dev;
/* Verify that the packet connection is valid */
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;
/* Perform the application callback */
/* REVISIT: Need to pass the meta data and the IOB through the callback */
#warning Missing logic
/* Perform the application callback */
(void)bluetooth_callback(radio, conn, BLUETOOTH_POLL);
}
}
#endif /* CONFIG_NET && CONFIG_NET_PKT */
/****************************************************************************
* net/socket/bluetooth_recvfrom.c
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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 <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <debug.h>
#include <assert.h>
#include <netpacket/bluetooth.h>
#include <arch/irq.h>
#include <nuttx/clock.h>
#include <nuttx/semaphore.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bt_hci.h>
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "socket/socket.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Private Types
****************************************************************************/
struct bluetooth_recvfrom_s
{
FAR struct socket *ir_sock; /* Points to the parent socket structure */
FAR struct devif_callback_s *ir_cb; /* Reference to callback instance */
FAR struct sockaddr *ir_from; /* Location to return the from address */
FAR uint8_t *ir_buffer; /* Pointer to receive buffer */
size_t ir_buflen; /* Length of receive buffer */
sem_t ir_sem; /* Semaphore signals recv completion */
ssize_t ir_result; /* Success:size, failure:negated errno */
};
/****************************************************************************
* Private 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_recvfrom_sender
*
* Description:
* Perform the reception operation if there are any queued frames in the
* RX frame queue.
*
* Input Parameters:
*
* Returned Value:
*
* Assumptions:
* The network is lockec
*
****************************************************************************/
static ssize_t bluetooth_recvfrom_rxqueue(FAR struct radio_driver_s *radio,
FAR struct bluetooth_recvfrom_s *pstate)
{
FAR struct bluetooth_container_s *container;
FAR struct sockaddr_bt_s *iaddr;
FAR struct bluetooth_conn_s *conn;
FAR struct iob_s *iob;
size_t copylen;
int ret = -EAGAIN;
/* Check if there is anyting in in the RX input queue */
DEBUGASSERT(pstate != NULL && pstate->ir_sock != NULL);
conn = (FAR struct bluetooth_conn_s *)pstate->ir_sock->s_conn;
DEBUGASSERT(conn != NULL);
if (conn->bc_rxhead != NULL)
{
/* Remove the container from the 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;
}
#if CONFIG_NET_BLUETOOTH_BACKLOG > 0
/* Decrement the count of frames in the queue. */
DEBUGASSERT(conn->bc_backlog > 0);
conn->bc_backlog--;
DEBUGASSERT((int)conn->bc_backlog == bluetooth_count_frames(conn));
#endif
/* Extract the IOB containing the frame from the container */
iob = container->bn_iob;
container->bn_iob = NULL;
DEBUGASSERT(iob != NULL);
/* Copy the new packet data into the user buffer */
copylen = iob->io_len - iob->io_offset;
memcpy(pstate->ir_buffer, &iob->io_data[iob->io_offset], copylen);
ninfo("Received %d bytes\n", (int)copylen);
ret = copylen;
/* If a 'from' address poiner was supplied, copy the source address
* in the container there.
*/
if (pstate->ir_from != NULL)
{
iaddr = (FAR struct sockaddr_bt_s *)pstate->ir_from;
iaddr->bt_family = AF_BLUETOOTH;
BLUETOOTH_ADDRCOPY(&iaddr->bt_bdaddr, &container->bn_raddr);
iaddr->bt_channel = container->bn_channel;
}
/* Free both the IOB and the container */
iob_free(iob);
bluetooth_container_free(container);
}
return ret;
}
/****************************************************************************
* Name: bluetooth_recvfrom_eventhandler
*
* Description:
*
* Input Parameters:
*
* Returned Value:
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static uint16_t bluetooth_recvfrom_eventhandler(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv,
uint16_t flags)
{
FAR struct bluetooth_recvfrom_s *pstate;
FAR struct radio_driver_s *radio;
ssize_t ret;
ninfo("flags: %04x\n", flags);
DEBUGASSERT(pvpriv != NULL && dev != NULL && pvconn != NULL);
/* Ignore polls from non Bluetooth network drivers */
if (dev->d_lltype != NET_LL_BLUETOOTH)
{
return flags;
}
/* Make sure that this is the driver to which the socket is bound. */
#warning Missing logic
pstate = (FAR struct bluetooth_recvfrom_s *)pvpriv;
radio = (FAR struct radio_driver_s *)dev;
/* 'pstate' might be null in some race conditions (?) */
if (pstate != NULL)
{
/* If a new packet is available, then complete the read action. */
if ((flags & BLUETOOTH_NEWDATA) != 0)
{
/* Attempt to receive the frame */
ret = bluetooth_recvfrom_rxqueue(radio, pstate);
if (ret > 0)
{
/* Don't allow any further call backs. */
pstate->ir_cb->flags = 0;
pstate->ir_cb->priv = NULL;
pstate->ir_cb->event = NULL;
pstate->ir_result = ret;
/* indicate that the data has been consumed */
flags &= ~BLUETOOTH_NEWDATA;
/* Wake up the waiting thread, returning the number of bytes
* actually read.
*/
nxsem_post(&pstate->ir_sem);
}
}
}
return flags;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_recvfrom
*
* Description:
* Implements the socket recvfrom interface for the case of the AF_INET
* and AF_INET6 address families. bluetooth_recvfrom() receives messages from
* a socket, and may be used to receive data on a socket whether or not it
* is connection-oriented.
*
* If 'from' is not NULL, and the underlying protocol provides the source
* address, this source address is filled in. The argument 'fromlen' is
* initialized to the size of the buffer associated with from, and
* modified on return to indicate the actual size of the address stored
* there.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Buffer to receive data
* len Length of buffer
* flags Receive flags
* from Address of source (may be NULL)
* fromlen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters received. If no data is
* available to be received and the peer has performed an orderly shutdown,
* recv() will return 0. Otherwise, on errors, a negated errno value is
* returned (see recvfrom() for the list of appropriate error values).
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
ssize_t bluetooth_recvfrom(FAR struct socket *psock, FAR void *buf,
size_t len, int flags, FAR struct sockaddr *from,
FAR socklen_t *fromlen)
{
FAR struct bluetooth_conn_s *conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
FAR struct radio_driver_s *radio;
struct bluetooth_recvfrom_s state;
ssize_t ret;
/* If a 'from' address has been provided, verify that it is large
* enough to hold this address family.
*/
if (from != NULL && *fromlen < sizeof(struct sockaddr_bt_s))
{
return -EINVAL;
}
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Unsupported socket type: %d\n", psock->s_type);
return -EPROTONOSUPPORT;
}
/* Perform the packet recvfrom() operation */
/* Initialize the state structure. This is done with the network
* locked because we don't want anything to happen until we are ready.
*/
net_lock();
memset(&state, 0, sizeof(struct bluetooth_recvfrom_s));
state.ir_buflen = len;
state.ir_buffer = buf;
state.ir_sock = psock;
state.ir_from = from;
/* Get the device driver that will service this transfer */
radio = bluetooth_find_device(conn, &conn->bc_laddr);
if (radio == NULL)
{
ret = -ENODEV;
goto errout_with_lock;
}
/* Before we wait for data, let's check if there are already frame(s)
* waiting in the RX queue.
*/
ret = bluetooth_recvfrom_rxqueue(radio, &state);
if (ret > 0)
{
/* Good newe! We have a frame and we are done. */
net_unlock();
return ret;
}
/* We will have to wait. This semaphore is used for signaling and,
* hence, should not have priority inheritance enabled.
*/
(void)nxsem_init(&state.ir_sem, 0, 0); /* Doesn't really fail */
(void)nxsem_setprotocol(&state.ir_sem, SEM_PRIO_NONE);
/* Set the socket state to receiving */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_RECV);
/* Set up the callback in the connection */
state.ir_cb = bluetooth_callback_alloc(&radio->r_dev, conn);
if (state.ir_cb)
{
state.ir_cb->flags = (BLUETOOTH_NEWDATA | BLUETOOTH_POLL);
state.ir_cb->priv = (FAR void *)&state;
state.ir_cb->event = bluetooth_recvfrom_eventhandler;
/* Wait for either the receive to complete or for an error/timeout to
* occur. NOTES: (1) net_lockedwait will also terminate if a signal
* is received, (2) the network is locked! It will be un-locked while
* the task sleeps and automatically re-locked when the task restarts.
*/
(void)net_lockedwait(&state.ir_sem);
/* Make sure that no further events are processed */
bluetooth_callback_free(&radio->r_dev, conn, state.ir_cb);
ret = state.ir_result;
}
else
{
ret = -EBUSY;
}
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
nxsem_destroy(&state.ir_sem);
errout_with_lock:
net_unlock();
return ret;
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* net/bluetooth/bluetooth_sendto.c
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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 <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <netpacket/bluetooth.h>
#include <arch/irq.h>
#include <nuttx/clock.h>
#include <nuttx/semaphore.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/net/net.h>
#include <nuttx/net/ip.h>
#include <nuttx/wireless/bt_hci.h>
#include "netdev/netdev.h"
#include "devif/devif.h"
#include "socket/socket.h"
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure holds the state of the send operation until it can be
* operated upon from the interrupt level.
*/
struct bluetooth_sendto_s
{
FAR struct socket *is_sock; /* Points to the parent socket structure */
FAR struct devif_callback_s *is_cb; /* Reference to callback instance */
bt_addr_t is_destaddr; /* Frame destination address */
uint8_t is_channel; /* Frame destination channel */
sem_t is_sem; /* Used to wake up the waiting thread */
FAR const uint8_t *is_buffer; /* User buffer of data to send */
size_t is_buflen; /* Number of bytes in the is_buffer */
ssize_t is_sent; /* The number of bytes sent (or error) */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_sendto_eventhandler
****************************************************************************/
static uint16_t bluetooth_sendto_eventhandler(FAR struct net_driver_s *dev,
FAR void *pvconn,
FAR void *pvpriv,
uint16_t flags)
{
FAR struct radio_driver_s *radio;
FAR struct bluetooth_sendto_s *pstate;
struct bluetooth_frame_meta_s meta;
FAR struct iob_s *iob;
int hdrlen;
int ret;
DEBUGASSERT(pvpriv != NULL && dev != NULL && pvconn != NULL);
/* Ignore polls from non Bluetooth network drivers */
if (dev->d_lltype != NET_LL_BLUETOOTH)
{
return flags;
}
/* Make sure that this is the driver to which the socket is connected. */
#warning Missing logic
pstate = (FAR struct bluetooth_sendto_s *)pvpriv;
radio = (FAR struct radio_driver_s *)dev;
ninfo("flags: %04x sent: %d\n", flags, pstate->is_sent);
if (pstate != NULL && (flags & BLUETOOTH_POLL) != 0)
{
/* Initialize the meta data */
BLUETOOTH_ADDRCOPY(&meta.bm_raddr, &pstate->is_destaddr);
meta.bm_channel = pstate->is_channel;
/* Get the Bluetooth MAC header length */
hdrlen = radio->r_get_mhrlen(radio, &meta);
if (hdrlen < 0)
{
nerr("ERROR: Failed to get header length: %d\n", hdrlen);
ret = hdrlen;
goto errout;
}
/* Verify that the user buffer can fit within the frame with this
* MAC header.
*/
DEBUGASSERT(BLUETOOTH_MAX_FRAMELEN <= CONFIG_IOB_BUFSIZE);
if (pstate->is_buflen + hdrlen > BLUETOOTH_MAX_FRAMELEN)
{
nerr("ERROR: User buffer will not fit into the frame: %u > %u\n",
(unsigned int)(pstate->is_buflen + hdrlen),
(unsigned int)CONFIG_IOB_BUFSIZE);
ret = -E2BIG;
goto errout;
}
/* Allocate an IOB to hold the frame data */
iob = iob_alloc(0);
if (iob == NULL)
{
nwarn("WARNING: Failed to allocate IOB\n");
return flags;
}
/* Initialize the IOB */
iob->io_offset = hdrlen;
iob->io_len = pstate->is_buflen + hdrlen;
iob->io_pktlen = pstate->is_buflen + hdrlen;
/* Copy the user data into the IOB */
memcpy(&iob->io_data[hdrlen], pstate->is_buffer, pstate->is_buflen);
/* And submit the IOB to the network driver */
ret = radio->r_req_data(radio, &meta, iob);
if (ret < 0)
{
nerr("ERROR: r_req_data() failed: %d\n", ret);
goto errout;
}
/* Save the successful result */
pstate->is_sent = pstate->is_buflen;
/* Don't allow any further call backs. */
pstate->is_cb->flags = 0;
pstate->is_cb->priv = NULL;
pstate->is_cb->event = NULL;
/* Wake up the waiting thread */
nxsem_post(&pstate->is_sem);
}
return flags;
errout:
/* Don't allow any further call backs. */
pstate->is_cb->flags = 0;
pstate->is_cb->priv = NULL;
pstate->is_cb->event = NULL;
pstate->is_sent = ret;
/* Wake up the waiting thread */
nxsem_post(&pstate->is_sem);
return flags;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: psock_bluetooth_sendto
*
* Description:
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
* may be returned when they are not NULL and 0), and the error ENOTCONN is
* returned when the socket was not actually connected.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters sent. On error,
* a negated errno value is retruend. See sendto() for the complete list
* of return values.
*
****************************************************************************/
ssize_t psock_bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
{
FAR struct sockaddr_bt_s *destaddr;
FAR struct radio_driver_s *radio;
FAR struct bluetooth_conn_s *conn;
struct bluetooth_sendto_s state;
int ret = OK;
/* Verify that the sockfd corresponds to valid, allocated socket */
if (psock == NULL || psock->s_crefs <= 0)
{
return -EBADF;
}
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
/* Verify that the address is large enough to be a valid PF_BLUETOOTH
* address.
*/
if (tolen < sizeof(bt_addr_t))
{
return -EDESTADDRREQ;
}
/* Get the device driver that will service this transfer */
radio = bluetooth_find_device(conn, &conn->bc_laddr);
if (radio == NULL)
{
return -ENODEV;
}
/* Set the socket state to sending */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND);
/* Perform the send operation */
/* Initialize the state structure. This is done with interrupts
* disabled because we don't want anything to happen until we
* are ready.
*/
net_lock();
memset(&state, 0, sizeof(struct bluetooth_sendto_s));
/* This semaphore is used for signaling and, hence, should not have
* priority inheritance enabled.
*/
(void)nxsem_init(&state.is_sem, 0, 0); /* Doesn't really fail */
(void)nxsem_setprotocol(&state.is_sem, SEM_PRIO_NONE);
state.is_sock = psock; /* Socket descriptor to use */
state.is_buflen = len; /* Number of bytes to send */
state.is_buffer = buf; /* Buffer to send from */
/* Copy the destination address */
destaddr = (FAR struct sockaddr_bt_s *)to;
memcpy(&state.is_destaddr, &destaddr->bt_bdaddr,
sizeof(bt_addr_t));
if (len > 0)
{
/* Allocate resource to receive a callback */
state.is_cb = bluetooth_callback_alloc(&radio->r_dev, conn);
if (state.is_cb)
{
/* Set up the callback in the connection */
state.is_cb->flags = PKT_POLL;
state.is_cb->priv = (FAR void *)&state;
state.is_cb->event = bluetooth_sendto_eventhandler;
/* Notify the device driver that new TX data is available. */
netdev_txnotify_dev(&radio->r_dev);
/* Wait for the send to complete or an error to occur: NOTES: (1)
* net_lockedwait will also terminate if a signal is received, (2)
* interrupts may be disabled! They will be re-enabled while the
* task sleeps and automatically re-enabled when the task restarts.
*/
ret = net_lockedwait(&state.is_sem);
/* Make sure that no further interrupts are processed */
bluetooth_callback_free(&radio->r_dev, conn, state.is_cb);
}
}
nxsem_destroy(&state.is_sem);
net_unlock();
/* Set the socket state to idle */
psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
/* Check for a errors, Errors are signaled by negative errno values
* for the send length
*/
if (state.is_sent < 0)
{
return state.is_sent;
}
/* If net_lockedwait failed, then we were probably reawakened by a signal. In
* this case, net_lockedwait will have returned negated errno appropriately.
*/
if (ret < 0)
{
return ret;
}
/* Return the number of bytes actually sent */
return state.is_sent;
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* net/socket/bluetooth_sockif.c
*
* 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. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "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
* COPYRIGHT OWNER OR CONTRIBUTORS 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 <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <socket/socket.h>
#include <netpacket/bluetooth.h>
#include <nuttx/net/net.h>
#include <nuttx/net/radiodev.h>
#include <nuttx/net/bluetooth.h>
#include <nuttx/wireless/bt_hci.h>
#include "bluetooth/bluetooth.h"
#ifdef CONFIG_NET_BLUETOOTH
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int bluetooth_setup(FAR struct socket *psock, int protocol);
static sockcaps_t bluetooth_sockcaps(FAR struct socket *psock);
static void bluetooth_addref(FAR struct socket *psock);
static int bluetooth_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen);
static int bluetooth_getsockname(FAR struct socket *psock,
FAR struct sockaddr *addr, FAR socklen_t *addrlen);
static int bluetooth_listen(FAR struct socket *psock, int backlog);
static int bluetooth_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen);
static int bluetooth_accept(FAR struct socket *psock,
FAR struct sockaddr *addr, FAR socklen_t *addrlen,
FAR struct socket *newsock);
#ifndef CONFIG_DISABLE_POLL
static int bluetooth_poll_local(FAR struct socket *psock,
FAR struct pollfd *fds, bool setup);
#endif
static ssize_t bluetooth_send(FAR struct socket *psock,
FAR const void *buf, size_t len, int flags);
static ssize_t bluetooth_sendto(FAR struct socket *psock,
FAR const void *buf, size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen);
static int bluetooth_close(FAR struct socket *psock);
/****************************************************************************
* Public Data
****************************************************************************/
const struct sock_intf_s g_bluetooth_sockif =
{
bluetooth_setup, /* si_setup */
bluetooth_sockcaps, /* si_sockcaps */
bluetooth_addref, /* si_addref */
bluetooth_bind, /* si_bind */
bluetooth_getsockname, /* si_getsockname */
bluetooth_listen, /* si_listen */
bluetooth_connect, /* si_connect */
bluetooth_accept, /* si_accept */
#ifndef CONFIG_DISABLE_POLL
bluetooth_poll_local, /* si_poll */
#endif
bluetooth_send, /* si_send */
bluetooth_sendto, /* si_sendto */
#ifdef CONFIG_NET_SENDFILE
NULL, /* si_sendfile */
#endif
bluetooth_recvfrom, /* si_recvfrom */
bluetooth_close /* si_close */
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: bluetooth_sockif_alloc
*
* Description:
* Allocate and attach a PF_BLUETOOTH connection structure.
*
* Assumptions:
* The network is locked
*
****************************************************************************/
static int bluetooth_sockif_alloc(FAR struct socket *psock)
{
/* Allocate the packet socket connection structure and save in the new
* socket instance.
*/
FAR struct bluetooth_conn_s *conn = bluetooth_conn_alloc();
if (conn == NULL)
{
/* Failed to reserve a connection structure */
return -ENOMEM;
}
/* Set the reference count on the connection structure. This reference
* count will be incremented only if the socket is dup'ed
*/
DEBUGASSERT(conn->bc_crefs == 0);
conn->bc_crefs = 1;
/* Save the pre-allocated connection in the socket structure */
psock->s_conn = conn;
return OK;
}
/****************************************************************************
* Name: bluetooth_setup
*
* Description:
* Called for socket() to verify that the provided socket type and
* protocol are usable by this address family. Perform any family-
* specific socket fields.
*
* Input Parameters:
* psock A pointer to a user allocated socket structure to be
* initialized.
* protocol (see sys/socket.h)
*
* Returned Value:
* Zero (OK) is returned on success. Otherwise, a negater errno value is
* returned.
*
****************************************************************************/
static int bluetooth_setup(FAR struct socket *psock, int protocol)
{
/* Allocate the appropriate connection structure. This reserves the
* the connection structure is is unallocated at this point. It will
* not actually be initialized until the socket is connected.
*
* Only SOCK_RAW is supported
*/
if (psock->s_type == SOCK_RAW)
{
return bluetooth_sockif_alloc(psock);
}
else
{
return -EPROTONOSUPPORT;
}
}
/****************************************************************************
* Name: bluetooth_sockcaps
*
* Description:
* Return the bit encoded capabilities of this socket.
*
* Input Parameters:
* psock - Socket structure of the socket whose capabilities are being
* queried.
*
* Returned Value:
* The set of socket cababilities is returned.
*
****************************************************************************/
static sockcaps_t bluetooth_sockcaps(FAR struct socket *psock)
{
return 0;
}
/****************************************************************************
* Name: bluetooth_addref
*
* Description:
* Increment the refernce count on the underlying connection structure.
*
* Input Parameters:
* psock - Socket structure of the socket whose reference count will be
* incremented.
*
* Returned Value:
* None
*
****************************************************************************/
static void bluetooth_addref(FAR struct socket *psock)
{
FAR struct bluetooth_conn_s *conn;
DEBUGASSERT(psock != NULL && psock->s_conn != NULL &&
psock->s_type == SOCK_RAW);
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
DEBUGASSERT(conn->bc_crefs > 0 && conn->bc_crefs < 255);
conn->bc_crefs++;
}
/****************************************************************************
* Name: bluetooth_connect
*
* Description:
* bluetooth_connect() connects the local socket referred to by the structure
* 'psock' to the address specified by 'addr'. The addrlen argument
* specifies the size of 'addr'. The format of the address in 'addr' is
* determined by the address space of the socket 'psock'.
*
* Generally, connection-based protocol sockets may successfully
* bluetooth_connect() only once; connectionless protocol sockets may use
* bluetooth_connect() multiple times to change their association.
* Connectionless sockets may dissolve the association by connecting to
* an address with the bt_family member of sockaddr set to AF_UNSPEC.
*
* Input Parameters:
* psock Pointer to a socket structure initialized by psock_socket()
* addr Server address (form depends on type of socket)
* addrlen Length of actual 'addr'
*
* Returned Value:
* 0 on success; a negated errno value on failue. See connect() for the
* list of appropriate errno values to be returned.
*
****************************************************************************/
static int bluetooth_connect(FAR struct socket *psock,
FAR const struct sockaddr *addr,
socklen_t addrlen)
{
FAR struct bluetooth_conn_s *conn;
FAR struct sockaddr_bt_s *btaddr;
int ret;
DEBUGASSERT(psock != NULL || addr != NULL);
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
/* Verify the address family */
if (addr->sa_family == AF_BLUETOOTH)
{
/* Save the "connection" address */
btaddr = (FAR struct sockaddr_bt_s *)addr;
memcpy(&conn->bc_raddr, &btaddr->bt_bdaddr, sizeof(bt_addr_t));
conn->bc_channel = btaddr->bt_channel;
/* Mark the socket as connected. */
psock->s_flags |= _SF_CONNECTED;
ret = OK;
}
else
{
/* The specified address is not a valid address for the address family
* of the specified socket.
*/
ret = -EAFNOSUPPORT;
}
return ret;
}
/****************************************************************************
* Name: bluetooth_accept
*
* Description:
* The bluetooth_accept function is used with connection-based socket types
* (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first
* connection request on the queue of pending connections, creates a new
* connected socket with mostly the same properties as 'sockfd', and
* allocates a new socket descriptor for the socket, which is returned. The
* newly created socket is no longer in the listening state. The original
* socket 'sockfd' is unaffected by this call. Per file descriptor flags
* are not inherited across an bluetooth_accept.
*
* The 'sockfd' argument is a socket descriptor that has been created with
* socket(), bound to a local address with bind(), and is listening for
* connections after a call to listen().
*
* On return, the 'addr' structure is filled in with the address of the
* connecting entity. The 'addrlen' argument initially contains the size
* of the structure pointed to by 'addr'; on return it will contain the
* actual length of the address returned.
*
* If no pending connections are present on the queue, and the socket is
* not marked as non-blocking, bluetooth_accept blocks the caller until a
* connection is present. If the socket is marked non-blocking and no
* pending connections are present on the queue, bluetooth_accept returns
* EAGAIN.
*
* Input Parameters:
* psock Reference to the listening socket structure
* addr Receives the address of the connecting client
* addrlen Input: allocated size of 'addr', Return: returned size of 'addr'
* newsock Location to return the accepted socket information.
*
* Returned Value:
* Returns 0 (OK) on success. On failure, it returns a negated errno
* value. See accept() for a desrciption of the approriate error value.
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static int bluetooth_accept(FAR struct socket *psock,
FAR struct sockaddr *addr,
FAR socklen_t *addrlen,
FAR struct socket *newsock)
{
return -EAFNOSUPPORT;
}
/****************************************************************************
* Name: bluetooth_bind
*
* Description:
* bluetooth_bind() gives the socket 'psock' the local address 'addr'.
* 'addr' is 'addrlen' bytes long. Traditionally, this is called
* "assigning a name to a socket." When a socket is created with
* socket(), it exists in a name space (address family) but has no name
* assigned.
*
* Input Parameters:
* psock Socket structure of the socket to bind
* addr Socket local address
* addrlen Length of 'addr'
*
* Returned Value:
* 0 on success; A negated errno value is returned on failure. See
* bind() for a list a appropriate error values.
*
****************************************************************************/
static int bluetooth_bind(FAR struct socket *psock,
FAR const struct sockaddr *addr, socklen_t addrlen)
{
FAR const struct sockaddr_bt_s *iaddr;
FAR struct radio_driver_s *radio;
FAR struct bluetooth_conn_s *conn;
DEBUGASSERT(psock != NULL && addr != NULL);
/* Verify that a valid address has been provided */
if (addr->sa_family != AF_BLUETOOTH ||
addrlen < sizeof(struct sockaddr_bt_s))
{
nerr("ERROR: Invalid family: %u or address length: %d < %d\n",
addr->sa_family, addrlen, sizeof(struct sockaddr_ll));
return -EBADF;
}
/* Bind a PF_BLUETOOTH socket to an network device.
*
* Only SOCK_RAW is supported
*/
if (psock->s_type != SOCK_RAW)
{
nerr("ERROR: Invalid socket type: %u\n", psock->s_type);
return -EBADF;
}
/* Verify that the socket is not already bound. */
if (_SS_ISBOUND(psock->s_flags))
{
nerr("ERROR: Already bound\n");
return -EINVAL;
}
iaddr = (FAR const struct sockaddr_bt_s *)addr;
/* Very that some address was provided */
/* REVISIT: Currently and explict address must be assigned. Should we
* support some moral equivalent to INADDR_ANY?
*/
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
/* Find the device associated with the requested address */
radio = bluetooth_find_device(conn, &iaddr->bt_bdaddr);
if (radio == NULL)
{
nerr("ERROR: No radio at this address\n");
return -ENODEV;
}
/* Save the address as the socket's local address */
memcpy(&conn->bc_laddr, &iaddr->bt_bdaddr, sizeof(bt_addr_t));
/* Mark the socket bound */
psock->s_flags |= _SF_BOUND;
return OK;
}
/****************************************************************************
* Name: bluetooth_getsockname
*
* Description:
* The bluetooth_getsockname() function retrieves the locally-bound name of the
* specified packet socket, stores this address in the sockaddr structure
* pointed to by the 'addr' argument, and stores the length of this
* address in the object pointed to by the 'addrlen' argument.
*
* If the actual length of the address is greater than the length of the
* supplied sockaddr structure, the stored address will be truncated.
*
* If the socket has not been bound to a local name, the value stored in
* the object pointed to by address is unspecified.
*
* Input Parameters:
* psock Socket structure of the socket to be queried
* addr sockaddr structure to receive data [out]
* addrlen Length of sockaddr structure [in/out]
*
* Returned Value:
* On success, 0 is returned, the 'addr' argument points to the address
* of the socket, and the 'addrlen' argument points to the length of the
* address. Otherwise, a negated errno value is returned. See
* getsockname() for the list of appropriate error numbers.
*
****************************************************************************/
static int bluetooth_getsockname(FAR struct socket *psock,
FAR struct sockaddr *addr, FAR
socklen_t *addrlen)
{
FAR struct bluetooth_conn_s *conn;
FAR struct sockaddr_bt_s tmp;
socklen_t copylen;
DEBUGASSERT(psock != NULL && addr != NULL && addrlen != NULL);
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
/* Create a copy of the full address on the stack */
tmp.bt_family = AF_BLUETOOTH;
memcpy(&tmp.bt_bdaddr, &conn->bc_laddr, sizeof(bt_addr_t));
/* Copy to the user buffer, truncating if necessary */
copylen = sizeof(struct sockaddr_bt_s);
if (copylen > *addrlen)
{
copylen = *addrlen;
}
memcpy(addr, &tmp, copylen);
/* Return the actual size transferred */
*addrlen = copylen;
return OK;
}
/****************************************************************************
* Name: bluetooth_listen
*
* Description:
* To accept connections, a socket is first created with psock_socket(), a
* willingness to accept incoming connections and a queue limit for
* incoming connections are specified with psock_listen(), and then the
* connections are accepted with psock_accept(). For the case of
* PF_BLUETOOTH sockets, psock_listen() calls this function. The listen()
* call does not apply only to PF_BLUETOOTH sockets.
*
* Input Parameters:
* psock Reference to an internal, boound socket structure.
* backlog The maximum length the queue of pending connections may grow.
* If a connection request arrives with the queue full, the client
* may receive an error with an indication of ECONNREFUSED or,
* if the underlying protocol supports retransmission, the request
* may be ignored so that retries succeed.
*
* Returned Value:
* On success, zero is returned. On error, a negated errno value is
* returned. See list() for the set of appropriate error values.
*
****************************************************************************/
int bluetooth_listen(FAR struct socket *psock, int backlog)
{
return -EOPNOTSUPP;
}
/****************************************************************************
* Name: bluetooth_poll
*
* Description:
* The standard poll() operation redirects operations on socket descriptors
* to net_poll which, indiectly, calls to function.
*
* Input Parameters:
* psock - An instance of the internal socket structure.
* fds - The structure describing the events to be monitored, OR NULL if
* this is a request to stop monitoring events.
* setup - true: Setup up the poll; false: Teardown the poll
*
* Returned Value:
* 0: Success; Negated errno on failure
*
****************************************************************************/
#ifndef CONFIG_DISABLE_POLL
static int bluetooth_poll_local(FAR struct socket *psock,
FAR struct pollfd *fds, bool setup)
{
/* We should need to support some kind of write ahead buffering for this
* feature.
*/
#warning Missing logic
return -ENOSYS;
}
#endif /* !CONFIG_DISABLE_POLL */
/****************************************************************************
* Name: bluetooth_send
*
* Description:
* Socket send() method for the PF_BLUETOOTH socket.
*
* Input Parameters:
* psock An instance of the internal socket structure.
* buf Data to send
* len Length of data to send
* flags Send flags
*
* Returned Value:
* On success, returns the number of characters sent. On error, a negated
* errno value is returned (see send() for the list of appropriate error
* values.
*
****************************************************************************/
static ssize_t bluetooth_send(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags)
{
struct sockaddr_bt_s to;
FAR struct bluetooth_conn_s *conn;
ssize_t ret;
DEBUGASSERT(psock != NULL || buf != NULL);
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);
/* Only SOCK_RAW is supported */
if (psock->s_type == SOCK_RAW)
{
/* send() may be used only if the socket is has been connected. */
if (!_SS_ISCONNECTED( psock->s_flags))
{
ret = -ENOTCONN;
}
else
{
to.bt_family = AF_BLUETOOTH;
memcpy(&to.bt_bdaddr, &conn->bc_raddr, sizeof(bt_addr_t));
to.bt_channel = conn->bc_channel;
/* Then perform the send() as sendto() */
ret = psock_bluetooth_sendto(psock, buf, len, flags,
(FAR const struct sockaddr *)&to,
sizeof(struct sockaddr_bt_s));
}
}
else
{
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and
* no peer address is set.
*/
ret = -EDESTADDRREQ;
}
return ret;
}
/****************************************************************************
* Name: bluetooth_sendto
*
* Description:
* Implements the sendto() operation for the case of the PF_BLUETOOTH
* socket.
*
* Input Parameters:
* psock A pointer to a NuttX-specific, internal socket structure
* buf Data to send
* len Length of data to send
* flags Send flags
* to Address of recipient
* tolen The length of the address structure
*
* Returned Value:
* On success, returns the number of characters sent. On error, a negated
* errno value is returned (see send_to() for the list of appropriate error
* values.
*
****************************************************************************/
static ssize_t bluetooth_sendto(FAR struct socket *psock, FAR const void *buf,
size_t len, int flags,
FAR const struct sockaddr *to, socklen_t tolen)
{
ssize_t ret;
/* Only SOCK_RAW is supported */
if (psock->s_type == SOCK_RAW)
{
/* Raw packet send */
ret = psock_bluetooth_sendto(psock, buf, len, flags, to, tolen);
}
else
{
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and
* no peer address is set.
*/
ret = -EDESTADDRREQ;
}
return ret;
}
/****************************************************************************
* Name: bluetooth_close
*
* Description:
* Performs the close operation on a PF_BLUETOOTH socket instance
*
* Input Parameters:
* psock Socket instance
*
* Returned Value:
* 0 on success; a negated errno value is returned on any failure.
*
* Assumptions:
*
****************************************************************************/
static int bluetooth_close(FAR struct socket *psock)
{
/* Perform some pre-close operations for the PF_BLUETOOTH address type */
switch (psock->s_type)
{
/* Only SOCK_RAW is supported */
case SOCK_RAW:
{
FAR struct bluetooth_conn_s *conn = psock->s_conn;
/* Is this the last reference to the connection structure (there
* could be more if the socket was dup'ed).
*/
if (conn->bc_crefs <= 1)
{
/* Yes... free the connection structure */
conn->bc_crefs = 0; /* No more references on the connection */
bluetooth_conn_free(psock->s_conn); /* Free network resources */
}
else
{
/* No.. Just decrement the reference count */
conn->bc_crefs--;
}
return OK;
}
default:
return -EBADF;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
#endif /* CONFIG_NET_BLUETOOTH */
......@@ -74,7 +74,8 @@
* TCP_NEWDATA IN: Set to indicate that the peer has sent us new data.
* UDP_NEWDATA OUT: Cleared (only) by the socket layer logic to indicate
* PKT_NEWDATA that the new data was consumed, suppressing further
* IEEE802154_NEWDATA attempts to process the new data.
* BLUETOOTH_NEWDATA attempts to process the new data.
* IEEE802154_NEWDATA
*
* TCP_SNDACK IN: Not used; always zero
* OUT: Set by the socket layer if the new data was consumed
......@@ -87,8 +88,8 @@
* TCP_POLL IN: Used for polling the socket layer. This is provided
* UDP_POLL periodically from the drivers to support (1) timed
* PKT_POLL operations, and (2) to check if the socket layer has
* IEEE802154_POLL data that it wants to send. These are socket oriented
* callbacks where the context depends on the specific
* BLUETOOTH_POLL data that it wants to send. These are socket oriented
* IEEE802154_POLL callbacks where the context depends on the specific
* set
* OUT: Not used
*
......@@ -177,6 +178,7 @@
#define TCP_ACKDATA (1 << 0)
#define TCP_NEWDATA (1 << 1)
#define UDP_NEWDATA TCP_NEWDATA
#define BLUETOOTH_NEWDATA TCP_NEWDATA
#define IEEE802154_NEWDATA TCP_NEWDATA
#define PKT_NEWDATA TCP_NEWDATA
#define WPAN_NEWDATA TCP_NEWDATA
......@@ -186,6 +188,7 @@
#define TCP_POLL (1 << 4)
#define UDP_POLL TCP_POLL
#define PKT_POLL TCP_POLL
#define BLUETOOTH_POLL TCP_POLL
#define IEEE802154_POLL TCP_POLL
#define WPAN_POLL TCP_POLL
#define TCP_BACKLOG (1 << 5)
......
/****************************************************************************
* net/devif/devif_poll.c
*
* Copyright (C) 2007-2010, 2012, 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2010, 2012, 2014, 2016-2018 Gregory Nutt. All rights
* reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
......@@ -53,6 +54,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
#include "bluetooth/bluetooth.h"
#include "ieee802154/ieee802154.h"
#include "icmp/icmp.h"
#include "icmpv6/icmpv6.h"
......@@ -238,6 +240,42 @@ static int devif_poll_pkt_connections(FAR struct net_driver_s *dev,
}
#endif /* CONFIG_NET_PKT */
/****************************************************************************
* Name: devif_poll_bluetooth_connections
*
* Description:
* Poll all packet connections for available packets to send.
*
* Assumptions:
* This function is called from the MAC device driver with the network
* locked.
*
****************************************************************************/
#ifdef CONFIG_NET_BLUETOOTH
static int devif_poll_bluetooth_connections(FAR struct net_driver_s *dev,
devif_poll_callback_t callback)
{
FAR struct bluetooth_conn_s *bluetooth_conn = NULL;
int bstop = 0;
/* Traverse all of the allocated packet connections and perform the poll action */
while (!bstop && (bluetooth_conn = bluetooth_conn_next(bluetooth_conn)))
{
/* Perform the packet TX poll */
bluetooth_poll(dev, bluetooth_conn);
/* Call back into the driver */
bstop = callback(dev);
}
return bstop;
}
#endif /* CONFIG_NET_BLUETOOTH */
/****************************************************************************
* Name: devif_poll_ieee802154_connections
*
......@@ -272,7 +310,7 @@ static int devif_poll_ieee802154_connections(FAR struct net_driver_s *dev,
return bstop;
}
#endif /* CONFIG_NET_PKT */
#endif /* CONFIG_NET_IEEE802154 */
/****************************************************************************
* Name: devif_poll_icmp
......@@ -561,6 +599,15 @@ int devif_poll(FAR struct net_driver_s *dev, devif_poll_callback_t callback)
if (!bstop)
#endif
#ifdef CONFIG_NET_BLUETOOTH
{
/* Check for pending PF_BLUETOOTH socket transfer */
bstop = devif_poll_bluetooth_connections(dev, callback);
}
if (!bstop)
#endif
#ifdef CONFIG_NET_IEEE802154
{
/* Check for pending PF_IEEE802154 socket transfer */
......
......@@ -13,7 +13,7 @@ config NET_IEEE802154
---help---
Enable support for raw, IEEE 802.15.4 sockets.
Raw sockets allow receiving and transmitting IEEE 802.15.3 radio
Raw sockets allow receiving and transmitting IEEE 802.15.4 radio
frames without a layer2 protocol such as 6LoWPAN in between. Frames
received are copied into a IEEE 802.15.4 socket tap before they
enter the network. Frames written into a IEEE 802.15.4 socket will
......@@ -23,7 +23,7 @@ config NET_IEEE802154
if NET_IEEE802154
config NET_IEEE802154_FRAMELEN
int "IEEE802.15.4 Frame Length"
int "IEEE 802.15.4 Frame Length"
default 127
range 1 999999
---help---
......
......@@ -66,7 +66,7 @@
/* Frame size */
/* This maximum size of an IEEE802.15.4 frame. Certain, non-standard
/* This maximum size of an IEEE 802.15.4 frame. Certain, non-standard
* devices may exceed this value, however.
*/
......@@ -153,7 +153,6 @@ EXTERN const struct sock_intf_s g_ieee802154_sockif;
struct ieee802154_data_ind_s; /* Forward reference */
struct radio_driver_s; /* Forward reference */
struct net_driver_s; /* Forward reference */
struct eth_hdr_s; /* Forward reference */
struct socket; /* Forward reference */
struct sockaddr; /* Forward reference */
......@@ -175,7 +174,7 @@ void ieee802154_initialize(void);
* Name: ieee802154_conn_initialize
*
* Description:
* Initialize the IEEE 802.15.5 connection structure allocator. Called
* Initialize the IEEE 802.15.4 connection structure allocator. Called
* once and only from ieee802154_initialize().
*
* Assumptions:
......