From abb79e4fb5208ae93daff71c04d08b311053b571 Mon Sep 17 00:00:00 2001 From: Chinmay Chhajed Date: Wed, 3 Jun 2020 21:44:27 +0530 Subject: [PATCH 1/2] 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 From 6dbb993071b962f156aadb85e8e6680a74e1fa33 Mon Sep 17 00:00:00 2001 From: Chinmay Chhajed Date: Tue, 12 Nov 2019 11:31:17 +0530 Subject: [PATCH 2/2] bluetooth: Added HCI example for combined scanning and advertising. --- examples/bluetooth/hci/README.md | 7 + .../hci/ble_adv_scan_combined/CMakeLists.txt | 9 + .../hci/ble_adv_scan_combined/Makefile | 10 + .../hci/ble_adv_scan_combined/README.md | 9 + .../ble_adv_scan_combined/main/CMakeLists.txt | 2 + .../hci/ble_adv_scan_combined/main/app_bt.c | 446 ++++++++++++++++++ .../ble_adv_scan_combined/main/component.mk | 4 + .../ble_adv_scan_combined/sdkconfig.defaults | 12 + .../hci/hci_common_component/bt_hci_common.c | 40 +- .../include/bt_hci_common.h | 65 ++- 10 files changed, 594 insertions(+), 10 deletions(-) create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/CMakeLists.txt create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/Makefile create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/README.md create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/main/CMakeLists.txt create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/main/component.mk create mode 100644 examples/bluetooth/hci/ble_adv_scan_combined/sdkconfig.defaults diff --git a/examples/bluetooth/hci/README.md b/examples/bluetooth/hci/README.md index 69b45e50db..96852fd688 100644 --- a/examples/bluetooth/hci/README.md +++ b/examples/bluetooth/hci/README.md @@ -18,6 +18,13 @@ Demonstrates interaction with controller though virtual HCI layer. In this examp See the [README.md](./controller_vhci_ble_adv/README.md) file in the example [controller_vhci_ble_adv](./controller_vhci_ble_adv). +## ble_adv_scan_combined + +Demonstrates interaction with controller. In this example, BLE advertising and scanning is done. Also scanned advertising reports are parsed and displayed. + +See the [README.md](./ble_adv_scan_combined/README.md) file in the example [ble_adv_scan_combined](./ble_adv_scan_combined). + + ## 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/ble_adv_scan_combined/CMakeLists.txt b/examples/bluetooth/hci/ble_adv_scan_combined/CMakeLists.txt new file mode 100644 index 0000000000..35b5d877e2 --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/CMakeLists.txt @@ -0,0 +1,9 @@ +# The following lines of boilerplate have to be in your project's +# 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_scan) diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/Makefile b/examples/bluetooth/hci/ble_adv_scan_combined/Makefile new file mode 100644 index 0000000000..6da01365d7 --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/Makefile @@ -0,0 +1,10 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := ble_adv_scan + +EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/bluetooth/hci/hci_common_component + +include $(IDF_PATH)/make/project.mk diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/README.md b/examples/bluetooth/hci/ble_adv_scan_combined/README.md new file mode 100644 index 0000000000..cbbcadd91a --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/README.md @@ -0,0 +1,9 @@ +| Supported Targets | ESP32 | +| ----------------- | ----- | + +ESP-IDF Combined Bluetooth advertising and scanning +=================================================== + +This is a Bluetooth advertising and scanning demo with virtual HCI interface. Send Reset, ADV_PARAM, ADV_DATA and HCI_ADV_ENABLE command for BLE advertising. And SET_EVENT_MASK, SCAN_PARAMS and SCAN_START commands for BLE scanning. Scanned advertising reports from other devices are also displayed. + +In this example no host is used. But some of the functionalities of a host are implemented. diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/main/CMakeLists.txt b/examples/bluetooth/hci/ble_adv_scan_combined/main/CMakeLists.txt new file mode 100644 index 0000000000..494d32308b --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "app_bt.c" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c new file mode 100644 index 0000000000..4112523b32 --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/main/app_bt.c @@ -0,0 +1,446 @@ +/* BLE Combined Advertising and Scanning Example. + + 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 +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_bt.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "freertos/queue.h" +#include "bt_hci_common.h" + +static const char *TAG = "BLE_ADV_SCAN"; + +typedef struct { + char scan_local_name[32]; + uint8_t name_len; +} ble_scan_local_name_t; + +typedef struct { + uint8_t *q_data; + uint16_t q_data_len; +} host_rcv_data_t; + +static uint8_t hci_cmd_buf[128]; + +static uint16_t scanned_count = 0; +static QueueHandle_t adv_queue; + +static void periodic_timer_callback(void *arg) +{ + ESP_LOGI(TAG, "Number of received advertising reports: %d", scanned_count); +} + +/* + * @brief: BT controller callback function, used to notify the upper layer that + * controller is ready to receive command + */ +static void controller_rcv_pkt_ready(void) +{ + ESP_LOGI(TAG, "controller rcv pkt ready"); +} + +/* + * @brief: BT controller callback function to transfer data packet to + * the host + */ +static int host_rcv_pkt(uint8_t *data, uint16_t len) +{ + host_rcv_data_t send_data; + uint8_t *data_pkt; + /* Check second byte for HCI event. If event opcode is 0x0e, the event is + * HCI Command Complete event. Sice we have recieved "0x0e" event, we can + * check for byte 4 for command opcode and byte 6 for it's return status. */ + if (data[1] == 0x0e) { + if (data[6] == 0) { + ESP_LOGI(TAG, "Event opcode 0x%02x success.", data[4]); + } else { + ESP_LOGE(TAG, "Event opcode 0x%02x fail with reason: 0x%02x.", data[4], data[6]); + return ESP_FAIL; + } + } + + data_pkt = (uint8_t *)malloc(sizeof(uint8_t) * len); + if (data_pkt == NULL) { + ESP_LOGE(TAG, "Malloc data_pkt failed!"); + return ESP_FAIL; + } + memcpy(data_pkt, data, len); + send_data.q_data = data_pkt; + send_data.q_data_len = len; + if (xQueueSend(adv_queue, (void *)&send_data, ( TickType_t ) 0) != pdTRUE) { + ESP_LOGD(TAG, "Failed to enqueue advertising report. Queue full."); + /* If data sent successfully, then free the pointer in `xQueueReceive' + * after processing it. Or else if enqueue in not successful, free it + * here. */ + free(data_pkt); + } + return ESP_OK; +} + +static esp_vhci_host_callback_t vhci_host_cb = { + controller_rcv_pkt_ready, + host_rcv_pkt +}; + +static void hci_cmd_send_reset(void) +{ + uint16_t sz = make_cmd_reset (hci_cmd_buf); + esp_vhci_host_send_packet(hci_cmd_buf, sz); +} + +static void hci_cmd_send_set_evt_mask(void) +{ + /* Set bit 61 in event mask to enable LE Meta events. */ + uint8_t evt_mask[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20}; + uint16_t sz = make_cmd_set_evt_mask(hci_cmd_buf, evt_mask); + esp_vhci_host_send_packet(hci_cmd_buf, sz); +} + +static void hci_cmd_send_ble_scan_params(void) +{ + /* Set scan type to 0x01 for active scanning and 0x00 for passive scanning. */ + uint8_t scan_type = 0x01; + + /* Scan window and Scan interval are set in terms of number of slots. Each slot is of 625 microseconds. */ + uint16_t scan_interval = 0x50; /* 50 ms */ + uint16_t scan_window = 0x30; /* 30 ms */ + + uint8_t own_addr_type = 0x00; /* Public Device Address (default). */ + uint8_t filter_policy = 0x00; /* Accept all packets excpet directed advertising packets (default). */ + uint16_t sz = make_cmd_ble_set_scan_params(hci_cmd_buf, scan_type, scan_interval, scan_window, own_addr_type, filter_policy); + esp_vhci_host_send_packet(hci_cmd_buf, sz); +} + +static void hci_cmd_send_ble_scan_start(void) +{ + uint8_t scan_enable = 0x01; /* Scanning enabled. */ + uint8_t filter_duplicates = 0x00; /* Duplicate filtering disabled. */ + uint16_t sz = make_cmd_ble_set_scan_enable(hci_cmd_buf, scan_enable, filter_duplicates); + esp_vhci_host_send_packet(hci_cmd_buf, sz); + ESP_LOGI(TAG, "BLE Scanning started.."); +} + +static void hci_cmd_send_ble_adv_start(void) +{ + uint16_t sz = make_cmd_ble_set_adv_enable (hci_cmd_buf, 1); + esp_vhci_host_send_packet(hci_cmd_buf, sz); + ESP_LOGI(TAG, "BLE Advertising started.."); +} + +static void hci_cmd_send_ble_set_adv_param(void) +{ + /* Minimum and maximum Advertising interval are set in terms of slots. Each slot is of 625 microseconds. */ + uint16_t adv_intv_min = 0x100; + uint16_t adv_intv_max = 0x100; + + /* Connectable undirected advertising (ADV_IND). */ + uint8_t adv_type = 0; + + /* Own address is public address. */ + uint8_t own_addr_type = 0; + + /* Public Device Address */ + uint8_t peer_addr_type = 0; + uint8_t peer_addr[6] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85}; + + /* Channel 37, 38 and 39 for advertising. */ + uint8_t adv_chn_map = 0x07; + + /* Process scan and connection requests from all devices (i.e., the White List is not in use). */ + uint8_t adv_filter_policy = 0; + + uint16_t sz = make_cmd_ble_set_adv_param(hci_cmd_buf, + adv_intv_min, + adv_intv_max, + adv_type, + own_addr_type, + peer_addr_type, + peer_addr, + adv_chn_map, + adv_filter_policy); + esp_vhci_host_send_packet(hci_cmd_buf, sz); +} + +static void hci_cmd_send_ble_set_adv_data(void) +{ + char *adv_name = "ESP-BLE-1"; + uint8_t name_len = (uint8_t)strlen(adv_name); + uint8_t adv_data[31] = {0x02, 0x01, 0x06, 0x0, 0x09}; + uint8_t adv_data_len; + + adv_data[3] = name_len + 1; + for (int i = 0; i < name_len; i++) { + adv_data[5 + i] = (uint8_t)adv_name[i]; + } + adv_data_len = 5 + name_len; + + uint16_t sz = make_cmd_ble_set_adv_data(hci_cmd_buf, adv_data_len, (uint8_t *)adv_data); + esp_vhci_host_send_packet(hci_cmd_buf, sz); + ESP_LOGI(TAG, "Starting BLE advertising with name \"%s\"", adv_name); +} + +static esp_err_t get_local_name (uint8_t *data_msg, uint8_t data_len, ble_scan_local_name_t *scanned_packet) +{ + uint8_t curr_ptr = 0, curr_len, curr_type; + while (curr_ptr < data_len) { + curr_len = data_msg[curr_ptr++]; + curr_type = data_msg[curr_ptr++]; + if (curr_len == 0) { + return ESP_FAIL; + } + + /* Search for current data type and see if it contains name as data (0x08 or 0x09). */ + if (curr_type == 0x08 || curr_type == 0x09) { + for (uint8_t i = 0; i < curr_len - 1; i += 1) { + scanned_packet->scan_local_name[i] = data_msg[curr_ptr + i]; + } + scanned_packet->name_len = curr_len - 1; + return ESP_OK; + } else { + /* Search for next data. Current length includes 1 octate for AD Type (2nd octate). */ + curr_ptr += curr_len - 1; + } + } + return ESP_FAIL; +} + +void hci_evt_process(void *pvParameters) +{ + host_rcv_data_t *rcv_data = (host_rcv_data_t *)malloc(sizeof(host_rcv_data_t)); + if (rcv_data == NULL) { + ESP_LOGE(TAG, "Malloc rcv_data failed!"); + return; + } + esp_err_t ret; + + while (1) { + uint8_t sub_event, num_responses, total_data_len, data_msg_ptr, hci_event_opcode; + uint8_t *queue_data = NULL, *event_type = NULL, *addr_type = NULL, *addr = NULL, *data_len = NULL, *data_msg = NULL; + short int *rssi = NULL; + uint16_t data_ptr; + ble_scan_local_name_t *scanned_name = NULL; + total_data_len = 0; + data_msg_ptr = 0; + if (xQueueReceive(adv_queue, rcv_data, portMAX_DELAY) != pdPASS) { + ESP_LOGE(TAG, "Queue receive error"); + } else { + /* `data_ptr' keeps track of current position in the received data. */ + data_ptr = 0; + queue_data = rcv_data->q_data; + + /* Parsing `data' and copying in various fields. */ + hci_event_opcode = queue_data[++data_ptr]; + if (hci_event_opcode == LE_META_EVENTS) { + /* Set `data_ptr' to 4th entry, which will point to sub event. */ + data_ptr += 2; + sub_event = queue_data[data_ptr++]; + /* Check if sub event is LE advertising report event. */ + if (sub_event == HCI_LE_ADV_REPORT) { + + scanned_count += 1; + + /* Get number of advertising reports. */ + num_responses = queue_data[data_ptr++]; + event_type = (uint8_t *)malloc(sizeof(uint8_t) * num_responses); + if (event_type == NULL) { + ESP_LOGE(TAG, "Malloc event_type failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + event_type[i] = queue_data[data_ptr++]; + } + + /* Get advertising type for every report. */ + addr_type = (uint8_t *)malloc(sizeof(uint8_t) * num_responses); + if (addr_type == NULL) { + ESP_LOGE(TAG, "Malloc addr_type failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + addr_type[i] = queue_data[data_ptr++]; + } + + /* Get BD address in every advetising report and store in + * single array of length `6 * num_responses' as each address + * will take 6 spaces. */ + addr = (uint8_t *)malloc(sizeof(uint8_t) * 6 * num_responses); + if (addr == NULL) { + ESP_LOGE(TAG, "Malloc addr failed!"); + goto reset; + } + for (int i = 0; i < num_responses; i += 1) { + for (int j = 0; j < 6; j += 1) { + addr[(6 * i) + j] = queue_data[data_ptr++]; + } + } + + /* Get length of data for each advertising report. */ + data_len = (uint8_t *)malloc(sizeof(uint8_t) * num_responses); + if (data_len == NULL) { + ESP_LOGE(TAG, "Malloc data_len failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + data_len[i] = queue_data[data_ptr]; + total_data_len += queue_data[data_ptr++]; + } + + if (total_data_len != 0) { + /* Get all data packets. */ + data_msg = (uint8_t *)malloc(sizeof(uint8_t) * total_data_len); + if (data_msg == NULL) { + ESP_LOGE(TAG, "Malloc data_msg failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + for (uint8_t j = 0; j < data_len[i]; j += 1) { + data_msg[data_msg_ptr++] = queue_data[data_ptr++]; + } + } + } + + /* Counts of advertisements done. This count is set in advertising data every time before advertising. */ + rssi = (short int *)malloc(sizeof(short int) * num_responses); + if (data_len == NULL) { + ESP_LOGE(TAG, "Malloc rssi failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + rssi[i] = -(0xFF - queue_data[data_ptr++]); + } + + /* Extracting advertiser's name. */ + data_msg_ptr = 0; + scanned_name = (ble_scan_local_name_t *)malloc(num_responses * sizeof(ble_scan_local_name_t)); + if (data_len == NULL) { + ESP_LOGE(TAG, "Malloc scanned_name failed!"); + goto reset; + } + for (uint8_t i = 0; i < num_responses; i += 1) { + ret = get_local_name(&data_msg[data_msg_ptr], data_len[i], scanned_name); + + /* Print the data if adv report has a valid name. */ + if (ret == ESP_OK) { + printf("******** Response %d/%d ********\n", i + 1, num_responses); + printf("Event type: %02x\nAddress type: %02x\nAddress: ", event_type[i], addr_type[i]); + for (int j = 5; j >= 0; j -= 1) { + printf("%02x", addr[(6 * i) + j]); + if (j > 0) { + printf(":"); + } + } + + printf("\nData length: %d", data_len[i]); + data_msg_ptr += data_len[i]; + printf("\nAdvertisement Name: "); + for (int k = 0; k < scanned_name->name_len; k += 1 ) { + printf("%c", scanned_name->scan_local_name[k]); + } + printf("\nRSSI: %ddB\n", rssi[i]); + } + } + + /* Freeing all spaces allocated. */ +reset: + free(scanned_name); + free(rssi); + free(data_msg); + free(data_len); + free(addr); + free(addr_type); + free(event_type); + } + } +#if (CONFIG_LOG_DEFAULT_LEVEL_DEBUG || CONFIG_LOG_DEFAULT_LEVEL_VERBOSE) + printf("Raw Data:"); + for (uint8_t j = 0; j < rcv_data->q_data_len; j += 1) { + printf(" %02x", queue_data[j]); + } + printf("\nQueue free size: %d\n", uxQueueSpacesAvailable(adv_queue)); +#endif + free(queue_data); + } + memset(rcv_data, 0, sizeof(host_rcv_data_t)); + } +} + +void app_main(void) +{ + bool continue_commands = 1; + int cmd_cnt = 0; + + const esp_timer_create_args_t periodic_timer_args = { + .callback = &periodic_timer_callback, + .name = "periodic" + }; + + /* Create timer for logging scanned devices. */ + esp_timer_handle_t periodic_timer; + ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer)); + + /* Start periodic timer for 5 sec. */ + ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, 5000000)); + + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + + ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); + if (ret) { + ESP_LOGI(TAG, "Bluetooth controller release classic bt memory failed: %s", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + ESP_LOGI(TAG, "Bluetooth controller initialize failed: %s", esp_err_to_name(ret)); + return; + } + + if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) { + ESP_LOGI(TAG, "Bluetooth controller enable failed: %s", esp_err_to_name(ret)); + return; + } + + /* A queue for storing received HCI packets. */ + adv_queue = xQueueCreate(15, sizeof(host_rcv_data_t)); + if (adv_queue == NULL) { + ESP_LOGE(TAG, "Queue creation failed\n"); + return; + } + + esp_vhci_host_register_callback(&vhci_host_cb); + while (continue_commands) { + if (continue_commands && esp_vhci_host_check_send_available()) { + switch (cmd_cnt) { + case 0: hci_cmd_send_reset(); ++cmd_cnt; break; + case 1: hci_cmd_send_set_evt_mask(); ++cmd_cnt; break; + + /* Send advertising commands. */ + case 2: hci_cmd_send_ble_set_adv_param(); ++cmd_cnt; break; + case 3: hci_cmd_send_ble_set_adv_data(); ++cmd_cnt; break; + case 4: hci_cmd_send_ble_adv_start(); ++cmd_cnt; break; + + /* Send scan commands. */ + case 5: hci_cmd_send_ble_scan_params(); ++cmd_cnt; break; + case 6: hci_cmd_send_ble_scan_start(); ++cmd_cnt; break; + default: continue_commands = 0; break; + } + ESP_LOGI(TAG, "BLE Advertise, cmd_sent: %d", cmd_cnt); + } + vTaskDelay(1000 / portTICK_RATE_MS); + } + xTaskCreatePinnedToCore(&hci_evt_process, "hci_evt_process", 2048, NULL, 6, NULL, 0); +} diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/main/component.mk b/examples/bluetooth/hci/ble_adv_scan_combined/main/component.mk new file mode 100644 index 0000000000..a98f634eae --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/bluetooth/hci/ble_adv_scan_combined/sdkconfig.defaults b/examples/bluetooth/hci/ble_adv_scan_combined/sdkconfig.defaults new file mode 100644 index 0000000000..3b0474335e --- /dev/null +++ b/examples/bluetooth/hci/ble_adv_scan_combined/sdkconfig.defaults @@ -0,0 +1,12 @@ +# Override some defaults so BT stack is enabled +# in this example + +# +# BT config +# +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n +CONFIG_BTDM_CTRL_MODE_BTDM=n +CONFIG_BT_BLUEDROID_ENABLED=n +CONFIG_BT_CONTROLLER_ONLY=y diff --git a/examples/bluetooth/hci/hci_common_component/bt_hci_common.c b/examples/bluetooth/hci/hci_common_component/bt_hci_common.c index 5a1cc53ef0..4284460901 100644 --- a/examples/bluetooth/hci/hci_common_component/bt_hci_common.c +++ b/examples/bluetooth/hci/hci_common_component/bt_hci_common.c @@ -9,6 +9,40 @@ #include "bt_hci_common.h" +uint16_t make_cmd_set_evt_mask (uint8_t *buf, uint8_t *evt_mask) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_SET_EVT_MASK); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_SET_EVENT_MASK); + ARRAY_TO_STREAM(buf, evt_mask, HCIC_PARAM_SIZE_SET_EVENT_MASK); + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_SET_EVENT_MASK; +} + +uint16_t make_cmd_ble_set_scan_enable (uint8_t *buf, uint8_t scan_enable, + uint8_t filter_duplicates) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_BLE_WRITE_SCAN_ENABLE); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE); + UINT8_TO_STREAM (buf, scan_enable); + UINT8_TO_STREAM (buf, filter_duplicates); + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE; +} + +uint16_t make_cmd_ble_set_scan_params (uint8_t *buf, uint8_t scan_type, + uint16_t scan_interval, uint16_t scan_window, + uint8_t own_addr_type, uint8_t filter_policy) +{ + UINT8_TO_STREAM (buf, H4_TYPE_COMMAND); + UINT16_TO_STREAM (buf, HCI_BLE_WRITE_SCAN_PARAM); + UINT8_TO_STREAM (buf, HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM); + UINT8_TO_STREAM (buf, scan_type); + UINT16_TO_STREAM (buf, scan_interval); + UINT16_TO_STREAM (buf, scan_window); + UINT8_TO_STREAM (buf, own_addr_type); + UINT8_TO_STREAM (buf, filter_policy); + return HCI_H4_CMD_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM; +} uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable) { @@ -20,9 +54,9 @@ uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t 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_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); 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 index 684d756bbe..c78264d7a0 100644 --- a/examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h +++ b/examples/bluetooth/hci/hci_common_component/include/bt_hci_common.h @@ -24,14 +24,26 @@ extern "C" { /* HCI Command Opcode Command Field (OCF) */ #define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) +#define HCI_SET_EVT_MASK (0x0001 | HCI_GRP_HOST_CONT_BASEBAND_CMDS) +/* Advertising Commands. */ #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) +/* Scan commands */ +#define HCI_BLE_WRITE_SCAN_PARAM (0x000B | HCI_GRP_BLE_CMDS) +#define HCI_BLE_WRITE_SCAN_ENABLE (0x000C | 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 HCIC_PARAM_SIZE_SET_EVENT_MASK (8) +#define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_PARAM (7) +#define HCIC_PARAM_SIZE_BLE_WRITE_SCAN_ENABLE (2) + +/* LE Meta Events. */ +#define LE_META_EVENTS (0x3E) +#define HCI_LE_ADV_REPORT (0x02) #define BD_ADDR_LEN (6) /* Device address length */ typedef uint8_t bd_addr_t[BD_ADDR_LEN]; /* Device address */ @@ -84,21 +96,60 @@ uint16_t make_cmd_ble_set_adv_enable (uint8_t *buf, uint8_t adv_enable); * @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); + 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. + * @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. + * @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); +/** + * @brief This function is used to control which LE events are generated by the HCI for the Host. + * The event mask allows the Host to control which events will interrupt it. + * + * @param buf Input buffer to write which will be sent to controller. + * @param evt_mask 8 byte data as per spec. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_set_evt_mask (uint8_t *buf, uint8_t *evt_mask); + +/** + * @brief This function is used to set the scan parameters. + * + * @param buf Input buffer to write which will be sent to controller. + * @param scan_type Active or Passive scanning. + * @param scan_interval Set scan_interval. + * @param scan_window Set scan_window. + * @param own_addr_type Set own address type. + * @param filter_policy Scanning filter policy. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_ble_set_scan_params (uint8_t *buf, uint8_t scan_type, + uint16_t scan_interval, uint16_t scan_window, uint8_t own_addr_type, + uint8_t 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 scan_enable Enable or disable scanning. + * @param filter_duplicates Filter duplicates enable or disable. + * + * @return Size of buf after writing into it. + */ +uint16_t make_cmd_ble_set_scan_enable (uint8_t *buf, uint8_t scan_enable, + uint8_t filter_duplicates); + #ifdef __cplusplus } #endif