From abb79e4fb5208ae93daff71c04d08b311053b571 Mon Sep 17 00:00:00 2001 From: Chinmay Chhajed Date: Wed, 3 Jun 2020 21:44:27 +0530 Subject: [PATCH] Bluetooth HCI common components. Separate Bluetooth HCI component example which adds some macros and functions used by HCI Layer defined by the spec. --- examples/bluetooth/hci/README.md | 4 + .../controller_vhci_ble_adv/CMakeLists.txt | 3 + .../hci/controller_vhci_ble_adv/Makefile | 2 + .../hci/controller_vhci_ble_adv/main/app_bt.c | 90 +-------------- .../hci/hci_common_component/CMakeLists.txt | 3 + .../hci/hci_common_component/bt_hci_common.c | 70 ++++++++++++ .../hci/hci_common_component/component.mk | 0 .../include/bt_hci_common.h | 104 ++++++++++++++++++ 8 files changed, 187 insertions(+), 89 deletions(-) create mode 100644 examples/bluetooth/hci/hci_common_component/CMakeLists.txt create mode 100644 examples/bluetooth/hci/hci_common_component/bt_hci_common.c create mode 100644 examples/bluetooth/hci/hci_common_component/component.mk create mode 100644 examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h diff --git a/examples/bluetooth/hci/README.md b/examples/bluetooth/hci/README.md index 41be804912..69b45e50db 100644 --- a/examples/bluetooth/hci/README.md +++ b/examples/bluetooth/hci/README.md @@ -17,3 +17,7 @@ See the [README.md](./controller_hci_uart/README.md) file in the example [contro Demonstrates interaction with controller though virtual HCI layer. In this example, simple BLE advertising is done. See the [README.md](./controller_vhci_ble_adv/README.md) file in the example [controller_vhci_ble_adv](./controller_vhci_ble_adv). + +## hci_common_component + +This is separate component adding functionalities for HCI Layer. Since this component is just used by HCI examples, it is not placed in global components. diff --git a/examples/bluetooth/hci/controller_vhci_ble_adv/CMakeLists.txt b/examples/bluetooth/hci/controller_vhci_ble_adv/CMakeLists.txt index 22b94847f6..b79bd7193f 100644 --- a/examples/bluetooth/hci/controller_vhci_ble_adv/CMakeLists.txt +++ b/examples/bluetooth/hci/controller_vhci_ble_adv/CMakeLists.txt @@ -2,5 +2,8 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +# This example uses an extra component for common functions for Bluetooth HCI layer. +set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/bluetooth/hci/hci_common_component) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ble_adv) diff --git a/examples/bluetooth/hci/controller_vhci_ble_adv/Makefile b/examples/bluetooth/hci/controller_vhci_ble_adv/Makefile index 2319786d4a..03317f7da4 100644 --- a/examples/bluetooth/hci/controller_vhci_ble_adv/Makefile +++ b/examples/bluetooth/hci/controller_vhci_ble_adv/Makefile @@ -5,4 +5,6 @@ PROJECT_NAME := ble_adv +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/bluetooth/hci/hci_common_component + include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/hci/controller_vhci_ble_adv/main/app_bt.c b/examples/bluetooth/hci/controller_vhci_ble_adv/main/app_bt.c index 09f78064cf..36fb8bb0d7 100644 --- a/examples/bluetooth/hci/controller_vhci_ble_adv/main/app_bt.c +++ b/examples/bluetooth/hci/controller_vhci_ble_adv/main/app_bt.c @@ -13,39 +13,10 @@ #include "esp_bt.h" #include "esp_log.h" #include "nvs_flash.h" +#include "bt_hci_common.h" static const char *tag = "BLE_ADV"; -#define HCI_H4_CMD_PREAMBLE_SIZE (4) - -/* HCI Command opcode group field(OGF) */ -#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ -#define HCI_GRP_BLE_CMDS (0x08 << 10) - -#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) -#define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS) -#define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS) -#define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS) - -#define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE (1) -#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS (15) -#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA (31) - -#define BD_ADDR_LEN (6) /* Device address length */ -typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ - -#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} -#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);} -#define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} -#define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} - -enum { - H4_TYPE_COMMAND = 1, - H4_TYPE_ACL = 2, - H4_TYPE_SCO = 3, - H4_TYPE_EVENT = 4 -}; - static uint8_t hci_cmd_buf[128]; /* @@ -75,65 +46,6 @@ static esp_vhci_host_callback_t vhci_host_cb = { controller_rcv_pkt_ready, host_rcv_pkt }; - -static uint16_t make_cmd_reset(uint8_t *buf) -{ - UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); - UINT16_TO_STREAM (buf, HCI_RESET); - UINT8_TO_STREAM (buf, 0); - return HCI_H4_CMD_PREAMBLE_SIZE; -} - -static uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable) -{ - UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); - UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_ENABLE); - UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE); - UINT8_TO_STREAM (buf, adv_enable); - return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_ADV_ENABLE; -} - -static uint16_t make_cmd_ble_set_adv_param (uint8_t *buf, uint16_t adv_int_min, uint16_t adv_int_max, - uint8_t adv_type, uint8_t addr_type_own, - uint8_t addr_type_dir, bd_addr_t direct_bda, - uint8_t channel_map, uint8_t adv_filter_policy) -{ - UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); - UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_PARAMS); - UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS ); - - UINT16_TO_STREAM (buf, adv_int_min); - UINT16_TO_STREAM (buf, adv_int_max); - UINT8_TO_STREAM (buf, adv_type); - UINT8_TO_STREAM (buf, addr_type_own); - UINT8_TO_STREAM (buf, addr_type_dir); - BDADDR_TO_STREAM (buf, direct_bda); - UINT8_TO_STREAM (buf, channel_map); - UINT8_TO_STREAM (buf, adv_filter_policy); - return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS; -} - - -static uint16_t make_cmd_ble_set_adv_data(uint8_t *buf, uint8_t data_len, uint8_t *p_data) -{ - UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); - UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_DATA); - UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); - - memset(buf, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA); - - if (p_data != NULL && data_len > 0) { - if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA) { - data_len = HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA; - } - - UINT8_TO_STREAM (buf, data_len); - - ARRAY_TO_STREAM (buf, p_data, data_len); - } - return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1; -} - static void hci_cmd_send_reset(void) { uint16_t sz = make_cmd_reset (hci_cmd_buf); diff --git a/examples/bluetooth/hci/hci_common_component/CMakeLists.txt b/examples/bluetooth/hci/hci_common_component/CMakeLists.txt new file mode 100644 index 0000000000..36a0e78f5a --- /dev/null +++ b/examples/bluetooth/hci/hci_common_component/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "bt_hci_common.c" + INCLUDE_DIRS "include" + ) diff --git a/examples/bluetooth/hci/hci_common_component/bt_hci_common.c b/examples/bluetooth/hci/hci_common_component/bt_hci_common.c new file mode 100644 index 0000000000..5a1cc53ef0 --- /dev/null +++ b/examples/bluetooth/hci/hci_common_component/bt_hci_common.c @@ -0,0 +1,70 @@ +/* Basic functionality for Bluetooth Host Controller Interface Layer. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "bt_hci_common.h" + + +uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_ENABLE); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_WRITE_ADV_ENABLE); + UINT8_TO_STREAM (buf, adv_enable); + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_ADV_ENABLE; +} + +uint16_t make_cmd_ble_set_adv_param (uint8_t *buf, uint16_t adv_int_min, uint16_t adv_int_max, + uint8_t adv_type, uint8_t addr_type_own, + uint8_t addr_type_dir, bd_addr_t direct_bda, + uint8_t channel_map, uint8_t adv_filter_policy) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_PARAMS); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS ); + + UINT16_TO_STREAM (buf, adv_int_min); + UINT16_TO_STREAM (buf, adv_int_max); + UINT8_TO_STREAM (buf, adv_type); + UINT8_TO_STREAM (buf, addr_type_own); + UINT8_TO_STREAM (buf, addr_type_dir); + BDADDR_TO_STREAM (buf, direct_bda); + UINT8_TO_STREAM (buf, channel_map); + UINT8_TO_STREAM (buf, adv_filter_policy); + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS; +} + +uint16_t make_cmd_reset(uint8_t *buf) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_RESET); + UINT8_TO_STREAM (buf, 0); + return HCI_H4_CMD_PREAMBLE_SIZE; +} + + + +uint16_t make_cmd_ble_set_adv_data(uint8_t *buf, uint8_t data_len, uint8_t *p_data) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_BLE_WRITE_ADV_DATA); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1); + + memset(buf, 0, HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA); + + if (p_data != NULL && data_len > 0) { + if (data_len > HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA) { + data_len = HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA; + } + + UINT8_TO_STREAM (buf, data_len); + + ARRAY_TO_STREAM (buf, p_data, data_len); + } + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1; +} diff --git a/examples/bluetooth/hci/hci_common_component/component.mk b/examples/bluetooth/hci/hci_common_component/component.mk new file mode 100644 index 0000000000..e69de29bb2 diff --git a/examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h b/examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h new file mode 100644 index 0000000000..684d756bbe --- /dev/null +++ b/examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h @@ -0,0 +1,104 @@ +/* Baisc macros and functions for Bluetooth Host Controller Interface Layer. + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stdio.h" +#include "string.h" + +#define HCI_H4_CMD_PREAMBLE_SIZE (4) + +/* HCI Command Opcode group Field (OGF) */ +#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10) /* 0x0C00 */ +#define HCI_GRP_BLE_CMDS (0x08 << 10) + +/* HCI Command Opcode Command Field (OCF) */ +#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) +#define HCI_BLE_WRITE_ADV_ENABLE (0x000A | HCI_GRP_BLE_CMDS) +#define HCI_BLE_WRITE_ADV_DATA (0x0008 | HCI_GRP_BLE_CMDS) +#define HCI_BLE_WRITE_ADV_PARAMS (0x0006 | HCI_GRP_BLE_CMDS) + +/* HCI Command length. */ +#define HCIC_PARAM_SIZE_WRITE_ADV_ENABLE 1 +#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS 15 +#define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA 31 + +#define BD_ADDR_LEN (6) /* Device address length */ +typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ + +#define UINT16_TO_STREAM(p, u16) {*(p)++ = (uint8_t)(u16); *(p)++ = (uint8_t)((u16) >> 8);} +#define UINT8_TO_STREAM(p, u8) {*(p)++ = (uint8_t)(u8);} +#define BDADDR_TO_STREAM(p, a) {int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (uint8_t) a[BD_ADDR_LEN - 1 - ijk];} +#define ARRAY_TO_STREAM(p, a, len) {int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (uint8_t) a[ijk];} + +enum { + H4_TYPE_COMMAND = 1, + H4_TYPE_ACL = 2, + H4_TYPE_SCO = 3, + H4_TYPE_EVENT = 4 +}; + +/** + * @brief Writes reset bit in buf and returns size of input buffer after + * writing in it. + * + * @param buf Input buffer to write which will be sent to controller. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_reset(uint8_t *buf); + +/** + * @brief This function is used to request the Controller to start or stop advertising. + * + * @param buf Input buffer to write which will be sent to controller. + * @param adv_enable 1 to enable advertising and 0 to disable. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable); + +/** + * @brief This function is used by the Host to set the advertising parameters. + * + * @param buf Input buffer to write which will be sent to controller. + * @param adv_int_min Minimum advertising interval. + * @param adv_int_max Maximum advertising interval. + * @param adv_type Advertising type. + * @param addr_type_own Own advertising type. + * @param addr_type_peer Peer device's address type. + * @param peer_addr Peer device's BD address. + * @param channel_map Advertising channel map. + * @param adv_filter_policy Advertising Filter Policy. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_ble_set_adv_param (uint8_t *buf, uint16_t adv_int_min, uint16_t adv_int_max, + uint8_t adv_type, uint8_t addr_type_own, + uint8_t addr_type_peer, bd_addr_t peer_addr, + uint8_t channel_map, uint8_t adv_filter_policy); + +/** + * @brief This function is used to set the data used in advertising packets that have a data field. + * + * @param buf Input buffer to write which will be sent to controller. + * @param data_len Length of p_data. + * @param p_data Data to be set. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_ble_set_adv_data(uint8_t *buf, uint8_t data_len, uint8_t *p_data); + +#ifdef __cplusplus +} +#endif