mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 03:45:50 +08:00
Bluetooth: Start implementing BTPROTO_HCI socket support
Signed-off-by: Brennan Ashton <bashton@brennanashton.com>
This commit is contained in:
@@ -263,9 +263,9 @@ struct devif_callback_s; /* Forward reference */
|
|||||||
struct socket
|
struct socket
|
||||||
{
|
{
|
||||||
int16_t s_crefs; /* Reference count on the socket */
|
int16_t s_crefs; /* Reference count on the socket */
|
||||||
uint8_t s_domain; /* IP domain: PF_INET, PF_INET6, or PF_PACKET */
|
uint8_t s_domain; /* IP domain */
|
||||||
uint8_t s_type; /* Protocol type: Only SOCK_STREAM or
|
uint8_t s_type; /* Protocol type */
|
||||||
* SOCK_DGRAM */
|
uint8_t s_proto; /* Socket Protocol */
|
||||||
uint8_t s_flags; /* See _SF_* definitions */
|
uint8_t s_flags; /* See _SF_* definitions */
|
||||||
|
|
||||||
/* Socket options */
|
/* Socket options */
|
||||||
|
|||||||
+26
-38
@@ -1,35 +1,20 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* net/bluetooth/bluetooth.h
|
* net/bluetooth/bluetooth.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 2018-2019 Gregory Nutt. All rights reserved.
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
*
|
*
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* notice, this list of conditions and the following disclaimer.
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
* notice, this list of conditions and the following disclaimer in
|
* License for the specific language governing permissions and limitations
|
||||||
* the documentation and/or other materials provided with the
|
* under the License.
|
||||||
* 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.
|
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@@ -106,6 +91,7 @@ struct bluetooth_conn_s
|
|||||||
* Necessary only to support multiple
|
* Necessary only to support multiple
|
||||||
* Bluetooth devices */
|
* Bluetooth devices */
|
||||||
bt_addr_t bc_raddr; /* Connected remote address */
|
bt_addr_t bc_raddr; /* Connected remote address */
|
||||||
|
uint8_t bc_ldev; /* Locally bound device */
|
||||||
uint8_t bc_channel; /* Connection channel */
|
uint8_t bc_channel; /* Connection channel */
|
||||||
uint8_t bc_crefs; /* Reference counts on this instance */
|
uint8_t bc_crefs; /* Reference counts on this instance */
|
||||||
#if CONFIG_NET_BLUETOOTH_BACKLOG > 0
|
#if CONFIG_NET_BLUETOOTH_BACKLOG > 0
|
||||||
@@ -139,10 +125,10 @@ EXTERN const struct sock_intf_s g_bluetooth_sockif;
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct bluetooth_frame_meta_s; /* Forward reference */
|
struct bluetooth_frame_meta_s; /* Forward reference */
|
||||||
struct radio_driver_s; /* Forward reference */
|
struct radio_driver_s; /* Forward reference */
|
||||||
struct net_driver_s; /* Forward reference */
|
struct net_driver_s; /* Forward reference */
|
||||||
struct socket; /* Forward reference */
|
struct socket; /* Forward reference */
|
||||||
struct sockaddr; /* Forward reference */
|
struct sockaddr; /* Forward reference */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: bluetooth_initialize()
|
* Name: bluetooth_initialize()
|
||||||
@@ -272,7 +258,8 @@ FAR struct bluetooth_conn_s *
|
|||||||
* Name: bluetooth_callback
|
* Name: bluetooth_callback
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Inform the application holding the Bluetooth socket of a change in state.
|
* Inform the application holding the Bluetooth socket of a change in
|
||||||
|
* state.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* OK if Bluetooth has been processed, otherwise ERROR.
|
* OK if Bluetooth has been processed, otherwise ERROR.
|
||||||
@@ -291,9 +278,9 @@ uint16_t bluetooth_callback(FAR struct radio_driver_s *radio,
|
|||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Implements the socket recvfrom interface for the case of the AF_INET
|
* Implements the socket recvfrom interface for the case of the AF_INET
|
||||||
* and AF_INET6 address families. bluetooth_recvfrom() receives messages from
|
* and AF_INET6 address families. bluetooth_recvfrom() receives messages
|
||||||
* a socket, and may be used to receive data on a socket whether or not it
|
* from a socket, and may be used to receive data on a socket whether or
|
||||||
* is connection-oriented.
|
* not it is connection-oriented.
|
||||||
*
|
*
|
||||||
* If 'from' is not NULL, and the underlying protocol provides the source
|
* If 'from' is not NULL, and the underlying protocol provides the source
|
||||||
* address, this source address is filled in. The argument 'fromlen' is
|
* address, this source address is filled in. The argument 'fromlen' is
|
||||||
@@ -390,7 +377,8 @@ void bluetooth_poll(FAR struct net_driver_s *dev,
|
|||||||
ssize_t psock_bluetooth_sendto(FAR struct socket *psock,
|
ssize_t psock_bluetooth_sendto(FAR struct socket *psock,
|
||||||
FAR const void *buf,
|
FAR const void *buf,
|
||||||
size_t len, int flags,
|
size_t len, int flags,
|
||||||
FAR const struct sockaddr *to, socklen_t tolen);
|
FAR const struct sockaddr *to,
|
||||||
|
socklen_t tolen);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: bluetooth_container_initialize
|
* Name: bluetooth_container_initialize
|
||||||
@@ -428,8 +416,8 @@ void bluetooth_container_initialize(void);
|
|||||||
* None
|
* None
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* A reference to the allocated container structure. All user fields in this
|
* A reference to the allocated container structure. All user fields in
|
||||||
* structure have been zeroed. On a failure to allocate, NULL is
|
* this structure have been zeroed. On a failure to allocate, NULL is
|
||||||
* returned.
|
* returned.
|
||||||
*
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
|
|||||||
@@ -72,6 +72,18 @@ static ssize_t bluetooth_sendto(FAR struct socket *psock,
|
|||||||
FAR const struct sockaddr *to, socklen_t tolen);
|
FAR const struct sockaddr *to, socklen_t tolen);
|
||||||
static int bluetooth_close(FAR struct socket *psock);
|
static int bluetooth_close(FAR struct socket *psock);
|
||||||
|
|
||||||
|
/* Protocol Specific Interfaces */
|
||||||
|
|
||||||
|
static int bluetooth_l2cap_bind(FAR struct socket *psock,
|
||||||
|
FAR const struct sockaddr_l2 *addr, socklen_t addrlen);
|
||||||
|
static int bluetooth_hci_bind(FAR struct socket *psock,
|
||||||
|
FAR const struct sockaddr_hci *addr,
|
||||||
|
socklen_t addrlen);
|
||||||
|
static ssize_t bluetooth_l2cap_send(FAR struct socket *psock,
|
||||||
|
FAR const void *buf, size_t len, int flags);
|
||||||
|
static ssize_t bluetooth_hci_send(FAR struct socket *psock,
|
||||||
|
FAR const void *buf, size_t len, int flags);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -270,6 +282,13 @@ static int bluetooth_connect(FAR struct socket *psock,
|
|||||||
|
|
||||||
if (addr->sa_family == AF_BLUETOOTH)
|
if (addr->sa_family == AF_BLUETOOTH)
|
||||||
{
|
{
|
||||||
|
/* Verify the Protocol */
|
||||||
|
|
||||||
|
if (psock->s_proto != BTPROTO_L2CAP)
|
||||||
|
{
|
||||||
|
return -EPFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Save the "connection" address */
|
/* Save the "connection" address */
|
||||||
|
|
||||||
btaddr = (FAR struct sockaddr_l2 *)addr;
|
btaddr = (FAR struct sockaddr_l2 *)addr;
|
||||||
@@ -333,9 +352,9 @@ static int bluetooth_connect(FAR struct socket *psock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int bluetooth_accept(FAR struct socket *psock,
|
static int bluetooth_accept(FAR struct socket *psock,
|
||||||
FAR struct sockaddr *addr,
|
FAR struct sockaddr *addr,
|
||||||
FAR socklen_t *addrlen,
|
FAR socklen_t *addrlen,
|
||||||
FAR struct socket *newsock)
|
FAR struct socket *newsock)
|
||||||
{
|
{
|
||||||
return -EAFNOSUPPORT;
|
return -EAFNOSUPPORT;
|
||||||
}
|
}
|
||||||
@@ -364,22 +383,81 @@ static int bluetooth_accept(FAR struct socket *psock,
|
|||||||
static int bluetooth_bind(FAR struct socket *psock,
|
static int bluetooth_bind(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen)
|
FAR const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
FAR const struct sockaddr_l2 *iaddr;
|
|
||||||
FAR struct radio_driver_s *radio;
|
|
||||||
FAR struct bluetooth_conn_s *conn;
|
|
||||||
|
|
||||||
DEBUGASSERT(psock != NULL && addr != NULL);
|
DEBUGASSERT(psock != NULL && addr != NULL);
|
||||||
|
|
||||||
/* Verify that a valid address has been provided */
|
/* Verify that a valid address has been provided */
|
||||||
|
|
||||||
if (addr->sa_family != AF_BLUETOOTH ||
|
if (addr->sa_family != AF_BLUETOOTH)
|
||||||
addrlen < sizeof(struct sockaddr_l2))
|
|
||||||
{
|
{
|
||||||
nerr("ERROR: Invalid family: %u or address length: %d < %d\n",
|
nerr("ERROR: Invalid family: %u\n", addr->sa_family);
|
||||||
addr->sa_family, addrlen, sizeof(struct sockaddr_l2));
|
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (psock->s_proto)
|
||||||
|
{
|
||||||
|
case BTPROTO_L2CAP:
|
||||||
|
{
|
||||||
|
FAR const struct sockaddr_l2 *iaddr;
|
||||||
|
if (addrlen < sizeof(struct sockaddr_l2))
|
||||||
|
{
|
||||||
|
nerr("ERROR: Invalid address length: %d < %d\n",
|
||||||
|
addrlen, sizeof(struct sockaddr_l2));
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
iaddr = (FAR const struct sockaddr_l2 *)addr;
|
||||||
|
return bluetooth_l2cap_bind(psock, iaddr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
case BTPROTO_HCI:
|
||||||
|
{
|
||||||
|
FAR const struct sockaddr_hci *hciaddr;
|
||||||
|
if (addrlen < sizeof(struct sockaddr_hci))
|
||||||
|
{
|
||||||
|
nerr("ERROR: Invalid address length: %d < %d\n",
|
||||||
|
addrlen, sizeof(struct sockaddr_hci));
|
||||||
|
return -EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
hciaddr = (FAR const struct sockaddr_hci *)addr;
|
||||||
|
return bluetooth_hci_bind(psock, hciaddr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EPFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: bluetooth_l2cap_bind
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* bluetooth_bind() gives the socket 'psock' the local address 'iaddr'.
|
||||||
|
* 'iaddr' 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
|
||||||
|
* iaddr 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_l2cap_bind(FAR struct socket *psock,
|
||||||
|
FAR const struct sockaddr_l2 *iaddr,
|
||||||
|
socklen_t addrlen)
|
||||||
|
{
|
||||||
|
FAR struct radio_driver_s *radio;
|
||||||
|
FAR struct bluetooth_conn_s *conn;
|
||||||
|
|
||||||
/* Bind a PF_BLUETOOTH socket to an network device.
|
/* Bind a PF_BLUETOOTH socket to an network device.
|
||||||
*
|
*
|
||||||
* Only SOCK_RAW is supported
|
* Only SOCK_RAW is supported
|
||||||
@@ -399,8 +477,6 @@ static int bluetooth_bind(FAR struct socket *psock,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
iaddr = (FAR const struct sockaddr_l2 *)addr;
|
|
||||||
|
|
||||||
/* Very that some address was provided.
|
/* Very that some address was provided.
|
||||||
*
|
*
|
||||||
* REVISIT: Currently and explicit address must be assigned. Should we
|
* REVISIT: Currently and explicit address must be assigned. Should we
|
||||||
@@ -425,6 +501,60 @@ static int bluetooth_bind(FAR struct socket *psock,
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: bluetooth_l2cap_bind
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* bluetooth_bind() gives the socket 'psock' the local address 'hciaddr'.
|
||||||
|
* 'hciaddr' 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
|
||||||
|
* hciaddr 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_hci_bind(FAR struct socket *psock,
|
||||||
|
FAR const struct sockaddr_hci *hciaddr,
|
||||||
|
socklen_t addrlen)
|
||||||
|
{
|
||||||
|
FAR struct bluetooth_conn_s *conn;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
conn->bc_channel = hciaddr->hci_channel;
|
||||||
|
conn->bc_ldev = hciaddr->hci_dev;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: bluetooth_getsockname
|
* Name: bluetooth_getsockname
|
||||||
*
|
*
|
||||||
@@ -525,6 +655,11 @@ static int bluetooth_getpeername(FAR struct socket *psock,
|
|||||||
|
|
||||||
DEBUGASSERT(psock != NULL && addr != NULL && addrlen != NULL);
|
DEBUGASSERT(psock != NULL && addr != NULL && addrlen != NULL);
|
||||||
|
|
||||||
|
if (psock->s_proto != BTPROTO_L2CAP)
|
||||||
|
{
|
||||||
|
return -EPFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
|
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
|
||||||
DEBUGASSERT(conn != NULL);
|
DEBUGASSERT(conn != NULL);
|
||||||
|
|
||||||
@@ -628,51 +763,119 @@ static int bluetooth_poll_local(FAR struct socket *psock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t bluetooth_send(FAR struct socket *psock, FAR const void *buf,
|
static ssize_t bluetooth_send(FAR struct socket *psock, FAR const void *buf,
|
||||||
size_t len, int flags)
|
size_t len, int flags)
|
||||||
{
|
{
|
||||||
struct sockaddr_l2 to;
|
|
||||||
FAR struct bluetooth_conn_s *conn;
|
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
DEBUGASSERT(psock != NULL || buf != NULL);
|
DEBUGASSERT(psock != NULL || buf != NULL);
|
||||||
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
|
|
||||||
DEBUGASSERT(conn != NULL);
|
|
||||||
|
|
||||||
/* Only SOCK_RAW is supported */
|
/* Only SOCK_RAW is supported */
|
||||||
|
|
||||||
if (psock->s_type == SOCK_RAW)
|
if (psock->s_type == SOCK_RAW)
|
||||||
{
|
{
|
||||||
/* send() may be used only if the socket is has been connected. */
|
switch (psock->s_proto)
|
||||||
|
|
||||||
if (!_SS_ISCONNECTED(psock->s_flags))
|
|
||||||
{
|
{
|
||||||
ret = -ENOTCONN;
|
case BTPROTO_L2CAP:
|
||||||
}
|
{
|
||||||
else
|
ret = bluetooth_l2cap_send(psock, buf, len, flags);
|
||||||
{
|
break;
|
||||||
to.l2_family = AF_BLUETOOTH;
|
}
|
||||||
memcpy(&to.l2_bdaddr, &conn->bc_raddr, sizeof(bt_addr_t));
|
|
||||||
to.l2_cid = conn->bc_channel;
|
|
||||||
|
|
||||||
/* Then perform the send() as sendto() */
|
case BTPROTO_HCI:
|
||||||
|
{
|
||||||
|
ret = bluetooth_hci_send(psock, buf, len, flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = psock_bluetooth_sendto(psock, buf, len, flags,
|
default:
|
||||||
(FAR const struct sockaddr *)&to,
|
ret = -EPFNOSUPPORT;
|
||||||
sizeof(struct sockaddr_l2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and
|
ret = -EINVAL;
|
||||||
* no peer address is set.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ret = -EDESTADDRREQ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: bluetooth_l2cap_send
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Socket send() method for the PF_BLUETOOTH socket over BTPROTO_L2CAP.
|
||||||
|
*
|
||||||
|
* 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_l2cap_send(FAR struct socket *psock,
|
||||||
|
FAR const void *buf,
|
||||||
|
size_t len, int flags)
|
||||||
|
{
|
||||||
|
struct sockaddr_l2 to;
|
||||||
|
FAR struct bluetooth_conn_s *conn;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
conn = (FAR struct bluetooth_conn_s *)psock->s_conn;
|
||||||
|
DEBUGASSERT(conn != NULL);
|
||||||
|
|
||||||
|
if (!_SS_ISCONNECTED(psock->s_flags))
|
||||||
|
{
|
||||||
|
ret = -ENOTCONN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
to.l2_family = AF_BLUETOOTH;
|
||||||
|
memcpy(&to.l2_bdaddr, &conn->bc_raddr, sizeof(bt_addr_t));
|
||||||
|
to.l2_cid = 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_l2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: bluetooth_hci_send
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Socket send() method for the PF_BLUETOOTH socket over BTPROTO_HCI.
|
||||||
|
*
|
||||||
|
* 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_hci_send(FAR struct socket *psock,
|
||||||
|
FAR const void *buf,
|
||||||
|
size_t len, int flags)
|
||||||
|
{
|
||||||
|
#warning Missing logic
|
||||||
|
|
||||||
|
return -EPFNOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: bluetooth_sendto
|
* Name: bluetooth_sendto
|
||||||
*
|
*
|
||||||
@@ -702,9 +905,9 @@ static ssize_t bluetooth_sendto(FAR struct socket *psock,
|
|||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
|
|
||||||
/* Only SOCK_RAW is supported */
|
/* Only SOCK_RAW on L2CAP is supported */
|
||||||
|
|
||||||
if (psock->s_type == SOCK_RAW)
|
if (psock->s_type == SOCK_RAW && psock->s_proto == BTPROTO_L2CAP)
|
||||||
{
|
{
|
||||||
/* Raw packet send */
|
/* Raw packet send */
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ int psock_socket(int domain, int type, int protocol,
|
|||||||
|
|
||||||
psock->s_crefs = 1;
|
psock->s_crefs = 1;
|
||||||
psock->s_domain = domain;
|
psock->s_domain = domain;
|
||||||
|
psock->s_proto = protocol;
|
||||||
psock->s_conn = NULL;
|
psock->s_conn = NULL;
|
||||||
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS)
|
#if defined(CONFIG_NET_TCP_WRITE_BUFFERS) || defined(CONFIG_NET_UDP_WRITE_BUFFERS)
|
||||||
psock->s_sndcb = NULL;
|
psock->s_sndcb = NULL;
|
||||||
|
|||||||
@@ -120,6 +120,30 @@ static struct work_s g_hp_work;
|
|||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: bt_send
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Add the provided buffer 'buf' to the head selected buffer list 'list'
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* btdev - An instance of the low-level drivers interface structure.
|
||||||
|
* buf - The buffer to be sent by the driver
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero is returned on success; a negated errno value is returned on any
|
||||||
|
* failure.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int bt_send(FAR const struct bt_driver_s *btdev,
|
||||||
|
FAR struct bt_buf_s *buf)
|
||||||
|
{
|
||||||
|
/* TODDO: Hook here to notify hci monitor */
|
||||||
|
|
||||||
|
return btdev->send(btdev, buf);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: bt_enqueue_bufwork
|
* Name: bt_enqueue_bufwork
|
||||||
*
|
*
|
||||||
@@ -1049,6 +1073,8 @@ static void hci_rx_work(FAR void *arg)
|
|||||||
{
|
{
|
||||||
wlinfo("buf %p type %u len %u\n", buf, buf->type, buf->len);
|
wlinfo("buf %p type %u len %u\n", buf, buf->type, buf->len);
|
||||||
|
|
||||||
|
/* TODO: Hook monitor callback */
|
||||||
|
|
||||||
switch (buf->type)
|
switch (buf->type)
|
||||||
{
|
{
|
||||||
case BT_ACL_IN:
|
case BT_ACL_IN:
|
||||||
@@ -1096,6 +1122,8 @@ static void priority_rx_work(FAR void *arg)
|
|||||||
|
|
||||||
wlinfo("buf %p type %u len %u\n", buf, buf->type, buf->len);
|
wlinfo("buf %p type %u len %u\n", buf, buf->type, buf->len);
|
||||||
|
|
||||||
|
/* TODO: Hook monitor callback */
|
||||||
|
|
||||||
if (buf->type != BT_EVT)
|
if (buf->type != BT_EVT)
|
||||||
{
|
{
|
||||||
wlerr("Unknown buf type %u\n", buf->type);
|
wlerr("Unknown buf type %u\n", buf->type);
|
||||||
@@ -1684,7 +1712,7 @@ int bt_hci_cmd_send(uint16_t opcode, FAR struct bt_buf_s *buf)
|
|||||||
|
|
||||||
if (opcode == BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS)
|
if (opcode == BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS)
|
||||||
{
|
{
|
||||||
g_btdev.btdev->send(g_btdev.btdev, buf);
|
bt_send(g_btdev.btdev, buf);
|
||||||
bt_buf_release(buf);
|
bt_buf_release(buf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user