From a720984eb7b1cabd259014df0d4e9ac0ef0e94dd Mon Sep 17 00:00:00 2001 From: Lwazi Dube Date: Fri, 2 Jun 2023 22:47:14 -0400 Subject: [PATCH] wireless/bluetooth: Add a generic access service. Make NuttX peripheral visible to BLE apps. --- include/nuttx/wireless/bluetooth/bt_core.h | 16 ++ wireless/bluetooth/Kconfig | 20 ++ wireless/bluetooth/Make.defs | 2 +- wireless/bluetooth/bt_netdev.c | 9 +- wireless/bluetooth/bt_services.c | 241 +++++++++++++++++++++ 5 files changed, 282 insertions(+), 6 deletions(-) create mode 100644 wireless/bluetooth/bt_services.c diff --git a/include/nuttx/wireless/bluetooth/bt_core.h b/include/nuttx/wireless/bluetooth/bt_core.h index e13ef300fc..4b0f608965 100644 --- a/include/nuttx/wireless/bluetooth/bt_core.h +++ b/include/nuttx/wireless/bluetooth/bt_core.h @@ -217,4 +217,20 @@ static inline int bt_addr_le_to_str(FAR const bt_addr_le_t *addr, char *str, * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: bt_add_services + * + * Description: + * Register services and start advertising. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero in case of success or negative value in case of error. + * + ****************************************************************************/ + +int bt_add_services(void); + #endif /* __INCLUDE_NUTTX_WIRELESS_BLUETOOTH_BT_CORE_H */ diff --git a/wireless/bluetooth/Kconfig b/wireless/bluetooth/Kconfig index bdef26498d..d5c60c2dc5 100644 --- a/wireless/bluetooth/Kconfig +++ b/wireless/bluetooth/Kconfig @@ -60,6 +60,26 @@ menuconfig WIRELESS_BLUETOOTH_HOST BLE link-layer or to an external device over HCI UART). if WIRELESS_BLUETOOTH_HOST +config DEVICE_APPEARANCE + int "Appearance sub-category value" + default 0 + range 0 5188 + ---help--- + This value comes from the "Appearance sub-category" + section (2.6.3) in the Bluetooth Assigned Numbers document. + +config DEVICE_NAME + string "Device name" + default "Apache NuttX" + ---help--- + The device name. + +config DEVICE_LOCAL_NAME + string "Device local name" + default "NuttX" + ---help--- + The device name used for advertising. + endif # WIRELESS_BLUETOOTH_HOST config BLUETOOTH_MAX_CONN diff --git a/wireless/bluetooth/Make.defs b/wireless/bluetooth/Make.defs index e16fb7b08d..9df9daf468 100644 --- a/wireless/bluetooth/Make.defs +++ b/wireless/bluetooth/Make.defs @@ -30,7 +30,7 @@ ifeq ($(CONFIG_WIRELESS_BLUETOOTH_HOST),y) CSRCS += bt_atomic.c bt_att.c bt_conn.c bt_gatt.c CSRCS += bt_ioctl.c bt_keys.c bt_l2cap.c bt_smp.c -CSRCS += bt_uuid.c +CSRCS += bt_uuid.c bt_services.c endif diff --git a/wireless/bluetooth/bt_netdev.c b/wireless/bluetooth/bt_netdev.c index a2b5d446eb..bcf30ba384 100644 --- a/wireless/bluetooth/bt_netdev.c +++ b/wireless/bluetooth/bt_netdev.c @@ -296,21 +296,18 @@ static void btnet_l2cap_connected(FAR struct bt_conn_s *conn, FAR void *context, uint16_t cid) { wlinfo("Connected\n"); -#warning Missing logic } static void btnet_l2cap_disconnected(FAR struct bt_conn_s *conn, FAR void *context, uint16_t cid) { wlinfo("Disconnected\n"); -#warning Missing logic } static void btnet_l2cap_encrypt_change(FAR struct bt_conn_s *conn, FAR void *context, uint16_t cid) { wlinfo("Encryption change\n"); -#warning Missing logic } /**************************************************************************** @@ -463,14 +460,12 @@ static void btnet_hci_connected(FAR struct bt_conn_s *conn, FAR void *context) { wlinfo("Connected\n"); -#warning Missing logic } static void btnet_hci_disconnected(FAR struct bt_conn_s *conn, FAR void *context) { wlinfo("Disconnected\n"); -#warning Missing logic } #else @@ -1301,6 +1296,10 @@ int bt_netdev_register(FAR struct bt_driver_s *btdev) priv->bd_dev.r_dev.d_buf = g_iobuffer.rb_buf; #endif +#ifdef CONFIG_WIRELESS_BLUETOOTH_HOST + bt_add_services(); +#endif + /* Register the network device with the OS so that socket IOCTLs can be * performed */ diff --git a/wireless/bluetooth/bt_services.c b/wireless/bluetooth/bt_services.c new file mode 100644 index 0000000000..da754349d2 --- /dev/null +++ b/wireless/bluetooth/bt_services.c @@ -0,0 +1,241 @@ +/**************************************************************************** + * wireless/bluetooth/bt_services.c + * + * Copyright (c) 2016, Intel Corporation + * All rights reserved. + * + * 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 of the copyright holder 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 HOLDER 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "bt_hcicore.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GASVC 0x0001 +#define NAME_CHR (GASVC + 0x0002) +#define NAME_DSC (GASVC + 0x0003) +#define APPEARANCE_CHR (GASVC + 0x0004) +#define APPEARANCE_DSC (GASVC + 0x0005) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int read_appearance(FAR struct bt_conn_s *conn, + FAR const struct bt_gatt_attr_s *attr, + FAR void *buf, + uint8_t len, + uint16_t offset); + +static int read_name(FAR struct bt_conn_s *conn, + FAR const struct bt_gatt_attr_s *attr, + FAR void *buf, + uint8_t len, + uint16_t offset); + +static struct bt_uuid_s g_gap_uuid = +{ + .type = BT_UUID_16, + .u = + { + .u16 = BT_UUID_GAP + }, +}; + +static struct bt_uuid_s g_device_name_uuid = +{ + .type = BT_UUID_16, + .u = + { + .u16 = BT_UUID_GAP_DEVICE_NAME, + } +}; + +static struct bt_gatt_chrc_s g_name_chrc = +{ + .properties = BT_GATT_CHRC_READ, + .value_handle = NAME_DSC, + .uuid = &g_device_name_uuid, +}; + +static struct bt_uuid_s g_appeareance_uuid = +{ + .type = BT_UUID_16, + .u = + { + .u16 = BT_UUID_GAP_APPEARANCE, + } +}; + +static struct bt_gatt_chrc_s g_appearance_chrc = +{ + .properties = BT_GATT_CHRC_READ, + .value_handle = APPEARANCE_DSC, + .uuid = &g_appeareance_uuid, +}; + +static const struct bt_gatt_attr_s g_attrs[] = +{ + BT_GATT_PRIMARY_SERVICE(GASVC, &g_gap_uuid), + BT_GATT_CHARACTERISTIC(NAME_CHR, &g_name_chrc), + BT_GATT_DESCRIPTOR(NAME_DSC, &g_device_name_uuid, BT_GATT_PERM_READ, + read_name, NULL, (FAR void *)CONFIG_DEVICE_NAME), + BT_GATT_CHARACTERISTIC(APPEARANCE_CHR, &g_appearance_chrc), + BT_GATT_DESCRIPTOR(APPEARANCE_DSC, &g_appeareance_uuid, + BT_GATT_PERM_READ, read_appearance, NULL, NULL), +}; + +static const struct bt_eir_s g_ad[] = +{ + { + .len = 2, + .type = BT_EIR_FLAGS, + .data = + { + BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR + }, + }, + { + .len = 0, + .type = 0, + .data = "", + } +}; + +static const struct bt_eir_s g_sd[] = +{ + { + .len = 16, + .type = BT_EIR_NAME_COMPLETE, + .data = CONFIG_DEVICE_LOCAL_NAME, + }, + { + .len = 0, + .type = 0, + .data = "", + } +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: read_name + * + * Description: + * Read callback for name descriptor. + * + * Returned Value: + * Zero in case of success or negative value in case of error. + * + ****************************************************************************/ + +static int read_name(FAR struct bt_conn_s *conn, + FAR const struct bt_gatt_attr_s *attr, + FAR void *buf, + uint8_t len, + uint16_t offset) +{ + FAR const char *name = attr->user_data; + + return bt_gatt_attr_read(conn, attr, buf, len, offset, name, + strlen(name)); +} + +/**************************************************************************** + * Name: read_appearance + * + * Description: + * Read callback for appearance descriptor. + * + * Returned Value: + * Zero in case of success or negative value in case of error. + * + ****************************************************************************/ + +static int read_appearance(FAR struct bt_conn_s *conn, + FAR const struct bt_gatt_attr_s *attr, + FAR void *buf, + uint8_t len, + uint16_t offset) +{ + uint16_t appearance = htole16(CONFIG_DEVICE_APPEARANCE); + + return bt_gatt_attr_read(conn, attr, buf, len, offset, &appearance, + sizeof(appearance)); +} + +/**************************************************************************** + * Name: bt_add_services + * + * Description: + * Register services and start advertising. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero in case of success or negative value in case of error. + * + ****************************************************************************/ + +int bt_add_services(void) +{ + int err; + + bt_gatt_register(g_attrs, nitems(g_attrs)); + + err = bt_start_advertising(BT_LE_ADV_IND, g_ad, g_sd); + if (err) + { + wlerr("Advertising failed to start (err %d)\n", err); + } + + return err; +}